nodestack-client 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,eAAe,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IACjG,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,SAAS,EAAE,aAAa,CAAC;IACzC,SAAgB,KAAK,EAAE,WAAW,CAAC;IACnC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,MAAM,EAAE,YAAY,CAAC;IACrC,SAAgB,WAAW,EAAE,iBAAiB,CAAC;IAC/C,SAAgB,IAAI,EAAE,WAAW,CAAC;IAElC,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAA8C;gBAExD,OAAO,GAAE,MAAY,EAAE,OAAO,GAAE,aAAkB;IAe9D;;;OAGG;IACI,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAInD;;OAEG;IACI,QAAQ,IAAI,YAAY,GAAG,IAAI;IAItC;;;;OAIG;IACI,UAAU,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,IAAI,EAAE,CAAC,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjF,UAAU,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IAWlE;;;OAGG;IACU,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAsJ/E;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAItE;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC;IAIrC;;OAEG;IACU,IAAI,CAAC,IAAI,SAAI,EAAE,OAAO,SAAK,GAAG,OAAO,CAAC,GAAG,CAAC;IAOvD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;CAGrC"}
1
+ {"version":3,"file":"Client.d.ts","sourceRoot":"","sources":["../src/Client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,eAAe,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IACjG,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,SAAS,EAAE,aAAa,CAAC;IACzC,SAAgB,KAAK,EAAE,WAAW,CAAC;IACnC,SAAgB,QAAQ,EAAE,eAAe,CAAC;IAC1C,SAAgB,MAAM,EAAE,YAAY,CAAC;IACrC,SAAgB,WAAW,EAAE,iBAAiB,CAAC;IAC/C,SAAgB,IAAI,EAAE,WAAW,CAAC;IAClC,SAAgB,QAAQ,EAAE,cAAc,CAAC;IAEzC,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAA8C;gBAExD,OAAO,GAAE,MAAY,EAAE,OAAO,GAAE,aAAkB;IAgB9D;;;OAGG;IACI,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAInD;;OAEG;IACI,QAAQ,IAAI,YAAY,GAAG,IAAI;IAItC;;;;OAIG;IACI,UAAU,CAAC,CAAC,SAAS,MAAM,YAAY,EAAE,IAAI,EAAE,CAAC,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjF,UAAU,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IAWlE;;;OAGG;IACU,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IAsJ/E;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAItE;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC;IAIrC;;OAEG;IACU,IAAI,CAAC,IAAI,SAAI,EAAE,OAAO,SAAK,GAAG,OAAO,CAAC,GAAG,CAAC;IAOvD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;CAGrC"}
package/dist/index.cjs CHANGED
@@ -32,8 +32,11 @@ __export(index_exports, {
32
32
  NodeStackClient: () => NodeStackClient,
33
33
  RealtimeService: () => RealtimeService,
34
34
  RecordService: () => RecordService,
35
+ WebhookService: () => WebhookService,
36
+ computeWebhookSignature: () => computeWebhookSignature,
35
37
  decodeJwtPayload: () => decodeJwtPayload,
36
- default: () => NodeStackClient
38
+ default: () => NodeStackClient,
39
+ verifyWebhookSignature: () => verifyWebhookSignature
37
40
  });
38
41
  module.exports = __toCommonJS(index_exports);
39
42
 
@@ -875,6 +878,163 @@ var DemoService = class extends BaseService {
875
878
  }
876
879
  };
877
880
 
881
+ // src/services/WebhookService.ts
882
+ function computeWebhookSignature(payload, secret) {
883
+ const str = typeof payload === "string" ? payload : JSON.stringify(payload);
884
+ try {
885
+ const nodeCrypto = typeof require !== "undefined" ? require("crypto") : globalThis?.crypto;
886
+ if (nodeCrypto && typeof nodeCrypto.createHmac === "function") {
887
+ return nodeCrypto.createHmac("sha256", secret).update(str, "utf8").digest("hex");
888
+ }
889
+ } catch {
890
+ }
891
+ throw new Error("[NodeStackClient] HMAC-SHA256 computation requires crypto module.");
892
+ }
893
+ function verifyWebhookSignature(payload, signatureHeader, secret) {
894
+ if (!signatureHeader || !secret) return false;
895
+ let expected = "";
896
+ try {
897
+ expected = computeWebhookSignature(payload, secret);
898
+ } catch {
899
+ return false;
900
+ }
901
+ let cleanHeader = signatureHeader.trim();
902
+ if (cleanHeader.startsWith("sha256=")) {
903
+ cleanHeader = cleanHeader.substring(7);
904
+ } else if (cleanHeader.startsWith("sha256:")) {
905
+ cleanHeader = cleanHeader.substring(7);
906
+ }
907
+ if (cleanHeader.length !== expected.length) return false;
908
+ try {
909
+ const nodeCrypto = typeof require !== "undefined" ? require("crypto") : null;
910
+ if (nodeCrypto && typeof nodeCrypto.timingSafeEqual === "function" && typeof Buffer !== "undefined") {
911
+ return nodeCrypto.timingSafeEqual(Buffer.from(cleanHeader, "hex"), Buffer.from(expected, "hex"));
912
+ }
913
+ } catch {
914
+ }
915
+ let diff = 0;
916
+ for (let i = 0; i < cleanHeader.length; i++) {
917
+ diff |= cleanHeader.charCodeAt(i) ^ expected.charCodeAt(i);
918
+ }
919
+ return diff === 0;
920
+ }
921
+ var WebhookService = class extends BaseService {
922
+ /**
923
+ * Retrieves all configured outbound webhooks.
924
+ */
925
+ async getList(options = {}) {
926
+ const res = await this.send("/api/webhooks", {
927
+ method: "GET",
928
+ query: options
929
+ });
930
+ return Array.isArray(res) ? res : [];
931
+ }
932
+ /**
933
+ * Retrieves a single webhook by ID.
934
+ */
935
+ async getOne(id) {
936
+ return this.send(`/api/webhooks/${encodeURIComponent(id)}`, {
937
+ method: "GET"
938
+ });
939
+ }
940
+ /**
941
+ * Creates a new outbound webhook configuration.
942
+ */
943
+ async create(data) {
944
+ return this.send("/api/webhooks", {
945
+ method: "POST",
946
+ body: data
947
+ });
948
+ }
949
+ /**
950
+ * Updates an existing webhook configuration.
951
+ */
952
+ async update(id, data) {
953
+ return this.send(`/api/webhooks/${encodeURIComponent(id)}`, {
954
+ method: "PATCH",
955
+ body: data
956
+ });
957
+ }
958
+ /**
959
+ * Deletes a configured webhook by ID.
960
+ */
961
+ async delete(id) {
962
+ await this.send(`/api/webhooks/${encodeURIComponent(id)}`, {
963
+ method: "DELETE"
964
+ });
965
+ return true;
966
+ }
967
+ /**
968
+ * Dispatches a live test event to the target webhook endpoint with an optional payload.
969
+ */
970
+ async test(id, payload) {
971
+ return this.send(`/api/webhooks/${encodeURIComponent(id)}/test`, {
972
+ method: "POST",
973
+ body: payload !== void 0 ? { payload } : {}
974
+ });
975
+ }
976
+ /**
977
+ * Retrieves overall webhook health and delivery statistics.
978
+ */
979
+ async getStats() {
980
+ return this.send("/api/webhooks/stats", {
981
+ method: "GET"
982
+ });
983
+ }
984
+ /**
985
+ * Queries paginated webhook delivery logs with optional filtering by webhook ID, collection, status, or search.
986
+ */
987
+ async getDeliveries(options = {}) {
988
+ return this.send("/api/webhooks/deliveries", {
989
+ method: "GET",
990
+ query: options
991
+ });
992
+ }
993
+ /**
994
+ * Retrieves complete delivery log details including headers and request/response payloads.
995
+ */
996
+ async getDelivery(id) {
997
+ return this.send(`/api/webhooks/deliveries/${encodeURIComponent(id)}`, {
998
+ method: "GET"
999
+ });
1000
+ }
1001
+ /**
1002
+ * Manually retries a failed delivery attempt to its target endpoint.
1003
+ */
1004
+ async retryDelivery(id) {
1005
+ return this.send(`/api/webhooks/deliveries/${encodeURIComponent(id)}/retry`, {
1006
+ method: "POST"
1007
+ });
1008
+ }
1009
+ /**
1010
+ * Clears delivery history logs. If olderThanDays is specified, only deletes logs older than that many days.
1011
+ */
1012
+ async clearDeliveries(olderThanDays) {
1013
+ const query = {};
1014
+ if (olderThanDays !== void 0 && olderThanDays !== null) {
1015
+ query.olderThanDays = olderThanDays;
1016
+ }
1017
+ return this.send("/api/webhooks/deliveries", {
1018
+ method: "DELETE",
1019
+ query
1020
+ });
1021
+ }
1022
+ /**
1023
+ * Verifies an incoming X-NodeStack-Signature header against the expected secret.
1024
+ */
1025
+ verifySignature(payload, signatureHeader, secret) {
1026
+ return verifyWebhookSignature(payload, signatureHeader, secret);
1027
+ }
1028
+ /**
1029
+ * Computes an HMAC-SHA256 signature for a payload and secret string.
1030
+ */
1031
+ computeSignature(payload, secret) {
1032
+ return computeWebhookSignature(payload, secret);
1033
+ }
1034
+ static verifySignature = verifyWebhookSignature;
1035
+ static computeSignature = computeWebhookSignature;
1036
+ };
1037
+
878
1038
  // src/Client.ts
