@webiny/api-websockets-sql 0.0.0-unstable.b6d7105cee → 6.6.0-alpha.1

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.
@@ -2,6 +2,7 @@ import { WebinyError } from "@webiny/error";
2
2
  import { KnexClient } from "@webiny/api-core-sql";
3
3
  import { ConnectionRegistry } from "@webiny/api-websockets/exports/api.js";
4
4
  import { TableName } from "./TableName/abstractions.js";
5
+ import { toIsoString } from "./toIsoString.js";
5
6
  const BASE_TABLE_NAME = "WebsocketsConnections";
6
7
  class WebsocketsConnectionRegistryImpl {
7
8
  constructor(knex, tableName){
@@ -210,7 +211,7 @@ class WebsocketsConnectionRegistryImpl {
210
211
  },
211
212
  tenant: row.tenant,
212
213
  endpoint: row.endpoint,
213
- connectedOn: row.connectedOn
214
+ connectedOn: toIsoString(row.connectedOn)
214
215
  };
215
216
  }
216
217
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WebsocketsConnectionRegistry.js","sources":["../src/WebsocketsConnectionRegistry.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { KnexClient } from \"@webiny/api-core-sql\";\nimport { ConnectionRegistry } from \"@webiny/api-websockets/exports/api.js\";\nimport { TableName } from \"~/TableName/abstractions.js\";\n\ninterface ConnectionRow {\n connectionId: string;\n identityId: string;\n identityDisplayName: string;\n identityType: string;\n tenant: string;\n endpoint: string;\n connectedOn: string;\n lastSeen: string | null;\n}\n\nconst BASE_TABLE_NAME = \"WebsocketsConnections\";\n\nclass WebsocketsConnectionRegistryImpl implements ConnectionRegistry.Interface {\n private readonly knex;\n private readonly tableName;\n\n public constructor(knex: KnexClient.Interface, tableName: TableName.Interface) {\n this.knex = knex;\n this.tableName = tableName.resolve(BASE_TABLE_NAME);\n }\n\n public async register(\n event: ConnectionRegistry.RegisterParams\n ): Promise<ConnectionRegistry.Data> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const row: ConnectionRow = {\n connectionId: event.connectionId,\n identityId: event.identity.id,\n identityDisplayName: event.identity.displayName,\n identityType: event.identity.type,\n tenant: event.tenant,\n endpoint: event.endpoint,\n connectedOn: event.connectedOn,\n lastSeen: new Date().toISOString()\n };\n\n await this.knex.client<ConnectionRow>(this.tableName).insert(row);\n\n return this.toData(row);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not register websockets connection.\",\n code: \"REGISTER_CONNECTION_ERROR\",\n data: { event }\n });\n }\n }\n\n public async unregister(event: ConnectionRegistry.UnregisterParams): Promise<void> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const existing = await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"connectionId\", event.connectionId)\n .first();\n\n if (!existing) {\n throw new WebinyError(\n `Connection \"${event.connectionId}\" does not exist.`,\n \"CONNECTION_NOT_FOUND\",\n { connectionId: event.connectionId }\n );\n }\n\n await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"connectionId\", event.connectionId)\n .delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not unregister websockets connection.\",\n code: \"UNREGISTER_CONNECTION_ERROR\",\n data: { event }\n });\n }\n }\n\n public async listViaConnections(connections: string[]): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex\n .client<ConnectionRow>(this.tableName)\n .whereIn(\"connectionId\", connections);\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list websockets connections by connection IDs.\",\n code: \"LIST_VIA_CONNECTIONS_ERROR\",\n data: { connections }\n });\n }\n }\n\n public async listViaIdentity(identity: string): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"identityId\", identity);\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list websockets connections by identity.\",\n code: \"LIST_VIA_IDENTITY_ERROR\",\n data: { identity }\n });\n }\n }\n\n public async listViaTenant(tenant: string): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"tenant\", tenant);\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list websockets connections by tenant.\",\n code: \"LIST_VIA_TENANT_ERROR\",\n data: { tenant }\n });\n }\n }\n\n public async listAll(): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex.client<ConnectionRow>(this.tableName).select(\"*\");\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list all websockets connections.\",\n code: \"LIST_ALL_CONNECTIONS_ERROR\"\n });\n }\n }\n\n public async updateLastSeen(connectionId: string): Promise<void> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"connectionId\", connectionId)\n .update({ lastSeen: new Date().toISOString() });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update lastSeen for websockets connection.\",\n code: \"UPDATE_LAST_SEEN_ERROR\",\n data: { connectionId }\n });\n }\n }\n\n public async listStale(olderThan: Date): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const threshold = olderThan.toISOString();\n\n const rows = await this.knex.client<ConnectionRow>(this.tableName).where(qb => {\n qb.where(\"lastSeen\", \"<\", threshold).orWhereNull(\"lastSeen\");\n });\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list stale websockets connections.\",\n code: \"LIST_STALE_CONNECTIONS_ERROR\",\n data: { olderThan }\n });\n }\n }\n\n private async ensureTable(): Promise<void> {\n const exists = await this.knex.client.schema.hasTable(this.tableName);\n if (exists) {\n return;\n }\n\n await this.knex.client.schema.createTable(this.tableName, table => {\n table.text(\"connectionId\").notNullable().primary();\n table.text(\"identityId\").notNullable();\n table.text(\"identityDisplayName\").notNullable();\n table.text(\"identityType\").notNullable();\n table.text(\"tenant\").notNullable();\n table.text(\"endpoint\").notNullable();\n table.datetime(\"connectedOn\").notNullable();\n table.datetime(\"lastSeen\").nullable();\n table.index([\"identityId\"]);\n table.index([\"tenant\"]);\n });\n }\n\n private async migrateTable(): Promise<void> {\n const hasEndpoint = await this.knex.client.schema.hasColumn(this.tableName, \"endpoint\");\n if (hasEndpoint) {\n return;\n }\n\n await this.knex.client.schema.alterTable(this.tableName, table => {\n table.text(\"endpoint\").nullable();\n });\n\n await this.knex.client(this.tableName).update({\n endpoint: this.knex.client.raw(\"'https://' || \\\"domainName\\\" || '/' || \\\"stage\\\"\")\n });\n\n await this.knex.client.schema.alterTable(this.tableName, table => {\n table.text(\"endpoint\").notNullable().alter();\n table.dropColumn(\"domainName\");\n table.dropColumn(\"stage\");\n });\n }\n\n private async migrateLastSeen(): Promise<void> {\n const hasLastSeen = await this.knex.client.schema.hasColumn(this.tableName, \"lastSeen\");\n if (hasLastSeen) {\n return;\n }\n\n await this.knex.client.schema.alterTable(this.tableName, table => {\n table.datetime(\"lastSeen\").nullable();\n });\n }\n\n private toData(row: ConnectionRow): ConnectionRegistry.Data {\n return {\n connectionId: row.connectionId,\n identity: {\n id: row.identityId,\n displayName: row.identityDisplayName,\n type: row.identityType\n },\n tenant: row.tenant,\n endpoint: row.endpoint,\n connectedOn: row.connectedOn\n };\n }\n}\n\nexport const WebsocketsConnectionRegistry = ConnectionRegistry.createImplementation({\n implementation: WebsocketsConnectionRegistryImpl,\n dependencies: [KnexClient, TableName]\n});\n"],"names":["BASE_TABLE_NAME","WebsocketsConnectionRegistryImpl","knex","tableName","event","row","Date","err","WebinyError","existing","connections","rows","identity","tenant","connectionId","olderThan","threshold","qb","exists","table","hasEndpoint","hasLastSeen","WebsocketsConnectionRegistry","ConnectionRegistry","KnexClient","TableName"],"mappings":"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"}
1
+ {"version":3,"file":"WebsocketsConnectionRegistry.js","sources":["../src/WebsocketsConnectionRegistry.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\nimport { KnexClient } from \"@webiny/api-core-sql\";\nimport { ConnectionRegistry } from \"@webiny/api-websockets/exports/api.js\";\nimport { TableName } from \"~/TableName/abstractions.js\";\nimport { toIsoString } from \"~/toIsoString.js\";\n\ninterface ConnectionRow {\n connectionId: string;\n identityId: string;\n identityDisplayName: string;\n identityType: string;\n tenant: string;\n endpoint: string;\n connectedOn: string;\n lastSeen: string | null;\n}\n\nconst BASE_TABLE_NAME = \"WebsocketsConnections\";\n\nclass WebsocketsConnectionRegistryImpl implements ConnectionRegistry.Interface {\n private readonly knex;\n private readonly tableName;\n\n public constructor(knex: KnexClient.Interface, tableName: TableName.Interface) {\n this.knex = knex;\n this.tableName = tableName.resolve(BASE_TABLE_NAME);\n }\n\n public async register(\n event: ConnectionRegistry.RegisterParams\n ): Promise<ConnectionRegistry.Data> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const row: ConnectionRow = {\n connectionId: event.connectionId,\n identityId: event.identity.id,\n identityDisplayName: event.identity.displayName,\n identityType: event.identity.type,\n tenant: event.tenant,\n endpoint: event.endpoint,\n connectedOn: event.connectedOn,\n lastSeen: new Date().toISOString()\n };\n\n await this.knex.client<ConnectionRow>(this.tableName).insert(row);\n\n return this.toData(row);\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not register websockets connection.\",\n code: \"REGISTER_CONNECTION_ERROR\",\n data: { event }\n });\n }\n }\n\n public async unregister(event: ConnectionRegistry.UnregisterParams): Promise<void> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const existing = await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"connectionId\", event.connectionId)\n .first();\n\n if (!existing) {\n throw new WebinyError(\n `Connection \"${event.connectionId}\" does not exist.`,\n \"CONNECTION_NOT_FOUND\",\n { connectionId: event.connectionId }\n );\n }\n\n await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"connectionId\", event.connectionId)\n .delete();\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not unregister websockets connection.\",\n code: \"UNREGISTER_CONNECTION_ERROR\",\n data: { event }\n });\n }\n }\n\n public async listViaConnections(connections: string[]): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex\n .client<ConnectionRow>(this.tableName)\n .whereIn(\"connectionId\", connections);\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list websockets connections by connection IDs.\",\n code: \"LIST_VIA_CONNECTIONS_ERROR\",\n data: { connections }\n });\n }\n }\n\n public async listViaIdentity(identity: string): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"identityId\", identity);\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list websockets connections by identity.\",\n code: \"LIST_VIA_IDENTITY_ERROR\",\n data: { identity }\n });\n }\n }\n\n public async listViaTenant(tenant: string): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"tenant\", tenant);\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list websockets connections by tenant.\",\n code: \"LIST_VIA_TENANT_ERROR\",\n data: { tenant }\n });\n }\n }\n\n public async listAll(): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const rows = await this.knex.client<ConnectionRow>(this.tableName).select(\"*\");\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list all websockets connections.\",\n code: \"LIST_ALL_CONNECTIONS_ERROR\"\n });\n }\n }\n\n public async updateLastSeen(connectionId: string): Promise<void> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n await this.knex\n .client<ConnectionRow>(this.tableName)\n .where(\"connectionId\", connectionId)\n .update({ lastSeen: new Date().toISOString() });\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not update lastSeen for websockets connection.\",\n code: \"UPDATE_LAST_SEEN_ERROR\",\n data: { connectionId }\n });\n }\n }\n\n public async listStale(olderThan: Date): Promise<ConnectionRegistry.Data[]> {\n try {\n await this.ensureTable();\n await this.migrateTable();\n await this.migrateLastSeen();\n\n const threshold = olderThan.toISOString();\n\n const rows = await this.knex.client<ConnectionRow>(this.tableName).where(qb => {\n qb.where(\"lastSeen\", \"<\", threshold).orWhereNull(\"lastSeen\");\n });\n\n return rows.map(row => this.toData(row));\n } catch (err) {\n throw WebinyError.from(err, {\n message: \"Could not list stale websockets connections.\",\n code: \"LIST_STALE_CONNECTIONS_ERROR\",\n data: { olderThan }\n });\n }\n }\n\n private async ensureTable(): Promise<void> {\n const exists = await this.knex.client.schema.hasTable(this.tableName);\n if (exists) {\n return;\n }\n\n await this.knex.client.schema.createTable(this.tableName, table => {\n table.text(\"connectionId\").notNullable().primary();\n table.text(\"identityId\").notNullable();\n table.text(\"identityDisplayName\").notNullable();\n table.text(\"identityType\").notNullable();\n table.text(\"tenant\").notNullable();\n table.text(\"endpoint\").notNullable();\n table.datetime(\"connectedOn\").notNullable();\n table.datetime(\"lastSeen\").nullable();\n table.index([\"identityId\"]);\n table.index([\"tenant\"]);\n });\n }\n\n private async migrateTable(): Promise<void> {\n const hasEndpoint = await this.knex.client.schema.hasColumn(this.tableName, \"endpoint\");\n if (hasEndpoint) {\n return;\n }\n\n await this.knex.client.schema.alterTable(this.tableName, table => {\n table.text(\"endpoint\").nullable();\n });\n\n await this.knex.client(this.tableName).update({\n endpoint: this.knex.client.raw(\"'https://' || \\\"domainName\\\" || '/' || \\\"stage\\\"\")\n });\n\n await this.knex.client.schema.alterTable(this.tableName, table => {\n table.text(\"endpoint\").notNullable().alter();\n table.dropColumn(\"domainName\");\n table.dropColumn(\"stage\");\n });\n }\n\n private async migrateLastSeen(): Promise<void> {\n const hasLastSeen = await this.knex.client.schema.hasColumn(this.tableName, \"lastSeen\");\n if (hasLastSeen) {\n return;\n }\n\n await this.knex.client.schema.alterTable(this.tableName, table => {\n table.datetime(\"lastSeen\").nullable();\n });\n }\n\n private toData(row: ConnectionRow): ConnectionRegistry.Data {\n return {\n connectionId: row.connectionId,\n identity: {\n id: row.identityId,\n displayName: row.identityDisplayName,\n type: row.identityType\n },\n tenant: row.tenant,\n endpoint: row.endpoint,\n connectedOn: toIsoString(row.connectedOn)\n };\n }\n}\n\nexport const WebsocketsConnectionRegistry = ConnectionRegistry.createImplementation({\n implementation: WebsocketsConnectionRegistryImpl,\n dependencies: [KnexClient, TableName]\n});\n"],"names":["BASE_TABLE_NAME","WebsocketsConnectionRegistryImpl","knex","tableName","event","row","Date","err","WebinyError","existing","connections","rows","identity","tenant","connectionId","olderThan","threshold","qb","exists","table","hasEndpoint","hasLastSeen","toIsoString","WebsocketsConnectionRegistry","ConnectionRegistry","KnexClient","TableName"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type Container } from "@webiny/feature/api";
2
+ export interface WebsocketsSqlConfig {
3
+ tableNamePrefix?: string;
4
+ }
5
+ export declare const WebsocketsSqlFeature: {
6
+ name: string;
7
+ register(container: Container, context?: WebsocketsSqlConfig | undefined): void;
8
+ };
@@ -0,0 +1,14 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { TableName } from "./TableName/abstractions.js";
3
+ import { TableName as TableName_js_TableName } from "./TableName/TableName.js";
4
+ import { WebsocketsConnectionRegistry } from "./WebsocketsConnectionRegistry.js";
5
+ const WebsocketsSqlFeature = createFeature({
6
+ name: "WebsocketsSql",
7
+ register (container, config) {
8
+ container.registerInstance(TableName, new TableName_js_TableName(config?.tableNamePrefix));
9
+ container.register(WebsocketsConnectionRegistry);
10
+ }
11
+ });
12
+ export { WebsocketsSqlFeature };
13
+
14
+ //# sourceMappingURL=WebsocketsSqlFeature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebsocketsSqlFeature.js","sources":["../src/WebsocketsSqlFeature.ts"],"sourcesContent":["import { type Container, createFeature } from \"@webiny/feature/api\";\nimport { TableName as TableNameAbstraction } from \"~/TableName/abstractions.js\";\nimport { TableName } from \"~/TableName/TableName.js\";\nimport { WebsocketsConnectionRegistry } from \"./WebsocketsConnectionRegistry.js\";\n\nexport interface WebsocketsSqlConfig {\n tableNamePrefix?: string;\n}\n\nexport const WebsocketsSqlFeature = createFeature<WebsocketsSqlConfig | undefined>({\n name: \"WebsocketsSql\",\n register(container: Container, config?) {\n container.registerInstance(TableNameAbstraction, new TableName(config?.tableNamePrefix));\n container.register(WebsocketsConnectionRegistry);\n }\n});\n"],"names":["WebsocketsSqlFeature","createFeature","container","config","TableNameAbstraction","TableName","WebsocketsConnectionRegistry"],"mappings":";;;;AASO,MAAMA,uBAAuBC,cAA+C;IAC/E,MAAM;IACN,UAASC,SAAoB,EAAEC,MAAO;QAClCD,UAAU,gBAAgB,CAACE,WAAsB,IAAIC,uBAAUF,QAAQ;QACvED,UAAU,QAAQ,CAACI;IACvB;AACJ"}
package/index.d.ts CHANGED
@@ -1,7 +1,3 @@
1
- import type { Knex } from "knex";
2
- interface RegisterWebsocketsSqlStorageOperationsParams {
3
- knex: Knex;
4
- tableNamePrefix?: string;
5
- }
6
- export declare const registerWebsocketsSqlStorageOperations: (params: RegisterWebsocketsSqlStorageOperationsParams) => import("@webiny/handler").RegisterExtensionPlugin<import("@webiny/handler/types.js").Context>;
7
- export {};
1
+ export { WebsocketsConnectionRegistry } from "./WebsocketsConnectionRegistry.js";
2
+ export { WebsocketsSqlFeature } from "./WebsocketsSqlFeature.js";
3
+ export type { WebsocketsSqlConfig } from "./WebsocketsSqlFeature.js";
package/index.js CHANGED
@@ -1,11 +1,2 @@
1
- import { createRegisterExtensionPlugin } from "@webiny/handler";
2
- import { WebsocketsConnectionRegistry } from "./WebsocketsConnectionRegistry.js";
3
- import { TableName } from "./TableName/abstractions.js";
4
- import { TableName as TableName_js_TableName } from "./TableName/TableName.js";
5
- const registerWebsocketsSqlStorageOperations = (params)=>createRegisterExtensionPlugin((context)=>{
6
- context.container.registerInstance(TableName, new TableName_js_TableName(params.tableNamePrefix));
7
- context.container.register(WebsocketsConnectionRegistry);
8
- });
9
- export { registerWebsocketsSqlStorageOperations };
10
-
11
- //# sourceMappingURL=index.js.map
1
+ export { WebsocketsConnectionRegistry } from "./WebsocketsConnectionRegistry.js";
2
+ export { WebsocketsSqlFeature } from "./WebsocketsSqlFeature.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-websockets-sql",
3
- "version": "0.0.0-unstable.b6d7105cee",
3
+ "version": "6.6.0-alpha.1",
4
4
  "type": "module",
5
5
  "keywords": [
6
6
  "@webiny/api-websockets",
@@ -20,21 +20,20 @@
20
20
  "./*": "./*"
21
21
  },
22
22
  "dependencies": {
23
- "@webiny/api-core-sql": "0.0.0-unstable.b6d7105cee",
24
- "@webiny/api-websockets": "0.0.0-unstable.b6d7105cee",
25
- "@webiny/error": "0.0.0-unstable.b6d7105cee",
26
- "@webiny/feature": "0.0.0-unstable.b6d7105cee",
27
- "@webiny/handler": "0.0.0-unstable.b6d7105cee",
23
+ "@webiny/api-core-sql": "6.6.0-alpha.1",
24
+ "@webiny/api-websockets": "6.6.0-alpha.1",
25
+ "@webiny/error": "6.6.0-alpha.1",
26
+ "@webiny/feature": "6.6.0-alpha.1",
28
27
  "knex": "3.3.0"
29
28
  },
30
29
  "devDependencies": {
31
- "@webiny/build-tools": "0.0.0-unstable.b6d7105cee",
32
- "@webiny/di": "1.0.2",
33
- "@webiny/project-utils": "0.0.0-unstable.b6d7105cee",
34
- "better-sqlite3": "13.0.1",
30
+ "@webiny/api-core": "6.6.0-alpha.1",
31
+ "@webiny/build-tools": "6.6.0-alpha.1",
32
+ "@webiny/di": "1.1.0",
33
+ "better-sqlite3": "13.0.3",
35
34
  "rimraf": "6.1.3",
36
35
  "typescript": "7.0.2",
37
- "vitest": "4.1.10"
36
+ "vitest": "4.1.11"
38
37
  },
39
38
  "publishConfig": {
40
39
  "access": "public"
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Normalize a timestamp read out of a `datetime` column to a UTC ISO string.
3
+ *
4
+ * We always write ISO strings, but the column's read shape is the driver's decision: node-postgres
5
+ * and mysql2 parse it into a `Date`, better-sqlite3 hands back the text it was given, and some
6
+ * configurations return "2026-08-04 17:02:06" with no `T` and no zone. That wall-clock is UTC,
7
+ * because that is how it was written, so the space form is read back as UTC.
8
+ *
9
+ * Taking `unknown` keeps the variance out of the row type, so the rest of the registry can treat a
10
+ * timestamp as the `string` it is declared to be. Anything unparseable throws rather than being
11
+ * stringified: these values are compared against a cutoff to decide which connections are still
12
+ * live, and a quietly malformed one drops a user's connections with no error to show for it.
13
+ */
14
+ export declare const toIsoString: (value: unknown) => string;
package/toIsoString.js ADDED
@@ -0,0 +1,15 @@
1
+ import { WebinyError } from "@webiny/error";
2
+ const toIsoString = (value)=>{
3
+ if (value instanceof Date) return value.toISOString();
4
+ if ("string" == typeof value) {
5
+ const normalized = value.includes(" ") && !value.includes("T") ? `${value.replace(" ", "T")}Z` : value;
6
+ const parsed = new Date(normalized);
7
+ if (!Number.isNaN(parsed.getTime())) return parsed.toISOString();
8
+ }
9
+ throw new WebinyError("Could not read a websockets connection timestamp.", "INVALID_CONNECTION_TIMESTAMP", {
10
+ value
11
+ });
12
+ };
13
+ export { toIsoString };
14
+
15
+ //# sourceMappingURL=toIsoString.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toIsoString.js","sources":["../src/toIsoString.ts"],"sourcesContent":["import { WebinyError } from \"@webiny/error\";\n\n/**\n * Normalize a timestamp read out of a `datetime` column to a UTC ISO string.\n *\n * We always write ISO strings, but the column's read shape is the driver's decision: node-postgres\n * and mysql2 parse it into a `Date`, better-sqlite3 hands back the text it was given, and some\n * configurations return \"2026-08-04 17:02:06\" with no `T` and no zone. That wall-clock is UTC,\n * because that is how it was written, so the space form is read back as UTC.\n *\n * Taking `unknown` keeps the variance out of the row type, so the rest of the registry can treat a\n * timestamp as the `string` it is declared to be. Anything unparseable throws rather than being\n * stringified: these values are compared against a cutoff to decide which connections are still\n * live, and a quietly malformed one drops a user's connections with no error to show for it.\n */\nexport const toIsoString = (value: unknown): string => {\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (typeof value === \"string\") {\n const normalized =\n value.includes(\" \") && !value.includes(\"T\") ? `${value.replace(\" \", \"T\")}Z` : value;\n\n const parsed = new Date(normalized);\n if (!Number.isNaN(parsed.getTime())) {\n return parsed.toISOString();\n }\n }\n\n throw new WebinyError(\n \"Could not read a websockets connection timestamp.\",\n \"INVALID_CONNECTION_TIMESTAMP\",\n { value }\n );\n};\n"],"names":["toIsoString","value","Date","normalized","parsed","Number","WebinyError"],"mappings":";AAeO,MAAMA,cAAc,CAACC;IACxB,IAAIA,iBAAiBC,MACjB,OAAOD,MAAM,WAAW;IAG5B,IAAI,AAAiB,YAAjB,OAAOA,OAAoB;QAC3B,MAAME,aACFF,MAAM,QAAQ,CAAC,QAAQ,CAACA,MAAM,QAAQ,CAAC,OAAO,GAAGA,MAAM,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,GAAGA;QAElF,MAAMG,SAAS,IAAIF,KAAKC;QACxB,IAAI,CAACE,OAAO,KAAK,CAACD,OAAO,OAAO,KAC5B,OAAOA,OAAO,WAAW;IAEjC;IAEA,MAAM,IAAIE,YACN,qDACA,gCACA;QAAEL;IAAM;AAEhB"}
package/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport { createRegisterExtensionPlugin } from \"@webiny/handler\";\nimport { WebsocketsConnectionRegistry } from \"./WebsocketsConnectionRegistry.js\";\nimport { TableName as TableNameAbstraction } from \"~/TableName/abstractions.js\";\nimport { TableName } from \"~/TableName/TableName.js\";\n\ninterface RegisterWebsocketsSqlStorageOperationsParams {\n knex: Knex;\n tableNamePrefix?: string;\n}\n\nexport const registerWebsocketsSqlStorageOperations = (\n params: RegisterWebsocketsSqlStorageOperationsParams\n) => {\n return createRegisterExtensionPlugin(context => {\n context.container.registerInstance(\n TableNameAbstraction,\n new TableName(params.tableNamePrefix)\n );\n context.container.register(WebsocketsConnectionRegistry);\n });\n};\n"],"names":["registerWebsocketsSqlStorageOperations","params","createRegisterExtensionPlugin","context","TableNameAbstraction","TableName","WebsocketsConnectionRegistry"],"mappings":";;;;AAWO,MAAMA,yCAAyC,CAClDC,SAEOC,8BAA8BC,CAAAA;QACjCA,QAAQ,SAAS,CAAC,gBAAgB,CAC9BC,WACA,IAAIC,uBAAUJ,OAAO,eAAe;QAExCE,QAAQ,SAAS,CAAC,QAAQ,CAACG;IAC/B"}