Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"karma-sauce-launcher": "^4.3.6",
"karma-sourcemap-loader": "~0.4.0",
"karma-webpack": "^5.0.0",
"mocha": "^10.2.0",
"mocha": "^10.8.2",
"null-loader": "^4.0.1",
"nyc": "^15.1.0",
"prettier": "^3.1.0",
Expand All @@ -112,12 +112,12 @@
"@babel/runtime": "^7.23.2",
"@types/jsonwebtoken": "^9.0.5",
"@types/qs": "^6.9.10",
"axios": "0.x",
"axios": "0.29.0",
"faye": "^1.4.0",
"follow-redirects": "1.15.6",
"form-data": "^4.0.0",
"jsonwebtoken": "^9.0.2",
"jwt-decode": "^4.0.0",
"jwt-decode": "4.0.0",
"qs": "^6.10.2"
},
"peerDependencies": {
Expand Down
71 changes: 71 additions & 0 deletions src/audit_logs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { StreamClient, APIResponse, UR, DefaultGenerics } from './client';
import { SiteError } from './errors';

export type AuditLog = {
action: string;
created_at: string;
entity_id: string;
entity_type: string;
user_id: string;
custom?: UR;
};

export type AuditLogAPIResponse = APIResponse & AuditLog;

export type AuditLogFilterAPIResponse = APIResponse & {
audit_logs: AuditLogAPIResponse[];
next: string;
prev: string;
};

export type AuditLogFilterConditions = {
entity_id?: string;
entity_type?: string;
limit?: number;
next?: string;
prev?: string;
user_id?: string;
};

export class StreamAuditLogs<StreamFeedGenerics extends DefaultGenerics = DefaultGenerics> {
client: StreamClient<StreamFeedGenerics>;
token: string;

/**
* Initialize an audit logs object
* @link https://getstream.io/activity-feeds/docs/node/audit_logs/?language=js
* @method constructor
* @memberof StreamAuditLogs.prototype
* @param {StreamClient} client Stream client this feed is constructed from
* @param {string} token JWT token
* @example new StreamAuditLogs(client, "eyJhbGciOiJIUzI1...")
*/
constructor(client: StreamClient<StreamFeedGenerics>, token: string) {
this.client = client;
this.token = token;
}

buildURL = (...args: string[]) => {
return `${['audit_logs', ...args].join('/')}/`;
};

/**
* Query audit logs with filters
* @link https://getstream.io/activity-feeds/docs/node/audit_logs/?language=js#query-audit-logs
* @method query
* @memberof StreamAuditLogs.prototype
* @param {AuditLogFilterConditions} conditions Filter conditions
* @return {Promise<AuditLogFilterAPIResponse>}
* @example auditLogs.query({entity_type: "feed", entity_id: "user:123"})
* @example auditLogs.query({user_id: "john", limit: 25})
*/
query(conditions: AuditLogFilterConditions) {
const { limit = 25, ...qs } = conditions;

return this.client.get<AuditLogFilterAPIResponse>({
url: this.buildURL(),
qs: { ...qs, limit },
token: this.token,
});
}
}
30 changes: 15 additions & 15 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import * as https from 'https';
import * as axios from 'axios';
import * as Faye from 'faye';
import { jwtDecode } from 'jwt-decode';
import AxiosProgressEvent from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import pkg from '../package.json';

import { Personalization } from './personalization';
import { Collections } from './collections';
Expand Down Expand Up @@ -36,6 +37,7 @@ import {
GetFeedOptions,
EnrichedActivity,
} from './feed';
import { StreamAuditLogs } from './audit_logs';

export type UR = Record<string, unknown>;
export type UnknownRecord = UR; // alias to avoid breaking change
Expand All @@ -53,7 +55,7 @@ export type APIResponse = { duration?: string };

export type FileUploadAPIResponse = APIResponse & { file: string };

export type OnUploadProgress = (progressEvent: ProgressEvent) => void;
export type OnUploadProgress = NonNullable<AxiosRequestConfig['onUploadProgress']>;

export type ClientOptions = {
browser?: boolean;
Expand Down Expand Up @@ -183,6 +185,7 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe
files: StreamFileStore;
images: StreamImageStore;
reactions: StreamReaction<StreamFeedGenerics>;
auditLogs: StreamAuditLogs<StreamFeedGenerics>;

private _personalizationToken?: string;
private _collectionsToken?: string;
Expand Down Expand Up @@ -232,12 +235,12 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe
this.enrichByDefault = !this.usingApiSecret;

if (this.userToken != null) {
const jwtBody: { user_id?: string } = jwtDecode(this.userToken);
const jwtBody = jwtDecode<{ user_id?: string }>(this.userToken);
if (!jwtBody.user_id) {
throw new TypeError('user_id is missing in user token');
}
this.userId = jwtBody.user_id;
this.currentUser = this.user(this.userId);
this.currentUser = this.user(jwtBody.user_id);
}

this.appId = appId;
Expand Down Expand Up @@ -292,7 +295,8 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe
this.collections = new Collections<StreamFeedGenerics>(this, this.getOrCreateToken());
this.files = new StreamFileStore(this as StreamClient, this.getOrCreateToken());
this.images = new StreamImageStore(this as StreamClient, this.getOrCreateToken());
this.reactions = new StreamReaction<StreamFeedGenerics>(this, this.getOrCreateToken());
this.reactions = new StreamReaction<StreamFeedGenerics>(this, this.getAnalyticsToken());
this.auditLogs = new StreamAuditLogs<StreamFeedGenerics>(this, this.getAnalyticsToken());

// If we are in a node environment and batchOperations/createRedirectUrl is available add the methods to the prototype of StreamClient
if (BatchOperations && !!createRedirectUrl && DataPrivacy) {
Expand Down Expand Up @@ -422,12 +426,8 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe
* @return {string} current user agent
*/
userAgent() {
if (process === undefined || process.env.PACKAGE_VERSION === undefined) {
// eslint-disable-next-line
return `stream-javascript-client-${this.node ? 'node' : 'browser'}-${require('../package.json').version}`;
}

return `stream-javascript-client-${this.node ? 'node' : 'browser'}-${process.env.PACKAGE_VERSION}`;
const version = typeof process !== 'undefined' && process?.env?.PACKAGE_VERSION || pkg.version;
return `stream-javascript-client-${this.node ? 'node' : 'browser'}-${version}`;
}

/**
Expand Down Expand Up @@ -669,7 +669,7 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe
return this.fayeClient;
}

handleResponse = <T>(response: axios.AxiosResponse<T>): T => {
handleResponse = <T>(response: AxiosResponse<T>): T => {
if (/^2/.test(`${response.status}`)) {
this.send('response', null, response, response.data);
return response.data;
Expand All @@ -687,10 +687,10 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe

try {
const response = await this.request(this.enrichKwargs({ method, ...options }));
return this.handleResponse(response);
return this.handleResponse<T>(response as AxiosResponse<T>);
} catch (error) {
const err = error as StreamApiError<T>;
if (err.response) return this.handleResponse(err.response);
if (err.response) return this.handleResponse<T>(err.response as AxiosResponse<T>);
throw new SiteError(err.message);
}
};
Expand All @@ -700,7 +700,7 @@ export class StreamClient<StreamFeedGenerics extends DefaultGenerics = DefaultGe
uri: string | File | Buffer | NodeJS.ReadStream,
name?: string,
contentType?: string,
onUploadProgress?: (progressEvent: typeof AxiosProgressEvent) => void,
onUploadProgress?: (progressEvent: ProgressEvent) => void,
) {
const fd = utils.addFileToFormData(uri, name, contentType);
return this.doAxiosRequest<FileUploadAPIResponse>('POST', {
Expand Down
3 changes: 1 addition & 2 deletions src/files.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import AxiosProgressEvent from 'axios';
import { StreamClient } from './client';

export class StreamFileStore {
Expand All @@ -25,7 +24,7 @@ export class StreamFileStore {
uri: string | File | Buffer | NodeJS.ReadStream,
name?: string,
contentType?: string,
onUploadProgress?: (progressEvent: typeof AxiosProgressEvent) => void,
onUploadProgress?: (progressEvent: ProgressEvent) => void,
) {
return this.client.upload('files/', uri, name, contentType, onUploadProgress);
}
Expand Down
3 changes: 1 addition & 2 deletions src/images.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import AxiosProgressEvent from 'axios';
import { StreamClient, FileUploadAPIResponse } from './client';

export type ImageProcessOptions = {
Expand Down Expand Up @@ -33,7 +32,7 @@ export class StreamImageStore {
uri: string | File | Buffer | NodeJS.ReadStream,
name?: string,
contentType?: string,
onUploadProgress?: (progressEvent: typeof AxiosProgressEvent) => void,
onUploadProgress?: (progressEvent: ProgressEvent) => void,
) {
return this.client.upload('images/', uri, name, contentType, onUploadProgress);
}
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export * from './user';
export * from './batch_operations';
export * from './errors';
export * from './signing';
export * from './audit_logs';
7 changes: 6 additions & 1 deletion test/unit/node/client_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ describe('[UNIT] Stream Client (Node)', function () {

it('#userAgent', function () {
const useragent = this.client.userAgent();

expect(useragent).to.be(`stream-javascript-client-node-${pkg.version}`);

// Test with PACKAGE_VERSION environment variable
process.env.PACKAGE_VERSION = '1.2.3';
const useragentWithEnv = this.client.userAgent();
expect(useragentWithEnv).to.be('stream-javascript-client-node-1.2.3');
delete process.env.PACKAGE_VERSION;
});

it('#feed', function () {
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"strict": true,
"lib": ["DOM", "ES2020"],
"sourceMap": true,
"target": "ES2020"
"target": "ES2020",
"resolveJsonModule": true
},
"include": ["src", "types"],
"exclude": ["node_modules", "test", "lib", "dist"]
Expand Down
Loading
Loading