879
1039
  var NodeStackClient = class {
880
1040
  baseUrl;
@@ -884,6 +1044,7 @@ var NodeStackClient = class {
884
1044
  admins;
885
1045
  collections;
886
1046
  demo;
1047
+ webhooks;
887
1048
  customFetch;
888
1049
  defaultHeaders;
889
1050
  defaultTimeout;
@@ -901,6 +1062,7 @@ var NodeStackClient = class {
901
1062
  this.admins = new AdminService(this);
902
1063
  this.collections = new CollectionService(this);
903
1064
  this.demo = new DemoService(this);
1065
+ this.webhooks = new WebhookService(this);
904
1066
  }
905
1067
  /**
906
1068
  * Dynamically configure latency & chaos simulation options for all future requests.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/auth/BaseAuthStore.ts", "../src/auth/LocalAuthStore.ts", "../src/errors/ClientResponseError.ts", "../src/services/BaseService.ts", "../src/services/RecordService.ts", "../src/services/FileService.ts", "../src/services/RealtimeService.ts", "../src/services/AdminService.ts", "../src/services/CollectionService.ts", "../src/services/DemoService.ts", "../src/Client.ts", "../src/auth/MemoryAuthStore.ts"],
4
- "sourcesContent": ["// Main Client\r\nexport { NodeStackClient } from './Client';\r\nexport { NodeStackClient as default } from './Client';\r\n\r\n// Errors\r\nexport { ClientResponseError, ClientResponseErrorOptions } from './errors/ClientResponseError';\r\n\r\n// Auth Stores\r\nexport { BaseAuthStore, AuthChangeListener, decodeJwtPayload } from './auth/BaseAuthStore';\r\nexport { LocalAuthStore, StorageLike } from './auth/LocalAuthStore';\r\nexport { MemoryAuthStore } from './auth/MemoryAuthStore';\r\n\r\n// Services\r\nexport { BaseService, ClientInterface } from './services/BaseService';\r\nexport { RecordService, ClientWithRealtime } from './services/RecordService';\r\nexport { FileService, FileUrlOptions } from './services/FileService';\r\nexport { RealtimeService } from './services/RealtimeService';\r\nexport { AdminService } from './services/AdminService';\r\nexport { CollectionService } from './services/CollectionService';\r\nexport { DemoService } from './services/DemoService';\r\n\r\n// Types & Models\r\nexport * from './types';\r\n", "import type { RecordModel, AdminModel } from '../types';\n\nexport type AuthChangeListener = (token: string, model: RecordModel | AdminModel | null) => void;\n\n/**\n * Lightweight helper to decode JWT payload without external dependencies.\n */\nexport function decodeJwtPayload(token: string): Record<string, any> | null {\n if (!token || typeof token !== 'string') return null;\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n\n try {\n let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n while (b64.length % 4) {\n b64 += '=';\n }\n\n let jsonStr: string;\n const globalObj: any =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof window !== 'undefined'\n ? window\n : typeof self !== 'undefined'\n ? self\n : {};\n\n if (typeof globalObj.atob === 'function') {\n jsonStr = decodeURIComponent(\n Array.prototype.map\n .call(globalObj.atob(b64), (c: string) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\n .join('')\n );\n } else if (typeof globalObj.Buffer !== 'undefined') {\n jsonStr = globalObj.Buffer.from(b64, 'base64').toString('utf8');\n } else {\n return null;\n }\n\n return JSON.parse(jsonStr);\n } catch {\n return null;\n }\n}\n\n/**\n * Base abstract class for authentication stores.\n */\nexport abstract class BaseAuthStore {\n protected _token: string = '';\n protected _model: RecordModel | AdminModel | null = null;\n private _listeners: Set<AuthChangeListener> = new Set();\n\n public get token(): string {\n return this._token;\n }\n\n public get model(): RecordModel | AdminModel | null {\n return this._model;\n }\n\n /**\n * Returns true if a token exists and has not yet expired.\n */\n public get isValid(): boolean {\n if (!this._token) {\n return false;\n }\n\n const payload = decodeJwtPayload(this._token);\n if (!payload) {\n return false;\n }\n\n if (payload.exp && typeof payload.exp === 'number') {\n const now = Math.floor(Date.now() / 1000);\n return payload.exp > now;\n }\n\n return true;\n }\n\n /**\n * Saves the token and associated user or admin model.\n */\n public save(token: string, model?: RecordModel | AdminModel | null): void {\n this._token = token || '';\n this._model = model || null;\n this.notify();\n }\n\n /**\n * Clears the current authentication state.\n */\n public clear(): void {\n this._token = '';\n this._model = null;\n this.notify();\n }\n\n /**\n * Subscribes to changes in authentication state (token or model).\n * Returns an unbind function.\n */\n public onChange(callback: AuthChangeListener, fireImmediately = false): () => void {\n this._listeners.add(callback);\n if (fireImmediately) {\n try {\n callback(this._token, this._model);\n } catch (err) {\n console.error('[AuthStore] Error in immediate onChange listener:', err);\n }\n }\n\n return () => {\n this._listeners.delete(callback);\n };\n }\n\n /**\n * Triggers all subscribed change listeners.\n */\n protected notify(): void {\n for (const listener of this._listeners) {\n try {\n listener(this._token, this._model);\n } catch (err) {\n console.error('[AuthStore] Error in onChange listener:', err);\n }\n }\n }\n}\n", "import { BaseAuthStore } from './BaseAuthStore';\nimport type { RecordModel, AdminModel } from '../types';\n\nexport interface StorageLike {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nconst DEFAULT_STORAGE_KEY = 'nodestack_auth';\n\n/**\n * Storage-backed AuthStore that syncs token and model with localStorage\n * (or any custom StorageLike object, such as sessionStorage or AsyncStorage).\n * Safely degrades to memory if storage is not available.\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageKey: string;\n private storage?: StorageLike;\n\n constructor(storageKey: string = DEFAULT_STORAGE_KEY, customStorage?: StorageLike) {\n super();\n this.storageKey = storageKey;\n\n if (customStorage) {\n this.storage = customStorage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n this.storage = window.localStorage;\n }\n\n this.loadInitial();\n }\n\n private loadInitial(): void {\n if (!this.storage) return;\n\n try {\n const raw = this.storage.getItem(this.storageKey);\n if (raw) {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed.token === 'string') {\n this._token = parsed.token;\n this._model = parsed.model || null;\n }\n }\n } catch {\n // Ignore parse or storage errors\n }\n }\n\n public override save(token: string, model?: RecordModel | AdminModel | null): void {\n super.save(token, model);\n\n if (this.storage) {\n try {\n this.storage.setItem(\n this.storageKey,\n JSON.stringify({\n token: this._token,\n model: this._model,\n })\n );\n } catch {\n // Storage might be full or disabled\n }\n }\n }\n\n public override clear(): void {\n super.clear();\n\n if (this.storage) {\n try {\n this.storage.removeItem(this.storageKey);\n } catch {\n // Ignore storage error\n }\n }\n }\n}\n", "export interface ClientResponseErrorOptions {\n url?: string;\n status?: number;\n data?: any;\n isAbort?: boolean;\n originalError?: any;\n message?: string;\n}\n\n/**\n * Standardized client response error representing failed HTTP requests\n * or network exceptions when interacting with NodeStack.\n */\nexport class ClientResponseError extends Error {\n public readonly url: string;\n public readonly status: number;\n public readonly data: any;\n public readonly isAbort: boolean;\n public readonly originalError?: any;\n\n constructor(options: ClientResponseErrorOptions = {}) {\n const status = options.status || 0;\n const message =\n options.message ||\n options.data?.message ||\n (status > 0 ? `NodeStack request failed with status ${status}` : 'NodeStack network request failed');\n\n super(message);\n this.name = 'ClientResponseError';\n this.url = options.url || '';\n this.status = status;\n this.data = options.data || {};\n this.isAbort = Boolean(options.isAbort);\n this.originalError = options.originalError;\n\n // Restore prototype chain\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n }\n\n public toJSON() {\n return {\n name: this.name,\n message: this.message,\n url: this.url,\n status: this.status,\n data: this.data,\n isAbort: this.isAbort,\n };\n }\n}\n", "import type { SendOptions } from '../types';\nimport type { BaseAuthStore } from '../auth/BaseAuthStore';\n\nexport interface ClientInterface {\n baseUrl: string;\n authStore: BaseAuthStore;\n send<T = any>(path: string, options?: SendOptions): Promise<T>;\n}\n\n/**\n * Base service class from which all specific domain services inherit.\n */\nexport abstract class BaseService {\n constructor(protected readonly client: ClientInterface) {}\n\n protected send<T = any>(path: string, options: SendOptions = {}): Promise<T> {\n return this.client.send<T>(path, options);\n }\n}\n", "import { BaseService, ClientInterface } from './BaseService';\r\nimport { ClientResponseError } from '../errors/ClientResponseError';\r\nimport type {\r\n ListResult,\r\n QueryOptions,\r\n RecordModel,\r\n RecordAuthResponse,\r\n ImportResult,\r\n RealtimeCallback,\r\n UnsubscribeFunc,\r\n} from '../types';\r\n\r\nexport interface ClientWithRealtime extends ClientInterface {\r\n realtime: {\r\n subscribe<R = any>(topic: string, callback: RealtimeCallback<R>): Promise<UnsubscribeFunc>;\r\n unsubscribe(topic?: string, callback?: RealtimeCallback<any>): Promise<void>;\r\n };\r\n}\r\n\r\n/**\r\n * Service for managing CRUD, authentication, file handling, and subscriptions\r\n * for a specific collection.\r\n */\r\nexport class RecordService<T = RecordModel> extends BaseService {\r\n constructor(\r\n client: ClientWithRealtime,\r\n public readonly collectionName: string\r\n ) {\r\n super(client);\r\n }\r\n\r\n private get clientWithRealtime(): ClientWithRealtime {\r\n return this.client as ClientWithRealtime;\r\n }\r\n\r\n /**\r\n * Returns a paginated list of records matching the query options.\r\n */\r\n public async getList(options?: QueryOptions): Promise<ListResult<T>>;\r\n public async getList(\r\n page?: number,\r\n perPage?: number,\r\n options?: QueryOptions\r\n ): Promise<ListResult<T>>;\r\n public async getList(\r\n pageOrOptions: number | QueryOptions = 1,\r\n perPage = 30,\r\n options: QueryOptions = {}\r\n ): Promise<ListResult<T>> {\r\n let pageNum = 1;\r\n let perPageNum = perPage;\r\n let queryOpts: QueryOptions = options;\r\n\r\n if (typeof pageOrOptions === 'object' && pageOrOptions !== null) {\r\n queryOpts = pageOrOptions;\r\n pageNum = typeof queryOpts.page === 'number' ? queryOpts.page : 1;\r\n perPageNum = typeof queryOpts.perPage === 'number' ? queryOpts.perPage : 30;\r\n } else if (typeof pageOrOptions === 'number') {\r\n pageNum = pageOrOptions;\r\n }\r\n\r\n return this.send<ListResult<T>>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records`,\r\n {\r\n method: 'GET',\r\n query: {\r\n page: pageNum,\r\n perPage: perPageNum,\r\n ...queryOpts,\r\n },\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Fetches and aggregates all records in the collection across multiple pages.\r\n */\r\n public async getFullList(\r\n options: QueryOptions & { batch?: number } = {}\r\n ): Promise<T[]> {\r\n const batch = Math.max(1, Math.min(500, options.batch || 200));\r\n const query = { ...options };\r\n delete query.batch;\r\n\r\n const firstPage = await this.getList(1, batch, query);\r\n const items: T[] = [...firstPage.items];\r\n\r\n if (firstPage.totalPages <= 1) {\r\n return items;\r\n }\r\n\r\n for (let page = 2; page <= firstPage.totalPages; page++) {\r\n const result = await this.getList(page, batch, query);\r\n items.push(...result.items);\r\n }\r\n\r\n return items;\r\n }\r\n\r\n /**\r\n * Returns the first record matching the specified filter expression.\r\n * Throws ClientResponseError(404) if no record matches.\r\n */\r\n public async getFirstListItem(\r\n filter: string,\r\n options: QueryOptions = {}\r\n ): Promise<T> {\r\n const list = await this.getList(1, 1, {\r\n ...options,\r\n filter,\r\n });\r\n\r\n if (!list.items || list.items.length === 0) {\r\n throw new ClientResponseError({\r\n status: 404,\r\n url: `/api/collections/${this.collectionName}/records`,\r\n message: `The requested record was not found in collection '${this.collectionName}'.`,\r\n });\r\n }\r\n\r\n return list.items[0];\r\n }\r\n\r\n /**\r\n * Retrieves a single record by its ID.\r\n */\r\n public async getOne(id: string, options: QueryOptions = {}): Promise<T> {\r\n return this.send<T>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records/${encodeURIComponent(id)}`,\r\n {\r\n method: 'GET',\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Creates a new record in the collection.\r\n * Accepts a plain object or FormData (for file uploads).\r\n */\r\n public async create(\r\n data: Record<string, any> | FormData,\r\n options: QueryOptions = {}\r\n ): Promise<T> {\r\n return this.send<T>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records`,\r\n {\r\n method: 'POST',\r\n body: data,\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Updates an existing record by its ID.\r\n * Accepts a plain object or FormData (for file updates).\r\n */\r\n public async update(\r\n id: string,\r\n data: Record<string, any> | FormData,\r\n options: QueryOptions = {}\r\n ): Promise<T> {\r\n return this.send<T>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records/${encodeURIComponent(id)}`,\r\n {\r\n method: 'PATCH',\r\n body: data,\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Deletes a record by its ID.\r\n */\r\n public async delete(id: string): Promise<boolean> {\r\n await this.send<void>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records/${encodeURIComponent(id)}`,\r\n {\r\n method: 'DELETE',\r\n }\r\n );\r\n return true;\r\n }\r\n\r\n /**\r\n * Authenticates against an auth collection using identity/email and password.\r\n * On success, automatically persists the token and record to authStore.\r\n */\r\n public async authWithPassword(\r\n identity: string,\r\n password: string\r\n ): Promise<RecordAuthResponse<T>> {\r\n const result = await this.send<RecordAuthResponse<T>>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/auth-with-password`,\r\n {\r\n method: 'POST',\r\n body: { identity, password },\r\n }\r\n );\r\n\r\n if (result && result.token) {\r\n this.client.authStore.save(result.token, result.record as any);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Exports records from the collection as CSV or JSON.\r\n */\r\n public async export(\r\n format: 'csv' | 'json' = 'csv',\r\n options: QueryOptions = {}\r\n ): Promise<string> {\r\n return this.send<string>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/export`,\r\n {\r\n method: 'GET',\r\n query: {\r\n ...options,\r\n format,\r\n },\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Imports records into the collection.\r\n */\r\n public async import(\r\n data: any[] | FormData | Blob | string,\r\n options: { continueOnError?: boolean } = {}\r\n ): Promise<ImportResult> {\r\n return this.send<ImportResult>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/import`,\r\n {\r\n method: 'POST',\r\n body: data,\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Subscribes to realtime events on this collection or a specific record ID.\r\n *\r\n * Example:\r\n * // Listen to all records in collection:\r\n * client.collection('posts').subscribe('*', (e) => console.log(e.action, e.record));\r\n *\r\n * // Listen to single record changes:\r\n * client.collection('posts').subscribe('record_id_123', (e) => console.log(e.action, e.record));\r\n */\r\n public async subscribe(\r\n topicOrCallback: string | RealtimeCallback<T>,\r\n callback?: RealtimeCallback<T>\r\n ): Promise<UnsubscribeFunc> {\r\n let topic = '*';\r\n let cb: RealtimeCallback<T>;\r\n\r\n if (typeof topicOrCallback === 'function') {\r\n topic = '*';\r\n cb = topicOrCallback;\r\n } else {\r\n topic = topicOrCallback;\r\n cb = callback!;\r\n }\r\n\r\n const fullTopic = topic === '*' ? this.collectionName : `${this.collectionName}/${topic}`;\r\n return this.clientWithRealtime.realtime.subscribe<T>(fullTopic, cb);\r\n }\r\n\r\n /**\r\n * Unsubscribes from realtime events for this collection.\r\n */\r\n public async unsubscribe(topic?: string): Promise<void> {\r\n const fullTopic = !topic || topic === '*' ? this.collectionName : `${this.collectionName}/${topic}`;\r\n return this.clientWithRealtime.realtime.unsubscribe(fullTopic);\r\n }\r\n}\r\n", "import { BaseService } from './BaseService';\n\nexport interface FileUrlOptions {\n download?: boolean;\n token?: string | boolean;\n collection?: string;\n}\n\n/**\n * Service for generating file URLs for assets uploaded to NodeStack.\n */\nexport class FileService extends BaseService {\n /**\n * Generates a fully qualified URL to an uploaded file.\n *\n * @param record - Record object or record ID string\n * @param filename - Name of the file stored on the record\n * @param options - Additional options (download flag, auth token, collection override)\n */\n public getUrl(\n record: { id: string; collection?: string; collectionName?: string; [key: string]: any } | string,\n filename: string,\n options: FileUrlOptions = {}\n ): string {\n if (!filename) return '';\n\n let recordId = '';\n let collectionName = options.collection || '';\n\n if (typeof record === 'string') {\n recordId = record;\n } else if (record && typeof record === 'object') {\n recordId = record.id || '';\n collectionName =\n collectionName ||\n record.collection ||\n record.collectionName ||\n record['@collectionName'] ||\n '';\n }\n\n if (!recordId) {\n throw new Error('[FileService] A valid record or recordId is required to construct a file URL.');\n }\n\n if (!collectionName) {\n throw new Error(\n '[FileService] Collection name is required. Either provide a record with collection info or pass options.collection.'\n );\n }\n\n const cleanBase = (this.client.baseUrl || '').replace(/\\/+$/, '');\n const cleanCol = encodeURIComponent(collectionName);\n const cleanId = encodeURIComponent(recordId);\n const cleanFile = encodeURIComponent(filename);\n\n let url = `${cleanBase}/api/files/${cleanCol}/${cleanId}/${cleanFile}`;\n\n const queryParts: string[] = [];\n\n if (options.download) {\n queryParts.push('download=1');\n }\n\n // Attach token if requested\n if (typeof options.token === 'string' && options.token) {\n queryParts.push(`token=${encodeURIComponent(options.token)}`);\n } else if (options.token === true && this.client.authStore.token) {\n queryParts.push(`token=${encodeURIComponent(this.client.authStore.token)}`);\n }\n\n if (queryParts.length > 0) {\n url += `?${queryParts.join('&')}`;\n }\n\n return url;\n }\n}\n", "import { BaseService, ClientInterface } from './BaseService';\nimport type { RealtimeEvent, RealtimeCallback, UnsubscribeFunc } from '../types';\n\n/**\n * Multiplexed Realtime Server-Sent Events (SSE) service.\n * Manages a single persistent SSE connection and dispatches events to subscribed listeners.\n */\nexport class RealtimeService extends BaseService {\n private eventSource: any = null;\n private clientId: string = '';\n private isConnecting: boolean = false;\n private connectPromise: Promise<string> | null = null;\n private reconnectTimeout: any = null;\n private reconnectAttempts: number = 0;\n private customEventSource?: any;\n\n // Map of topic -> Set of callbacks\n private subscriptions: Map<string, Set<RealtimeCallback<any>>> = new Map();\n\n // Set of registered event names on the active EventSource\n private registeredEventNames: Set<string> = new Set();\n\n constructor(client: ClientInterface, customEventSource?: any) {\n super(client);\n this.customEventSource = customEventSource;\n }\n\n /**\n * Returns whether there is an active EventSource connection.\n */\n public get isConnected(): boolean {\n return Boolean(this.eventSource && this.clientId);\n }\n\n /**\n * Resolves the EventSource constructor available in the current environment.\n */\n private getEventSourceConstructor(): any {\n if (this.customEventSource) {\n return this.customEventSource;\n }\n if (typeof window !== 'undefined' && (window as any).EventSource) {\n return (window as any).EventSource;\n }\n if (typeof globalThis !== 'undefined' && (globalThis as any).EventSource) {\n return (globalThis as any).EventSource;\n }\n throw new Error(\n '[RealtimeService] EventSource is not supported natively in this environment. ' +\n 'Please pass an EventSource polyfill to ClientOptions (e.g. from the \"eventsource\" package).'\n );\n }\n\n /**\n * Connects to the SSE stream if not already connected.\n * Returns the connected clientId.\n */\n public async connect(): Promise<string> {\n if (this.clientId && this.eventSource) {\n return this.clientId;\n }\n\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.connectPromise = new Promise<string>((resolve, reject) => {\n try {\n const EventSourceClass = this.getEventSourceConstructor();\n const base = (this.client.baseUrl || '').replace(/\\/+$/, '');\n let url = `${base}/api/realtime`;\n\n if (this.client.authStore.token) {\n url += `?token=${encodeURIComponent(this.client.authStore.token)}`;\n }\n\n this.eventSource = new EventSourceClass(url);\n\n const handleConnect = async (event: any) => {\n try {\n const data = JSON.parse(event.data);\n this.clientId = data.clientId;\n this.reconnectAttempts = 0;\n\n // Re-apply any existing subscriptions on the server\n await this.syncSubscriptions();\n\n resolve(this.clientId);\n } catch (err) {\n reject(err);\n }\n };\n\n this.eventSource.addEventListener('NS_CONNECT', handleConnect);\n this.eventSource.addEventListener('NB_CONNECT', handleConnect);\n\n this.eventSource.onerror = (err: any) => {\n if (!this.clientId) {\n reject(err);\n }\n this.handleDisconnect();\n };\n\n // Bind listeners for all known collection topics\n this.bindActiveTopics();\n } catch (err) {\n this.connectPromise = null;\n reject(err);\n }\n }).finally(() => {\n this.connectPromise = null;\n });\n\n return this.connectPromise;\n }\n\n /**\n * Subscribes to realtime updates for a collection or record.\n *\n * @param topic - Collection name ('posts'), wildcard ('*'), or specific record ('posts/rec_123')\n * @param callback - Event listener callback\n * @returns Unsubscribe function\n */\n public async subscribe<T = any>(\n topic: string,\n callback: RealtimeCallback<T>\n ): Promise<UnsubscribeFunc> {\n const cleanTopic = (topic || '*').trim();\n\n if (!this.subscriptions.has(cleanTopic)) {\n this.subscriptions.set(cleanTopic, new Set());\n }\n\n this.subscriptions.get(cleanTopic)!.add(callback);\n\n // If connected, sync subscriptions with server\n if (this.isConnected) {\n this.bindTopicListener(cleanTopic);\n await this.syncSubscriptions();\n } else {\n // Connect and sync\n await this.connect();\n }\n\n return () => this.unsubscribe(cleanTopic, callback);\n }\n\n /**\n * Unsubscribes from a topic or specific callback.\n */\n public async unsubscribe(topic?: string, callback?: RealtimeCallback<any>): Promise<void> {\n if (!topic) {\n // Unsubscribe all\n this.subscriptions.clear();\n if (this.isConnected) {\n await this.syncSubscriptions();\n }\n return;\n }\n\n const cleanTopic = topic.trim();\n if (!this.subscriptions.has(cleanTopic)) {\n return;\n }\n\n if (callback) {\n this.subscriptions.get(cleanTopic)!.delete(callback);\n if (this.subscriptions.get(cleanTopic)!.size === 0) {\n this.subscriptions.delete(cleanTopic);\n }\n } else {\n this.subscriptions.delete(cleanTopic);\n }\n\n if (this.isConnected) {\n await this.syncSubscriptions();\n }\n }\n\n /**\n * Closes the SSE connection and clears state.\n */\n public disconnect(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.eventSource) {\n try {\n this.eventSource.close();\n } catch {}\n this.eventSource = null;\n }\n\n this.clientId = '';\n this.registeredEventNames.clear();\n }\n\n /**\n * Synchronizes active subscriptions with the backend via POST /api/realtime.\n */\n private async syncSubscriptions(): Promise<void> {\n if (!this.clientId) return;\n\n const topics = Array.from(this.subscriptions.keys());\n\n try {\n await this.client.send('/api/realtime', {\n method: 'POST',\n body: {\n clientId: this.clientId,\n subscriptions: topics.length > 0 ? topics : ['__noop__'],\n },\n });\n } catch (err) {\n console.warn('[RealtimeService] Failed to sync subscriptions with server:', err);\n }\n }\n\n /**\n * Binds an EventSource listener for the collection corresponding to a topic.\n */\n private bindTopicListener(topic: string): void {\n if (!this.eventSource) return;\n\n // Determine collection name\n const collectionName = topic.includes('/') ? topic.split('/')[0] : topic;\n\n if (this.registeredEventNames.has(collectionName)) {\n return;\n }\n\n this.registeredEventNames.add(collectionName);\n\n this.eventSource.addEventListener(collectionName, (event: any) => {\n try {\n const payload: RealtimeEvent<any> = JSON.parse(event.data);\n this.dispatchEvent(collectionName, payload);\n } catch (err) {\n console.error(`[RealtimeService] Error handling event for ${collectionName}:`, err);\n }\n });\n }\n\n private bindActiveTopics(): void {\n for (const topic of this.subscriptions.keys()) {\n this.bindTopicListener(topic);\n }\n }\n\n /**\n * Dispatches received SSE events to matching subscribed listeners.\n */\n private dispatchEvent(collectionName: string, event: RealtimeEvent<any>): void {\n const recordId = event.record?.id;\n\n // Check wildcard subscription '*'\n this.triggerListeners('*', event);\n\n // Check collection subscription e.g. 'posts' or 'posts/*'\n this.triggerListeners(collectionName, event);\n this.triggerListeners(`${collectionName}/*`, event);\n\n // Check record-specific subscription e.g. 'posts/rec_123'\n if (recordId) {\n this.triggerListeners(`${collectionName}/${recordId}`, event);\n }\n }\n\n private triggerListeners(topic: string, event: RealtimeEvent<any>): void {\n const callbacks = this.subscriptions.get(topic);\n if (!callbacks || callbacks.size === 0) return;\n\n for (const cb of callbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(`[RealtimeService] Error in realtime listener for ${topic}:`, err);\n }\n }\n }\n\n /**\n * Handles disconnections and schedules automatic reconnection.\n */\n private handleDisconnect(): void {\n if (this.reconnectTimeout) return;\n\n this.disconnect();\n\n // Exponential backoff up to 10 seconds\n const delay = Math.min(10000, 500 * Math.pow(1.5, this.reconnectAttempts));\n this.reconnectAttempts++;\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = null;\n if (this.subscriptions.size > 0) {\n this.connect().catch(() => {});\n }\n }, delay);\n }\n}\n", "import { BaseService } from './BaseService';\nimport type { AdminAuthResponse, AdminModel } from '../types';\n\n/**\n * Service for administrative and superuser actions.\n */\nexport class AdminService extends BaseService {\n /**\n * Checks whether at least one superuser / admin account exists in NodeStack.\n */\n public async hasAdmins(): Promise<boolean> {\n const res = await this.send<{ hasAdmins: boolean }>('/api/admins/has-admins', {\n method: 'GET',\n });\n return Boolean(res?.hasAdmins);\n }\n\n /**\n * Creates the initial superuser account during first-time setup.\n * Automatically persists the returned admin token and model to authStore.\n */\n public async createInitial(email: string, password: string): Promise<AdminAuthResponse> {\n const res = await this.send<AdminAuthResponse>('/api/admins/create-initial', {\n method: 'POST',\n body: { email, password },\n });\n\n if (res?.token) {\n this.client.authStore.save(res.token, res.admin);\n }\n\n return res;\n }\n\n /**\n * Authenticates a superuser / admin using email and password.\n * Automatically persists the returned admin token and model to authStore.\n */\n public async authWithPassword(identity: string, password: string): Promise<AdminAuthResponse> {\n const res = await this.send<AdminAuthResponse>('/api/admins/auth-with-password', {\n method: 'POST',\n body: { identity, password },\n });\n\n if (res?.token) {\n this.client.authStore.save(res.token, res.admin);\n }\n\n return res;\n }\n\n /**\n * Retrieves the currently authenticated superuser's profile.\n */\n public async getMe(): Promise<AdminModel> {\n return this.send<AdminModel>('/api/admins/me', {\n method: 'GET',\n });\n }\n}\n", "import { BaseService } from './BaseService';\r\n\r\n/**\r\n * Service for managing collection schema definitions (Admin only).\r\n */\r\nexport class CollectionService extends BaseService {\r\n /**\r\n * Retrieves all collection schema models.\r\n */\r\n public async getList(): Promise<any[]> {\r\n const res = await this.send<{ items: any[]; totalItems: number } | any[]>('/api/collections', {\r\n method: 'GET',\r\n });\r\n return Array.isArray(res) ? res : res?.items || [];\r\n }\r\n\r\n /**\r\n * Retrieves a single collection schema by name or ID.\r\n */\r\n public async getOne(nameOrId: string): Promise<any> {\r\n return this.send<any>(`/api/collections/${encodeURIComponent(nameOrId)}`, {\r\n method: 'GET',\r\n });\r\n }\r\n\r\n /**\r\n * Creates a new collection schema.\r\n */\r\n public async create(data: any): Promise<any> {\r\n return this.send<any>('/api/collections', {\r\n method: 'POST',\r\n body: data,\r\n });\r\n }\r\n\r\n /**\r\n * Updates an existing collection schema.\r\n */\r\n public async update(nameOrId: string, data: any): Promise<any> {\r\n return this.send<any>(`/api/collections/${encodeURIComponent(nameOrId)}`, {\r\n method: 'PATCH',\r\n body: data,\r\n });\r\n }\r\n\r\n /**\r\n * Deletes a collection schema and its corresponding SQLite table.\r\n */\r\n public async delete(nameOrId: string): Promise<boolean> {\r\n await this.send<void>(`/api/collections/${encodeURIComponent(nameOrId)}`, {\r\n method: 'DELETE',\r\n });\r\n return true;\r\n }\r\n\r\n /**\r\n * Infers schema fields, field types, and sample records from raw JSON (object or array).\r\n */\r\n public async inferSchema(data: any): Promise<{\r\n suggestedName?: string;\r\n fields: any[];\r\n recordCount: number;\r\n sampleRecords: any[];\r\n }> {\r\n return this.send('/api/collections/infer-schema', {\r\n method: 'POST',\r\n body: { data },\r\n });\r\n }\r\n\r\n /**\r\n * \"Paste JSON \u2192 Instant API\": Infers field types, creates collection and SQLite columns,\r\n * and populates all records within 1 second.\r\n */\r\n public async importJson(\r\n name: string,\r\n data: any,\r\n options: {\r\n type?: 'base' | 'auth';\r\n schemaOverrides?: any[];\r\n listRule?: string | null;\r\n viewRule?: string | null;\r\n createRule?: string | null;\r\n updateRule?: string | null;\r\n deleteRule?: string | null;\r\n } = {}\r\n ): Promise<{\r\n success: boolean;\r\n collection: any;\r\n recordCount: number;\r\n records: any[];\r\n inferredFields: any[];\r\n durationMs: number;\r\n }> {\r\n return this.send('/api/collections/import-json', {\r\n method: 'POST',\r\n body: {\r\n name,\r\n data,\r\n ...options,\r\n },\r\n });\r\n }\r\n}\r\n", "import { BaseService } from './BaseService';\r\nimport type {\r\n DemoSnapshotStatus,\r\n DemoSnapshotMetadata,\r\n DemoResetResult,\r\n} from '../types';\r\n\r\n/**\r\n * Service for freezing baseline demo state and 1-click restore (\"Reset to Demo State\").\r\n */\r\nexport class DemoService extends BaseService {\r\n /**\r\n * Retrieves the current snapshot availability, metadata, and live drift information.\r\n */\r\n public async getStatus(): Promise<DemoSnapshotStatus> {\r\n return this.send<DemoSnapshotStatus>('/api/demo/status', {\r\n method: 'GET',\r\n });\r\n }\r\n\r\n /**\r\n * Freezes current database & file storage state as the demo baseline.\r\n */\r\n public async snapshot(options?: { name?: string; description?: string }): Promise<DemoSnapshotMetadata> {\r\n return this.send<DemoSnapshotMetadata>('/api/demo/snapshot', {\r\n method: 'POST',\r\n body: options || {},\r\n });\r\n }\r\n\r\n /**\r\n * Restores the exact pristine demo state in one click.\r\n */\r\n public async reset(): Promise<DemoResetResult> {\r\n return this.send<DemoResetResult>('/api/demo/reset', {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /**\r\n * Deletes the frozen demo snapshot.\r\n */\r\n public async clear(): Promise<void> {\r\n return this.send<void>('/api/demo/snapshot', {\r\n method: 'DELETE',\r\n });\r\n }\r\n}\r\n", "import { BaseAuthStore } from './auth/BaseAuthStore';\r\nimport { LocalAuthStore } from './auth/LocalAuthStore';\r\nimport { ClientResponseError } from './errors/ClientResponseError';\r\nimport { RecordService } from './services/RecordService';\r\nimport { FileService } from './services/FileService';\r\nimport { RealtimeService } from './services/RealtimeService';\r\nimport { AdminService } from './services/AdminService';\r\nimport { CollectionService } from './services/CollectionService';\r\nimport { DemoService } from './services/DemoService';\r\nimport type {\r\n ClientOptions,\r\n SendOptions,\r\n RecordModel,\r\n ChaosOptions,\r\n} from './types';\r\n\r\n/**\r\n * Main NodeStack Client SDK entry point.\r\n */\r\nexport class NodeStackClient<TCollections extends Record<string, any> = Record<string, RecordModel>> {\r\n public readonly baseUrl: string;\r\n public readonly authStore: BaseAuthStore;\r\n public readonly files: FileService;\r\n public readonly realtime: RealtimeService;\r\n public readonly admins: AdminService;\r\n public readonly collections: CollectionService;\r\n public readonly demo: DemoService;\r\n\r\n private customFetch?: typeof fetch;\r\n private defaultHeaders: Record<string, string>;\r\n private defaultTimeout: number;\r\n private chaosOptions: ChaosOptions | null = null;\r\n private recordServices: Map<string, RecordService<any>> = new Map();\r\n\r\n constructor(baseUrl: string = '/', options: ClientOptions = {}) {\r\n this.baseUrl = (baseUrl || '/').replace(/\\/+$/, '');\r\n this.authStore = options.authStore || new LocalAuthStore();\r\n this.customFetch = options.fetch;\r\n this.defaultHeaders = options.headers || {};\r\n this.defaultTimeout = options.timeout || 120000; // 2 minutes default\r\n this.chaosOptions = options.chaos ? { ...options.chaos } : null;\r\n\r\n this.files = new FileService(this);\r\n this.realtime = new RealtimeService(this, options.EventSource);\r\n this.admins = new AdminService(this);\r\n this.collections = new CollectionService(this);\r\n this.demo = new DemoService(this);\r\n }\r\n\r\n /**\r\n * Dynamically configure latency & chaos simulation options for all future requests.\r\n * Pass null to disable client-side chaos injection.\r\n */\r\n public setChaos(options: ChaosOptions | null): void {\r\n this.chaosOptions = options ? { ...options } : null;\r\n }\r\n\r\n /**\r\n * Get active chaos simulation options.\r\n */\r\n public getChaos(): ChaosOptions | null {\r\n return this.chaosOptions ? { ...this.chaosOptions } : null;\r\n }\r\n\r\n /**\r\n * Returns a RecordService for interacting with a specific collection.\r\n * If a schema map type is provided to NodeStackClient, collection names\r\n * and record response types are automatically inferred and type-safe.\r\n */\r\n public collection<K extends keyof TCollections>(name: K): RecordService<TCollections[K]>;\r\n public collection<T = RecordModel>(name: string): RecordService<T>;\r\n public collection(name: string): RecordService<any> {\r\n const colName = String(name);\r\n let service = this.recordServices.get(colName);\r\n if (!service) {\r\n service = new RecordService(this, colName);\r\n this.recordServices.set(colName, service);\r\n }\r\n return service;\r\n }\r\n\r\n /**\r\n * Sends an HTTP request to NodeStack with automatic authentication,\r\n * header injection, query serialization, and standardized error handling.\r\n */\r\n public async send<T = any>(path: string, options: SendOptions = {}): Promise<T> {\r\n const fetchFn = this.customFetch || (typeof fetch !== 'undefined' ? fetch : null);\r\n if (!fetchFn) {\r\n throw new Error(\r\n '[NodeStackClient] fetch is not available in this environment. ' +\r\n 'Please pass a custom fetch implementation to ClientOptions.'\r\n );\r\n }\r\n\r\n // 1. Build URL & Query parameters\r\n let url = path.startsWith('http://') || path.startsWith('https://')\r\n ? path\r\n : `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\r\n\r\n if (options.query) {\r\n const searchParams = new URLSearchParams();\r\n for (const [key, val] of Object.entries(options.query)) {\r\n if (val === undefined || val === null) continue;\r\n searchParams.append(key, String(val));\r\n }\r\n const queryStr = searchParams.toString();\r\n if (queryStr) {\r\n url += (url.includes('?') ? '&' : '?') + queryStr;\r\n }\r\n }\r\n\r\n // 2. Prepare headers\r\n const headers: Record<string, string> = {\r\n ...this.defaultHeaders,\r\n ...(options.headers || {}),\r\n };\r\n\r\n if (this.authStore.token && !headers['Authorization'] && !headers['authorization']) {\r\n headers['Authorization'] = `Bearer ${this.authStore.token}`;\r\n }\r\n\r\n // 2b. Inject Latency & Chaos simulation headers\r\n const effectiveChaos: ChaosOptions = {\r\n ...(this.chaosOptions || {}),\r\n ...(options.chaos || {}),\r\n ...(options.mockDelay !== undefined ? { delay: options.mockDelay } : {}),\r\n ...(options.mockError !== undefined ? { errorStatus: options.mockError } : {}),\r\n ...(options.mockFailRate !== undefined ? { failRate: options.mockFailRate } : {}),\r\n ...(options.mockJitter !== undefined ? { jitter: options.mockJitter } : {}),\r\n };\r\n\r\n if (effectiveChaos.delay !== undefined && !headers['x-mock-delay'] && !headers['mock-delay']) {\r\n headers['x-mock-delay'] = String(effectiveChaos.delay);\r\n }\r\n if (effectiveChaos.errorStatus !== undefined && !headers['x-mock-error'] && !headers['mock-error']) {\r\n headers['x-mock-error'] = String(effectiveChaos.errorStatus);\r\n }\r\n if (effectiveChaos.failRate !== undefined && !headers['x-mock-fail-rate'] && !headers['mock-fail-rate']) {\r\n headers['x-mock-fail-rate'] = String(effectiveChaos.failRate);\r\n }\r\n if (effectiveChaos.jitter !== undefined && !headers['x-mock-jitter'] && !headers['mock-jitter']) {\r\n headers['x-mock-jitter'] = String(effectiveChaos.jitter);\r\n }\r\n if (effectiveChaos.errorMessage && !headers['x-mock-error-message'] && !headers['mock-error-message']) {\r\n headers['x-mock-error-message'] = String(effectiveChaos.errorMessage);\r\n }\r\n\r\n // 3. Serialize body\r\n let body: any = options.body;\r\n const isFormData = typeof FormData !== 'undefined' && body instanceof FormData;\r\n const isBlob = typeof Blob !== 'undefined' && body instanceof Blob;\r\n\r\n if (body !== undefined && body !== null) {\r\n if (isFormData) {\r\n // Let the environment compute multipart boundary headers automatically\r\n delete headers['Content-Type'];\r\n delete headers['content-type'];\r\n } else if (isBlob || typeof body === 'string') {\r\n // Leave body as-is\r\n } else if (typeof body === 'object') {\r\n headers['Content-Type'] = 'application/json';\r\n body = JSON.stringify(body);\r\n }\r\n }\r\n\r\n // 4. Handle abort signal & timeout\r\n let signal = options.signal;\r\n let timeoutId: any = null;\r\n\r\n if (!signal && this.defaultTimeout > 0 && typeof AbortController !== 'undefined') {\r\n const controller = new AbortController();\r\n signal = controller.signal;\r\n timeoutId = setTimeout(() => controller.abort(), this.defaultTimeout);\r\n }\r\n\r\n try {\r\n const response = await fetchFn(url, {\r\n ...options,\r\n headers,\r\n body,\r\n signal,\r\n });\r\n\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n\r\n // Handle 204 No Content\r\n if (response.status === 204) {\r\n return null as any;\r\n }\r\n\r\n const contentType = response.headers.get('content-type') || '';\r\n let data: any;\r\n\r\n if (contentType.includes('application/json')) {\r\n data = await response.json().catch(() => ({}));\r\n } else {\r\n data = await response.text();\r\n }\r\n\r\n if (!response.ok) {\r\n throw new ClientResponseError({\r\n url,\r\n status: response.status,\r\n data,\r\n message: typeof data === 'object' && data?.message ? data.message : undefined,\r\n });\r\n }\r\n\r\n return data as T;\r\n } catch (err: any) {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n\r\n if (err instanceof ClientResponseError) {\r\n throw err;\r\n }\r\n\r\n const isAbort =\r\n err?.name === 'AbortError' ||\r\n (signal && signal.aborted) ||\r\n Boolean(options.signal && options.signal.aborted);\r\n\r\n throw new ClientResponseError({\r\n url,\r\n status: isAbort ? 0 : 0,\r\n isAbort,\r\n originalError: err,\r\n message: isAbort ? 'Request was aborted' : err?.message || 'Network request failed',\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Checks backend system health.\r\n */\r\n public async health(): Promise<{ status: string; [key: string]: any }> {\r\n return this.send('/api/health', { method: 'GET' });\r\n }\r\n\r\n /**\r\n * Retrieves server runtime settings.\r\n */\r\n public async settings(): Promise<any> {\r\n return this.send('/api/settings', { method: 'GET' });\r\n }\r\n\r\n /**\r\n * Fetches request logs (Admin only).\r\n */\r\n public async logs(page = 1, perPage = 50): Promise<any> {\r\n return this.send('/api/logs', {\r\n method: 'GET',\r\n query: { page, perPage },\r\n });\r\n }\r\n\r\n /**\r\n * Fetches system metrics & analytics (Admin only).\r\n */\r\n public async metrics(): Promise<any> {\r\n return this.send('/api/metrics', { method: 'GET' });\r\n }\r\n}\r\n", "import { BaseAuthStore } from './BaseAuthStore';\n\n/**\n * In-memory authentication store.\n * Ideal for Node.js scripts, server-side rendering (SSR), and testing environments.\n */\nexport class MemoryAuthStore extends BaseAuthStore {\n // Inherits default in-memory behavior of BaseAuthStore\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/index.ts", "../src/auth/BaseAuthStore.ts", "../src/auth/LocalAuthStore.ts", "../src/errors/ClientResponseError.ts", "../src/services/BaseService.ts", "../src/services/RecordService.ts", "../src/services/FileService.ts", "../src/services/RealtimeService.ts", "../src/services/AdminService.ts", "../src/services/CollectionService.ts", "../src/services/DemoService.ts", "../src/services/WebhookService.ts", "../src/Client.ts", "../src/auth/MemoryAuthStore.ts"],
4
+ "sourcesContent": ["// Main Client\nexport { NodeStackClient } from './Client';\nexport { NodeStackClient as default } from './Client';\n\n// Errors\nexport { ClientResponseError, ClientResponseErrorOptions } from './errors/ClientResponseError';\n\n// Auth Stores\nexport { BaseAuthStore, AuthChangeListener, decodeJwtPayload } from './auth/BaseAuthStore';\nexport { LocalAuthStore, StorageLike } from './auth/LocalAuthStore';\nexport { MemoryAuthStore } from './auth/MemoryAuthStore';\n\n// Services\nexport { BaseService, ClientInterface } from './services/BaseService';\nexport { RecordService, ClientWithRealtime } from './services/RecordService';\nexport { FileService, FileUrlOptions } from './services/FileService';\nexport { RealtimeService } from './services/RealtimeService';\nexport { AdminService } from './services/AdminService';\nexport { CollectionService } from './services/CollectionService';\nexport { DemoService } from './services/DemoService';\nexport {\n WebhookService,\n computeWebhookSignature,\n verifyWebhookSignature,\n} from './services/WebhookService';\n\n// Types & Models\nexport * from './types';\n", "import type { RecordModel, AdminModel } from '../types';\n\nexport type AuthChangeListener = (token: string, model: RecordModel | AdminModel | null) => void;\n\n/**\n * Lightweight helper to decode JWT payload without external dependencies.\n */\nexport function decodeJwtPayload(token: string): Record<string, any> | null {\n if (!token || typeof token !== 'string') return null;\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n\n try {\n let b64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n while (b64.length % 4) {\n b64 += '=';\n }\n\n let jsonStr: string;\n const globalObj: any =\n typeof globalThis !== 'undefined'\n ? globalThis\n : typeof window !== 'undefined'\n ? window\n : typeof self !== 'undefined'\n ? self\n : {};\n\n if (typeof globalObj.atob === 'function') {\n jsonStr = decodeURIComponent(\n Array.prototype.map\n .call(globalObj.atob(b64), (c: string) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\n .join('')\n );\n } else if (typeof globalObj.Buffer !== 'undefined') {\n jsonStr = globalObj.Buffer.from(b64, 'base64').toString('utf8');\n } else {\n return null;\n }\n\n return JSON.parse(jsonStr);\n } catch {\n return null;\n }\n}\n\n/**\n * Base abstract class for authentication stores.\n */\nexport abstract class BaseAuthStore {\n protected _token: string = '';\n protected _model: RecordModel | AdminModel | null = null;\n private _listeners: Set<AuthChangeListener> = new Set();\n\n public get token(): string {\n return this._token;\n }\n\n public get model(): RecordModel | AdminModel | null {\n return this._model;\n }\n\n /**\n * Returns true if a token exists and has not yet expired.\n */\n public get isValid(): boolean {\n if (!this._token) {\n return false;\n }\n\n const payload = decodeJwtPayload(this._token);\n if (!payload) {\n return false;\n }\n\n if (payload.exp && typeof payload.exp === 'number') {\n const now = Math.floor(Date.now() / 1000);\n return payload.exp > now;\n }\n\n return true;\n }\n\n /**\n * Saves the token and associated user or admin model.\n */\n public save(token: string, model?: RecordModel | AdminModel | null): void {\n this._token = token || '';\n this._model = model || null;\n this.notify();\n }\n\n /**\n * Clears the current authentication state.\n */\n public clear(): void {\n this._token = '';\n this._model = null;\n this.notify();\n }\n\n /**\n * Subscribes to changes in authentication state (token or model).\n * Returns an unbind function.\n */\n public onChange(callback: AuthChangeListener, fireImmediately = false): () => void {\n this._listeners.add(callback);\n if (fireImmediately) {\n try {\n callback(this._token, this._model);\n } catch (err) {\n console.error('[AuthStore] Error in immediate onChange listener:', err);\n }\n }\n\n return () => {\n this._listeners.delete(callback);\n };\n }\n\n /**\n * Triggers all subscribed change listeners.\n */\n protected notify(): void {\n for (const listener of this._listeners) {\n try {\n listener(this._token, this._model);\n } catch (err) {\n console.error('[AuthStore] Error in onChange listener:', err);\n }\n }\n }\n}\n", "import { BaseAuthStore } from './BaseAuthStore';\nimport type { RecordModel, AdminModel } from '../types';\n\nexport interface StorageLike {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n}\n\nconst DEFAULT_STORAGE_KEY = 'nodestack_auth';\n\n/**\n * Storage-backed AuthStore that syncs token and model with localStorage\n * (or any custom StorageLike object, such as sessionStorage or AsyncStorage).\n * Safely degrades to memory if storage is not available.\n */\nexport class LocalAuthStore extends BaseAuthStore {\n private storageKey: string;\n private storage?: StorageLike;\n\n constructor(storageKey: string = DEFAULT_STORAGE_KEY, customStorage?: StorageLike) {\n super();\n this.storageKey = storageKey;\n\n if (customStorage) {\n this.storage = customStorage;\n } else if (typeof window !== 'undefined' && window.localStorage) {\n this.storage = window.localStorage;\n }\n\n this.loadInitial();\n }\n\n private loadInitial(): void {\n if (!this.storage) return;\n\n try {\n const raw = this.storage.getItem(this.storageKey);\n if (raw) {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed.token === 'string') {\n this._token = parsed.token;\n this._model = parsed.model || null;\n }\n }\n } catch {\n // Ignore parse or storage errors\n }\n }\n\n public override save(token: string, model?: RecordModel | AdminModel | null): void {\n super.save(token, model);\n\n if (this.storage) {\n try {\n this.storage.setItem(\n this.storageKey,\n JSON.stringify({\n token: this._token,\n model: this._model,\n })\n );\n } catch {\n // Storage might be full or disabled\n }\n }\n }\n\n public override clear(): void {\n super.clear();\n\n if (this.storage) {\n try {\n this.storage.removeItem(this.storageKey);\n } catch {\n // Ignore storage error\n }\n }\n }\n}\n", "export interface ClientResponseErrorOptions {\n url?: string;\n status?: number;\n data?: any;\n isAbort?: boolean;\n originalError?: any;\n message?: string;\n}\n\n/**\n * Standardized client response error representing failed HTTP requests\n * or network exceptions when interacting with NodeStack.\n */\nexport class ClientResponseError extends Error {\n public readonly url: string;\n public readonly status: number;\n public readonly data: any;\n public readonly isAbort: boolean;\n public readonly originalError?: any;\n\n constructor(options: ClientResponseErrorOptions = {}) {\n const status = options.status || 0;\n const message =\n options.message ||\n options.data?.message ||\n (status > 0 ? `NodeStack request failed with status ${status}` : 'NodeStack network request failed');\n\n super(message);\n this.name = 'ClientResponseError';\n this.url = options.url || '';\n this.status = status;\n this.data = options.data || {};\n this.isAbort = Boolean(options.isAbort);\n this.originalError = options.originalError;\n\n // Restore prototype chain\n Object.setPrototypeOf(this, ClientResponseError.prototype);\n }\n\n public toJSON() {\n return {\n name: this.name,\n message: this.message,\n url: this.url,\n status: this.status,\n data: this.data,\n isAbort: this.isAbort,\n };\n }\n}\n", "import type { SendOptions } from '../types';\nimport type { BaseAuthStore } from '../auth/BaseAuthStore';\n\nexport interface ClientInterface {\n baseUrl: string;\n authStore: BaseAuthStore;\n send<T = any>(path: string, options?: SendOptions): Promise<T>;\n}\n\n/**\n * Base service class from which all specific domain services inherit.\n */\nexport abstract class BaseService {\n constructor(protected readonly client: ClientInterface) {}\n\n protected send<T = any>(path: string, options: SendOptions = {}): Promise<T> {\n return this.client.send<T>(path, options);\n }\n}\n", "import { BaseService, ClientInterface } from './BaseService';\r\nimport { ClientResponseError } from '../errors/ClientResponseError';\r\nimport type {\r\n ListResult,\r\n QueryOptions,\r\n RecordModel,\r\n RecordAuthResponse,\r\n ImportResult,\r\n RealtimeCallback,\r\n UnsubscribeFunc,\r\n} from '../types';\r\n\r\nexport interface ClientWithRealtime extends ClientInterface {\r\n realtime: {\r\n subscribe<R = any>(topic: string, callback: RealtimeCallback<R>): Promise<UnsubscribeFunc>;\r\n unsubscribe(topic?: string, callback?: RealtimeCallback<any>): Promise<void>;\r\n };\r\n}\r\n\r\n/**\r\n * Service for managing CRUD, authentication, file handling, and subscriptions\r\n * for a specific collection.\r\n */\r\nexport class RecordService<T = RecordModel> extends BaseService {\r\n constructor(\r\n client: ClientWithRealtime,\r\n public readonly collectionName: string\r\n ) {\r\n super(client);\r\n }\r\n\r\n private get clientWithRealtime(): ClientWithRealtime {\r\n return this.client as ClientWithRealtime;\r\n }\r\n\r\n /**\r\n * Returns a paginated list of records matching the query options.\r\n */\r\n public async getList(options?: QueryOptions): Promise<ListResult<T>>;\r\n public async getList(\r\n page?: number,\r\n perPage?: number,\r\n options?: QueryOptions\r\n ): Promise<ListResult<T>>;\r\n public async getList(\r\n pageOrOptions: number | QueryOptions = 1,\r\n perPage = 30,\r\n options: QueryOptions = {}\r\n ): Promise<ListResult<T>> {\r\n let pageNum = 1;\r\n let perPageNum = perPage;\r\n let queryOpts: QueryOptions = options;\r\n\r\n if (typeof pageOrOptions === 'object' && pageOrOptions !== null) {\r\n queryOpts = pageOrOptions;\r\n pageNum = typeof queryOpts.page === 'number' ? queryOpts.page : 1;\r\n perPageNum = typeof queryOpts.perPage === 'number' ? queryOpts.perPage : 30;\r\n } else if (typeof pageOrOptions === 'number') {\r\n pageNum = pageOrOptions;\r\n }\r\n\r\n return this.send<ListResult<T>>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records`,\r\n {\r\n method: 'GET',\r\n query: {\r\n page: pageNum,\r\n perPage: perPageNum,\r\n ...queryOpts,\r\n },\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Fetches and aggregates all records in the collection across multiple pages.\r\n */\r\n public async getFullList(\r\n options: QueryOptions & { batch?: number } = {}\r\n ): Promise<T[]> {\r\n const batch = Math.max(1, Math.min(500, options.batch || 200));\r\n const query = { ...options };\r\n delete query.batch;\r\n\r\n const firstPage = await this.getList(1, batch, query);\r\n const items: T[] = [...firstPage.items];\r\n\r\n if (firstPage.totalPages <= 1) {\r\n return items;\r\n }\r\n\r\n for (let page = 2; page <= firstPage.totalPages; page++) {\r\n const result = await this.getList(page, batch, query);\r\n items.push(...result.items);\r\n }\r\n\r\n return items;\r\n }\r\n\r\n /**\r\n * Returns the first record matching the specified filter expression.\r\n * Throws ClientResponseError(404) if no record matches.\r\n */\r\n public async getFirstListItem(\r\n filter: string,\r\n options: QueryOptions = {}\r\n ): Promise<T> {\r\n const list = await this.getList(1, 1, {\r\n ...options,\r\n filter,\r\n });\r\n\r\n if (!list.items || list.items.length === 0) {\r\n throw new ClientResponseError({\r\n status: 404,\r\n url: `/api/collections/${this.collectionName}/records`,\r\n message: `The requested record was not found in collection '${this.collectionName}'.`,\r\n });\r\n }\r\n\r\n return list.items[0];\r\n }\r\n\r\n /**\r\n * Retrieves a single record by its ID.\r\n */\r\n public async getOne(id: string, options: QueryOptions = {}): Promise<T> {\r\n return this.send<T>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records/${encodeURIComponent(id)}`,\r\n {\r\n method: 'GET',\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Creates a new record in the collection.\r\n * Accepts a plain object or FormData (for file uploads).\r\n */\r\n public async create(\r\n data: Record<string, any> | FormData,\r\n options: QueryOptions = {}\r\n ): Promise<T> {\r\n return this.send<T>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records`,\r\n {\r\n method: 'POST',\r\n body: data,\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Updates an existing record by its ID.\r\n * Accepts a plain object or FormData (for file updates).\r\n */\r\n public async update(\r\n id: string,\r\n data: Record<string, any> | FormData,\r\n options: QueryOptions = {}\r\n ): Promise<T> {\r\n return this.send<T>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records/${encodeURIComponent(id)}`,\r\n {\r\n method: 'PATCH',\r\n body: data,\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Deletes a record by its ID.\r\n */\r\n public async delete(id: string): Promise<boolean> {\r\n await this.send<void>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/records/${encodeURIComponent(id)}`,\r\n {\r\n method: 'DELETE',\r\n }\r\n );\r\n return true;\r\n }\r\n\r\n /**\r\n * Authenticates against an auth collection using identity/email and password.\r\n * On success, automatically persists the token and record to authStore.\r\n */\r\n public async authWithPassword(\r\n identity: string,\r\n password: string\r\n ): Promise<RecordAuthResponse<T>> {\r\n const result = await this.send<RecordAuthResponse<T>>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/auth-with-password`,\r\n {\r\n method: 'POST',\r\n body: { identity, password },\r\n }\r\n );\r\n\r\n if (result && result.token) {\r\n this.client.authStore.save(result.token, result.record as any);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Exports records from the collection as CSV or JSON.\r\n */\r\n public async export(\r\n format: 'csv' | 'json' = 'csv',\r\n options: QueryOptions = {}\r\n ): Promise<string> {\r\n return this.send<string>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/export`,\r\n {\r\n method: 'GET',\r\n query: {\r\n ...options,\r\n format,\r\n },\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Imports records into the collection.\r\n */\r\n public async import(\r\n data: any[] | FormData | Blob | string,\r\n options: { continueOnError?: boolean } = {}\r\n ): Promise<ImportResult> {\r\n return this.send<ImportResult>(\r\n `/api/collections/${encodeURIComponent(this.collectionName)}/import`,\r\n {\r\n method: 'POST',\r\n body: data,\r\n query: options,\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Subscribes to realtime events on this collection or a specific record ID.\r\n *\r\n * Example:\r\n * // Listen to all records in collection:\r\n * client.collection('posts').subscribe('*', (e) => console.log(e.action, e.record));\r\n *\r\n * // Listen to single record changes:\r\n * client.collection('posts').subscribe('record_id_123', (e) => console.log(e.action, e.record));\r\n */\r\n public async subscribe(\r\n topicOrCallback: string | RealtimeCallback<T>,\r\n callback?: RealtimeCallback<T>\r\n ): Promise<UnsubscribeFunc> {\r\n let topic = '*';\r\n let cb: RealtimeCallback<T>;\r\n\r\n if (typeof topicOrCallback === 'function') {\r\n topic = '*';\r\n cb = topicOrCallback;\r\n } else {\r\n topic = topicOrCallback;\r\n cb = callback!;\r\n }\r\n\r\n const fullTopic = topic === '*' ? this.collectionName : `${this.collectionName}/${topic}`;\r\n return this.clientWithRealtime.realtime.subscribe<T>(fullTopic, cb);\r\n }\r\n\r\n /**\r\n * Unsubscribes from realtime events for this collection.\r\n */\r\n public async unsubscribe(topic?: string): Promise<void> {\r\n const fullTopic = !topic || topic === '*' ? this.collectionName : `${this.collectionName}/${topic}`;\r\n return this.clientWithRealtime.realtime.unsubscribe(fullTopic);\r\n }\r\n}\r\n", "import { BaseService } from './BaseService';\n\nexport interface FileUrlOptions {\n download?: boolean;\n token?: string | boolean;\n collection?: string;\n}\n\n/**\n * Service for generating file URLs for assets uploaded to NodeStack.\n */\nexport class FileService extends BaseService {\n /**\n * Generates a fully qualified URL to an uploaded file.\n *\n * @param record - Record object or record ID string\n * @param filename - Name of the file stored on the record\n * @param options - Additional options (download flag, auth token, collection override)\n */\n public getUrl(\n record: { id: string; collection?: string; collectionName?: string; [key: string]: any } | string,\n filename: string,\n options: FileUrlOptions = {}\n ): string {\n if (!filename) return '';\n\n let recordId = '';\n let collectionName = options.collection || '';\n\n if (typeof record === 'string') {\n recordId = record;\n } else if (record && typeof record === 'object') {\n recordId = record.id || '';\n collectionName =\n collectionName ||\n record.collection ||\n record.collectionName ||\n record['@collectionName'] ||\n '';\n }\n\n if (!recordId) {\n throw new Error('[FileService] A valid record or recordId is required to construct a file URL.');\n }\n\n if (!collectionName) {\n throw new Error(\n '[FileService] Collection name is required. Either provide a record with collection info or pass options.collection.'\n );\n }\n\n const cleanBase = (this.client.baseUrl || '').replace(/\\/+$/, '');\n const cleanCol = encodeURIComponent(collectionName);\n const cleanId = encodeURIComponent(recordId);\n const cleanFile = encodeURIComponent(filename);\n\n let url = `${cleanBase}/api/files/${cleanCol}/${cleanId}/${cleanFile}`;\n\n const queryParts: string[] = [];\n\n if (options.download) {\n queryParts.push('download=1');\n }\n\n // Attach token if requested\n if (typeof options.token === 'string' && options.token) {\n queryParts.push(`token=${encodeURIComponent(options.token)}`);\n } else if (options.token === true && this.client.authStore.token) {\n queryParts.push(`token=${encodeURIComponent(this.client.authStore.token)}`);\n }\n\n if (queryParts.length > 0) {\n url += `?${queryParts.join('&')}`;\n }\n\n return url;\n }\n}\n", "import { BaseService, ClientInterface } from './BaseService';\nimport type { RealtimeEvent, RealtimeCallback, UnsubscribeFunc } from '../types';\n\n/**\n * Multiplexed Realtime Server-Sent Events (SSE) service.\n * Manages a single persistent SSE connection and dispatches events to subscribed listeners.\n */\nexport class RealtimeService extends BaseService {\n private eventSource: any = null;\n private clientId: string = '';\n private isConnecting: boolean = false;\n private connectPromise: Promise<string> | null = null;\n private reconnectTimeout: any = null;\n private reconnectAttempts: number = 0;\n private customEventSource?: any;\n\n // Map of topic -> Set of callbacks\n private subscriptions: Map<string, Set<RealtimeCallback<any>>> = new Map();\n\n // Set of registered event names on the active EventSource\n private registeredEventNames: Set<string> = new Set();\n\n constructor(client: ClientInterface, customEventSource?: any) {\n super(client);\n this.customEventSource = customEventSource;\n }\n\n /**\n * Returns whether there is an active EventSource connection.\n */\n public get isConnected(): boolean {\n return Boolean(this.eventSource && this.clientId);\n }\n\n /**\n * Resolves the EventSource constructor available in the current environment.\n */\n private getEventSourceConstructor(): any {\n if (this.customEventSource) {\n return this.customEventSource;\n }\n if (typeof window !== 'undefined' && (window as any).EventSource) {\n return (window as any).EventSource;\n }\n if (typeof globalThis !== 'undefined' && (globalThis as any).EventSource) {\n return (globalThis as any).EventSource;\n }\n throw new Error(\n '[RealtimeService] EventSource is not supported natively in this environment. ' +\n 'Please pass an EventSource polyfill to ClientOptions (e.g. from the \"eventsource\" package).'\n );\n }\n\n /**\n * Connects to the SSE stream if not already connected.\n * Returns the connected clientId.\n */\n public async connect(): Promise<string> {\n if (this.clientId && this.eventSource) {\n return this.clientId;\n }\n\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.connectPromise = new Promise<string>((resolve, reject) => {\n try {\n const EventSourceClass = this.getEventSourceConstructor();\n const base = (this.client.baseUrl || '').replace(/\\/+$/, '');\n let url = `${base}/api/realtime`;\n\n if (this.client.authStore.token) {\n url += `?token=${encodeURIComponent(this.client.authStore.token)}`;\n }\n\n this.eventSource = new EventSourceClass(url);\n\n const handleConnect = async (event: any) => {\n try {\n const data = JSON.parse(event.data);\n this.clientId = data.clientId;\n this.reconnectAttempts = 0;\n\n // Re-apply any existing subscriptions on the server\n await this.syncSubscriptions();\n\n resolve(this.clientId);\n } catch (err) {\n reject(err);\n }\n };\n\n this.eventSource.addEventListener('NS_CONNECT', handleConnect);\n this.eventSource.addEventListener('NB_CONNECT', handleConnect);\n\n this.eventSource.onerror = (err: any) => {\n if (!this.clientId) {\n reject(err);\n }\n this.handleDisconnect();\n };\n\n // Bind listeners for all known collection topics\n this.bindActiveTopics();\n } catch (err) {\n this.connectPromise = null;\n reject(err);\n }\n }).finally(() => {\n this.connectPromise = null;\n });\n\n return this.connectPromise;\n }\n\n /**\n * Subscribes to realtime updates for a collection or record.\n *\n * @param topic - Collection name ('posts'), wildcard ('*'), or specific record ('posts/rec_123')\n * @param callback - Event listener callback\n * @returns Unsubscribe function\n */\n public async subscribe<T = any>(\n topic: string,\n callback: RealtimeCallback<T>\n ): Promise<UnsubscribeFunc> {\n const cleanTopic = (topic || '*').trim();\n\n if (!this.subscriptions.has(cleanTopic)) {\n this.subscriptions.set(cleanTopic, new Set());\n }\n\n this.subscriptions.get(cleanTopic)!.add(callback);\n\n // If connected, sync subscriptions with server\n if (this.isConnected) {\n this.bindTopicListener(cleanTopic);\n await this.syncSubscriptions();\n } else {\n // Connect and sync\n await this.connect();\n }\n\n return () => this.unsubscribe(cleanTopic, callback);\n }\n\n /**\n * Unsubscribes from a topic or specific callback.\n */\n public async unsubscribe(topic?: string, callback?: RealtimeCallback<any>): Promise<void> {\n if (!topic) {\n // Unsubscribe all\n this.subscriptions.clear();\n if (this.isConnected) {\n await this.syncSubscriptions();\n }\n return;\n }\n\n const cleanTopic = topic.trim();\n if (!this.subscriptions.has(cleanTopic)) {\n return;\n }\n\n if (callback) {\n this.subscriptions.get(cleanTopic)!.delete(callback);\n if (this.subscriptions.get(cleanTopic)!.size === 0) {\n this.subscriptions.delete(cleanTopic);\n }\n } else {\n this.subscriptions.delete(cleanTopic);\n }\n\n if (this.isConnected) {\n await this.syncSubscriptions();\n }\n }\n\n /**\n * Closes the SSE connection and clears state.\n */\n public disconnect(): void {\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.eventSource) {\n try {\n this.eventSource.close();\n } catch {}\n this.eventSource = null;\n }\n\n this.clientId = '';\n this.registeredEventNames.clear();\n }\n\n /**\n * Synchronizes active subscriptions with the backend via POST /api/realtime.\n */\n private async syncSubscriptions(): Promise<void> {\n if (!this.clientId) return;\n\n const topics = Array.from(this.subscriptions.keys());\n\n try {\n await this.client.send('/api/realtime', {\n method: 'POST',\n body: {\n clientId: this.clientId,\n subscriptions: topics.length > 0 ? topics : ['__noop__'],\n },\n });\n } catch (err) {\n console.warn('[RealtimeService] Failed to sync subscriptions with server:', err);\n }\n }\n\n /**\n * Binds an EventSource listener for the collection corresponding to a topic.\n */\n private bindTopicListener(topic: string): void {\n if (!this.eventSource) return;\n\n // Determine collection name\n const collectionName = topic.includes('/') ? topic.split('/')[0] : topic;\n\n if (this.registeredEventNames.has(collectionName)) {\n return;\n }\n\n this.registeredEventNames.add(collectionName);\n\n this.eventSource.addEventListener(collectionName, (event: any) => {\n try {\n const payload: RealtimeEvent<any> = JSON.parse(event.data);\n this.dispatchEvent(collectionName, payload);\n } catch (err) {\n console.error(`[RealtimeService] Error handling event for ${collectionName}:`, err);\n }\n });\n }\n\n private bindActiveTopics(): void {\n for (const topic of this.subscriptions.keys()) {\n this.bindTopicListener(topic);\n }\n }\n\n /**\n * Dispatches received SSE events to matching subscribed listeners.\n */\n private dispatchEvent(collectionName: string, event: RealtimeEvent<any>): void {\n const recordId = event.record?.id;\n\n // Check wildcard subscription '*'\n this.triggerListeners('*', event);\n\n // Check collection subscription e.g. 'posts' or 'posts/*'\n this.triggerListeners(collectionName, event);\n this.triggerListeners(`${collectionName}/*`, event);\n\n // Check record-specific subscription e.g. 'posts/rec_123'\n if (recordId) {\n this.triggerListeners(`${collectionName}/${recordId}`, event);\n }\n }\n\n private triggerListeners(topic: string, event: RealtimeEvent<any>): void {\n const callbacks = this.subscriptions.get(topic);\n if (!callbacks || callbacks.size === 0) return;\n\n for (const cb of callbacks) {\n try {\n cb(event);\n } catch (err) {\n console.error(`[RealtimeService] Error in realtime listener for ${topic}:`, err);\n }\n }\n }\n\n /**\n * Handles disconnections and schedules automatic reconnection.\n */\n private handleDisconnect(): void {\n if (this.reconnectTimeout) return;\n\n this.disconnect();\n\n // Exponential backoff up to 10 seconds\n const delay = Math.min(10000, 500 * Math.pow(1.5, this.reconnectAttempts));\n this.reconnectAttempts++;\n\n this.reconnectTimeout = setTimeout(() => {\n this.reconnectTimeout = null;\n if (this.subscriptions.size > 0) {\n this.connect().catch(() => {});\n }\n }, delay);\n }\n}\n", "import { BaseService } from './BaseService';\nimport type { AdminAuthResponse, AdminModel } from '../types';\n\n/**\n * Service for administrative and superuser actions.\n */\nexport class AdminService extends BaseService {\n /**\n * Checks whether at least one superuser / admin account exists in NodeStack.\n */\n public async hasAdmins(): Promise<boolean> {\n const res = await this.send<{ hasAdmins: boolean }>('/api/admins/has-admins', {\n method: 'GET',\n });\n return Boolean(res?.hasAdmins);\n }\n\n /**\n * Creates the initial superuser account during first-time setup.\n * Automatically persists the returned admin token and model to authStore.\n */\n public async createInitial(email: string, password: string): Promise<AdminAuthResponse> {\n const res = await this.send<AdminAuthResponse>('/api/admins/create-initial', {\n method: 'POST',\n body: { email, password },\n });\n\n if (res?.token) {\n this.client.authStore.save(res.token, res.admin);\n }\n\n return res;\n }\n\n /**\n * Authenticates a superuser / admin using email and password.\n * Automatically persists the returned admin token and model to authStore.\n */\n public async authWithPassword(identity: string, password: string): Promise<AdminAuthResponse> {\n const res = await this.send<AdminAuthResponse>('/api/admins/auth-with-password', {\n method: 'POST',\n body: { identity, password },\n });\n\n if (res?.token) {\n this.client.authStore.save(res.token, res.admin);\n }\n\n return res;\n }\n\n /**\n * Retrieves the currently authenticated superuser's profile.\n */\n public async getMe(): Promise<AdminModel> {\n return this.send<AdminModel>('/api/admins/me', {\n method: 'GET',\n });\n }\n}\n", "import { BaseService } from './BaseService';\r\n\r\n/**\r\n * Service for managing collection schema definitions (Admin only).\r\n */\r\nexport class CollectionService extends BaseService {\r\n /**\r\n * Retrieves all collection schema models.\r\n */\r\n public async getList(): Promise<any[]> {\r\n const res = await this.send<{ items: any[]; totalItems: number } | any[]>('/api/collections', {\r\n method: 'GET',\r\n });\r\n return Array.isArray(res) ? res : res?.items || [];\r\n }\r\n\r\n /**\r\n * Retrieves a single collection schema by name or ID.\r\n */\r\n public async getOne(nameOrId: string): Promise<any> {\r\n return this.send<any>(`/api/collections/${encodeURIComponent(nameOrId)}`, {\r\n method: 'GET',\r\n });\r\n }\r\n\r\n /**\r\n * Creates a new collection schema.\r\n */\r\n public async create(data: any): Promise<any> {\r\n return this.send<any>('/api/collections', {\r\n method: 'POST',\r\n body: data,\r\n });\r\n }\r\n\r\n /**\r\n * Updates an existing collection schema.\r\n */\r\n public async update(nameOrId: string, data: any): Promise<any> {\r\n return this.send<any>(`/api/collections/${encodeURIComponent(nameOrId)}`, {\r\n method: 'PATCH',\r\n body: data,\r\n });\r\n }\r\n\r\n /**\r\n * Deletes a collection schema and its corresponding SQLite table.\r\n */\r\n public async delete(nameOrId: string): Promise<boolean> {\r\n await this.send<void>(`/api/collections/${encodeURIComponent(nameOrId)}`, {\r\n method: 'DELETE',\r\n });\r\n return true;\r\n }\r\n\r\n /**\r\n * Infers schema fields, field types, and sample records from raw JSON (object or array).\r\n */\r\n public async inferSchema(data: any): Promise<{\r\n suggestedName?: string;\r\n fields: any[];\r\n recordCount: number;\r\n sampleRecords: any[];\r\n }> {\r\n return this.send('/api/collections/infer-schema', {\r\n method: 'POST',\r\n body: { data },\r\n });\r\n }\r\n\r\n /**\r\n * \"Paste JSON \u2192 Instant API\": Infers field types, creates collection and SQLite columns,\r\n * and populates all records within 1 second.\r\n */\r\n public async importJson(\r\n name: string,\r\n data: any,\r\n options: {\r\n type?: 'base' | 'auth';\r\n schemaOverrides?: any[];\r\n listRule?: string | null;\r\n viewRule?: string | null;\r\n createRule?: string | null;\r\n updateRule?: string | null;\r\n deleteRule?: string | null;\r\n } = {}\r\n ): Promise<{\r\n success: boolean;\r\n collection: any;\r\n recordCount: number;\r\n records: any[];\r\n inferredFields: any[];\r\n durationMs: number;\r\n }> {\r\n return this.send('/api/collections/import-json', {\r\n method: 'POST',\r\n body: {\r\n name,\r\n data,\r\n ...options,\r\n },\r\n });\r\n }\r\n}\r\n", "import { BaseService } from './BaseService';\r\nimport type {\r\n DemoSnapshotStatus,\r\n DemoSnapshotMetadata,\r\n DemoResetResult,\r\n} from '../types';\r\n\r\n/**\r\n * Service for freezing baseline demo state and 1-click restore (\"Reset to Demo State\").\r\n */\r\nexport class DemoService extends BaseService {\r\n /**\r\n * Retrieves the current snapshot availability, metadata, and live drift information.\r\n */\r\n public async getStatus(): Promise<DemoSnapshotStatus> {\r\n return this.send<DemoSnapshotStatus>('/api/demo/status', {\r\n method: 'GET',\r\n });\r\n }\r\n\r\n /**\r\n * Freezes current database & file storage state as the demo baseline.\r\n */\r\n public async snapshot(options?: { name?: string; description?: string }): Promise<DemoSnapshotMetadata> {\r\n return this.send<DemoSnapshotMetadata>('/api/demo/snapshot', {\r\n method: 'POST',\r\n body: options || {},\r\n });\r\n }\r\n\r\n /**\r\n * Restores the exact pristine demo state in one click.\r\n */\r\n public async reset(): Promise<DemoResetResult> {\r\n return this.send<DemoResetResult>('/api/demo/reset', {\r\n method: 'POST',\r\n });\r\n }\r\n\r\n /**\r\n * Deletes the frozen demo snapshot.\r\n */\r\n public async clear(): Promise<void> {\r\n return this.send<void>('/api/demo/snapshot', {\r\n method: 'DELETE',\r\n });\r\n }\r\n}\r\n", "import { BaseService } from './BaseService';\nimport type {\n WebhookModel,\n WebhookCreateOptions,\n WebhookUpdateOptions,\n WebhookDeliveryLog,\n WebhookQueryOptions,\n DeliveryQueryOptions,\n DeliveryListResult,\n WebhookStatsResult,\n WebhookClearDeliveriesResult,\n} from '../types';\n\n/**\n * Computes an HMAC-SHA256 signature for a payload and secret string.\n */\nexport function computeWebhookSignature(payload: string | object, secret: string): string {\n const str = typeof payload === 'string' ? payload : JSON.stringify(payload);\n try {\n const nodeCrypto = typeof require !== 'undefined' ? require('crypto') : (globalThis as any)?.crypto;\n if (nodeCrypto && typeof nodeCrypto.createHmac === 'function') {\n return nodeCrypto.createHmac('sha256', secret).update(str, 'utf8').digest('hex');\n }\n } catch {}\n throw new Error('[NodeStackClient] HMAC-SHA256 computation requires crypto module.');\n}\n\n/**\n * Verifies an incoming X-NodeStack-Signature header against the expected secret.\n * Tolerates both raw 64-char hex strings and 'sha256=' / 'sha256:' prefixes.\n * Uses constant-time comparison to mitigate timing attacks.\n */\nexport function verifyWebhookSignature(\n payload: string | object,\n signatureHeader: string,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false;\n let expected = '';\n try {\n expected = computeWebhookSignature(payload, secret);\n } catch {\n return false;\n }\n\n let cleanHeader = signatureHeader.trim();\n if (cleanHeader.startsWith('sha256=')) {\n cleanHeader = cleanHeader.substring(7);\n } else if (cleanHeader.startsWith('sha256:')) {\n cleanHeader = cleanHeader.substring(7);\n }\n\n if (cleanHeader.length !== expected.length) return false;\n\n try {\n const nodeCrypto = typeof require !== 'undefined' ? require('crypto') : null;\n if (nodeCrypto && typeof nodeCrypto.timingSafeEqual === 'function' && typeof Buffer !== 'undefined') {\n return nodeCrypto.timingSafeEqual(Buffer.from(cleanHeader, 'hex'), Buffer.from(expected, 'hex'));\n }\n } catch {}\n\n // Constant-time string comparison fallback\n let diff = 0;\n for (let i = 0; i < cleanHeader.length; i++) {\n diff |= cleanHeader.charCodeAt(i) ^ expected.charCodeAt(i);\n }\n return diff === 0;\n}\n\n/**\n * Service for managing outbound webhooks, inspecting deliveries, and manual retry (Admin only).\n */\nexport class WebhookService extends BaseService {\n /**\n * Retrieves all configured outbound webhooks.\n */\n public async getList(options: WebhookQueryOptions = {}): Promise<WebhookModel[]> {\n const res = await this.send<WebhookModel[]>('/api/webhooks', {\n method: 'GET',\n query: options,\n });\n return Array.isArray(res) ? res : [];\n }\n\n /**\n * Retrieves a single webhook by ID.\n */\n public async getOne(id: string): Promise<WebhookModel> {\n return this.send<WebhookModel>(`/api/webhooks/${encodeURIComponent(id)}`, {\n method: 'GET',\n });\n }\n\n /**\n * Creates a new outbound webhook configuration.\n */\n public async create(data: WebhookCreateOptions): Promise<WebhookModel> {\n return this.send<WebhookModel>('/api/webhooks', {\n method: 'POST',\n body: data,\n });\n }\n\n /**\n * Updates an existing webhook configuration.\n */\n public async update(id: string, data: WebhookUpdateOptions): Promise<WebhookModel> {\n return this.send<WebhookModel>(`/api/webhooks/${encodeURIComponent(id)}`, {\n method: 'PATCH',\n body: data,\n });\n }\n\n /**\n * Deletes a configured webhook by ID.\n */\n public async delete(id: string): Promise<boolean> {\n await this.send<void>(`/api/webhooks/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n });\n return true;\n }\n\n /**\n * Dispatches a live test event to the target webhook endpoint with an optional payload.\n */\n public async test(id: string, payload?: any): Promise<WebhookDeliveryLog> {\n return this.send<WebhookDeliveryLog>(`/api/webhooks/${encodeURIComponent(id)}/test`, {\n method: 'POST',\n body: payload !== undefined ? { payload } : {},\n });\n }\n\n /**\n * Retrieves overall webhook health and delivery statistics.\n */\n public async getStats(): Promise<WebhookStatsResult> {\n return this.send<WebhookStatsResult>('/api/webhooks/stats', {\n method: 'GET',\n });\n }\n\n /**\n * Queries paginated webhook delivery logs with optional filtering by webhook ID, collection, status, or search.\n */\n public async getDeliveries(options: DeliveryQueryOptions = {}): Promise<DeliveryListResult> {\n return this.send<DeliveryListResult>('/api/webhooks/deliveries', {\n method: 'GET',\n query: options,\n });\n }\n\n /**\n * Retrieves complete delivery log details including headers and request/response payloads.\n */\n public async getDelivery(id: string): Promise<WebhookDeliveryLog> {\n return this.send<WebhookDeliveryLog>(`/api/webhooks/deliveries/${encodeURIComponent(id)}`, {\n method: 'GET',\n });\n }\n\n /**\n * Manually retries a failed delivery attempt to its target endpoint.\n */\n public async retryDelivery(id: string): Promise<WebhookDeliveryLog> {\n return this.send<WebhookDeliveryLog>(`/api/webhooks/deliveries/${encodeURIComponent(id)}/retry`, {\n method: 'POST',\n });\n }\n\n /**\n * Clears delivery history logs. If olderThanDays is specified, only deletes logs older than that many days.\n */\n public async clearDeliveries(olderThanDays?: number): Promise<WebhookClearDeliveriesResult> {\n const query: Record<string, any> = {};\n if (olderThanDays !== undefined && olderThanDays !== null) {\n query.olderThanDays = olderThanDays;\n }\n return this.send<WebhookClearDeliveriesResult>('/api/webhooks/deliveries', {\n method: 'DELETE',\n query,\n });\n }\n\n /**\n * Verifies an incoming X-NodeStack-Signature header against the expected secret.\n */\n public verifySignature(payload: string | object, signatureHeader: string, secret: string): boolean {\n return verifyWebhookSignature(payload, signatureHeader, secret);\n }\n\n /**\n * Computes an HMAC-SHA256 signature for a payload and secret string.\n */\n public computeSignature(payload: string | object, secret: string): string {\n return computeWebhookSignature(payload, secret);\n }\n\n public static verifySignature = verifyWebhookSignature;\n public static computeSignature = computeWebhookSignature;\n}\n", "import { BaseAuthStore } from './auth/BaseAuthStore';\nimport { LocalAuthStore } from './auth/LocalAuthStore';\nimport { ClientResponseError } from './errors/ClientResponseError';\nimport { RecordService } from './services/RecordService';\nimport { FileService } from './services/FileService';\nimport { RealtimeService } from './services/RealtimeService';\nimport { AdminService } from './services/AdminService';\nimport { CollectionService } from './services/CollectionService';\nimport { DemoService } from './services/DemoService';\nimport { WebhookService } from './services/WebhookService';\nimport type {\n ClientOptions,\n SendOptions,\n RecordModel,\n ChaosOptions,\n} from './types';\n\n/**\n * Main NodeStack Client SDK entry point.\n */\nexport class NodeStackClient<TCollections extends Record<string, any> = Record<string, RecordModel>> {\n public readonly baseUrl: string;\n public readonly authStore: BaseAuthStore;\n public readonly files: FileService;\n public readonly realtime: RealtimeService;\n public readonly admins: AdminService;\n public readonly collections: CollectionService;\n public readonly demo: DemoService;\n public readonly webhooks: WebhookService;\n\n private customFetch?: typeof fetch;\n private defaultHeaders: Record<string, string>;\n private defaultTimeout: number;\n private chaosOptions: ChaosOptions | null = null;\n private recordServices: Map<string, RecordService<any>> = new Map();\n\n constructor(baseUrl: string = '/', options: ClientOptions = {}) {\n this.baseUrl = (baseUrl || '/').replace(/\\/+$/, '');\n this.authStore = options.authStore || new LocalAuthStore();\n this.customFetch = options.fetch;\n this.defaultHeaders = options.headers || {};\n this.defaultTimeout = options.timeout || 120000; // 2 minutes default\n this.chaosOptions = options.chaos ? { ...options.chaos } : null;\n\n this.files = new FileService(this);\n this.realtime = new RealtimeService(this, options.EventSource);\n this.admins = new AdminService(this);\n this.collections = new CollectionService(this);\n this.demo = new DemoService(this);\n this.webhooks = new WebhookService(this);\n }\n\n /**\n * Dynamically configure latency & chaos simulation options for all future requests.\n * Pass null to disable client-side chaos injection.\n */\n public setChaos(options: ChaosOptions | null): void {\n this.chaosOptions = options ? { ...options } : null;\n }\n\n /**\n * Get active chaos simulation options.\n */\n public getChaos(): ChaosOptions | null {\n return this.chaosOptions ? { ...this.chaosOptions } : null;\n }\n\n /**\n * Returns a RecordService for interacting with a specific collection.\n * If a schema map type is provided to NodeStackClient, collection names\n * and record response types are automatically inferred and type-safe.\n */\n public collection<K extends keyof TCollections>(name: K): RecordService<TCollections[K]>;\n public collection<T = RecordModel>(name: string): RecordService<T>;\n public collection(name: string): RecordService<any> {\n const colName = String(name);\n let service = this.recordServices.get(colName);\n if (!service) {\n service = new RecordService(this, colName);\n this.recordServices.set(colName, service);\n }\n return service;\n }\n\n /**\n * Sends an HTTP request to NodeStack with automatic authentication,\n * header injection, query serialization, and standardized error handling.\n */\n public async send<T = any>(path: string, options: SendOptions = {}): Promise<T> {\n const fetchFn = this.customFetch || (typeof fetch !== 'undefined' ? fetch : null);\n if (!fetchFn) {\n throw new Error(\n '[NodeStackClient] fetch is not available in this environment. ' +\n 'Please pass a custom fetch implementation to ClientOptions.'\n );\n }\n\n // 1. Build URL & Query parameters\n let url = path.startsWith('http://') || path.startsWith('https://')\n ? path\n : `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n\n if (options.query) {\n const searchParams = new URLSearchParams();\n for (const [key, val] of Object.entries(options.query)) {\n if (val === undefined || val === null) continue;\n searchParams.append(key, String(val));\n }\n const queryStr = searchParams.toString();\n if (queryStr) {\n url += (url.includes('?') ? '&' : '?') + queryStr;\n }\n }\n\n // 2. Prepare headers\n const headers: Record<string, string> = {\n ...this.defaultHeaders,\n ...(options.headers || {}),\n };\n\n if (this.authStore.token && !headers['Authorization'] && !headers['authorization']) {\n headers['Authorization'] = `Bearer ${this.authStore.token}`;\n }\n\n // 2b. Inject Latency & Chaos simulation headers\n const effectiveChaos: ChaosOptions = {\n ...(this.chaosOptions || {}),\n ...(options.chaos || {}),\n ...(options.mockDelay !== undefined ? { delay: options.mockDelay } : {}),\n ...(options.mockError !== undefined ? { errorStatus: options.mockError } : {}),\n ...(options.mockFailRate !== undefined ? { failRate: options.mockFailRate } : {}),\n ...(options.mockJitter !== undefined ? { jitter: options.mockJitter } : {}),\n };\n\n if (effectiveChaos.delay !== undefined && !headers['x-mock-delay'] && !headers['mock-delay']) {\n headers['x-mock-delay'] = String(effectiveChaos.delay);\n }\n if (effectiveChaos.errorStatus !== undefined && !headers['x-mock-error'] && !headers['mock-error']) {\n headers['x-mock-error'] = String(effectiveChaos.errorStatus);\n }\n if (effectiveChaos.failRate !== undefined && !headers['x-mock-fail-rate'] && !headers['mock-fail-rate']) {\n headers['x-mock-fail-rate'] = String(effectiveChaos.failRate);\n }\n if (effectiveChaos.jitter !== undefined && !headers['x-mock-jitter'] && !headers['mock-jitter']) {\n headers['x-mock-jitter'] = String(effectiveChaos.jitter);\n }\n if (effectiveChaos.errorMessage && !headers['x-mock-error-message'] && !headers['mock-error-message']) {\n headers['x-mock-error-message'] = String(effectiveChaos.errorMessage);\n }\n\n // 3. Serialize body\n let body: any = options.body;\n const isFormData = typeof FormData !== 'undefined' && body instanceof FormData;\n const isBlob = typeof Blob !== 'undefined' && body instanceof Blob;\n\n if (body !== undefined && body !== null) {\n if (isFormData) {\n // Let the environment compute multipart boundary headers automatically\n delete headers['Content-Type'];\n delete headers['content-type'];\n } else if (isBlob || typeof body === 'string') {\n // Leave body as-is\n } else if (typeof body === 'object') {\n headers['Content-Type'] = 'application/json';\n body = JSON.stringify(body);\n }\n }\n\n // 4. Handle abort signal & timeout\n let signal = options.signal;\n let timeoutId: any = null;\n\n if (!signal && this.defaultTimeout > 0 && typeof AbortController !== 'undefined') {\n const controller = new AbortController();\n signal = controller.signal;\n timeoutId = setTimeout(() => controller.abort(), this.defaultTimeout);\n }\n\n try {\n const response = await fetchFn(url, {\n ...options,\n headers,\n body,\n signal,\n });\n\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // Handle 204 No Content\n if (response.status === 204) {\n return null as any;\n }\n\n const contentType = response.headers.get('content-type') || '';\n let data: any;\n\n if (contentType.includes('application/json')) {\n data = await response.json().catch(() => ({}));\n } else {\n data = await response.text();\n }\n\n if (!response.ok) {\n throw new ClientResponseError({\n url,\n status: response.status,\n data,\n message: typeof data === 'object' && data?.message ? data.message : undefined,\n });\n }\n\n return data as T;\n } catch (err: any) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n if (err instanceof ClientResponseError) {\n throw err;\n }\n\n const isAbort =\n err?.name === 'AbortError' ||\n (signal && signal.aborted) ||\n Boolean(options.signal && options.signal.aborted);\n\n throw new ClientResponseError({\n url,\n status: isAbort ? 0 : 0,\n isAbort,\n originalError: err,\n message: isAbort ? 'Request was aborted' : err?.message || 'Network request failed',\n });\n }\n }\n\n /**\n * Checks backend system health.\n */\n public async health(): Promise<{ status: string; [key: string]: any }> {\n return this.send('/api/health', { method: 'GET' });\n }\n\n /**\n * Retrieves server runtime settings.\n */\n public async settings(): Promise<any> {\n return this.send('/api/settings', { method: 'GET' });\n }\n\n /**\n * Fetches request logs (Admin only).\n */\n public async logs(page = 1, perPage = 50): Promise<any> {\n return this.send('/api/logs', {\n method: 'GET',\n query: { page, perPage },\n });\n }\n\n /**\n * Fetches system metrics & analytics (Admin only).\n */\n public async metrics(): Promise<any> {\n return this.send('/api/metrics', { method: 'GET' });\n }\n}\n", "import { BaseAuthStore } from './BaseAuthStore';\n\n/**\n * In-memory authentication store.\n * Ideal for Node.js scripts, server-side rendering (SSR), and testing environments.\n */\nexport class MemoryAuthStore extends BaseAuthStore {\n // Inherits default in-memory behavior of BaseAuthStore\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -11,5 +11,6 @@ export { RealtimeService } from './services/RealtimeService';
11
11
  export { AdminService } from './services/AdminService';
12
12
  export { CollectionService } from './services/CollectionService';
13
13
  export { DemoService } from './services/DemoService';
14
+ export { WebhookService, computeWebhookSignature, verifyWebhookSignature, } from './services/WebhookService';
14
15
  export * from './types';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AAGtD,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAG/F,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AAGtD,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAG/F,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,2BAA2B,CAAC;AAGnC,cAAc,SAAS,CAAC"}