@framers/sql-storage-adapter 0.6.15 → 0.7.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.
Files changed (94) hide show
  1. package/README.md +174 -3
  2. package/dist/adapters/baseStorageAdapter.d.ts.map +1 -1
  3. package/dist/adapters/baseStorageAdapter.js +4 -2
  4. package/dist/adapters/baseStorageAdapter.js.map +1 -1
  5. package/dist/adapters/betterSqliteAdapter.d.ts +18 -2
  6. package/dist/adapters/betterSqliteAdapter.d.ts.map +1 -1
  7. package/dist/adapters/betterSqliteAdapter.js +23 -7
  8. package/dist/adapters/betterSqliteAdapter.js.map +1 -1
  9. package/dist/adapters/capacitorSqliteAdapter.d.ts +8 -0
  10. package/dist/adapters/capacitorSqliteAdapter.d.ts.map +1 -1
  11. package/dist/adapters/capacitorSqliteAdapter.js +11 -1
  12. package/dist/adapters/capacitorSqliteAdapter.js.map +1 -1
  13. package/dist/adapters/electron/electronMainAdapter.d.ts +10 -0
  14. package/dist/adapters/electron/electronMainAdapter.d.ts.map +1 -1
  15. package/dist/adapters/electron/electronMainAdapter.js +21 -12
  16. package/dist/adapters/electron/electronMainAdapter.js.map +1 -1
  17. package/dist/adapters/indexedDbAdapter.d.ts +202 -54
  18. package/dist/adapters/indexedDbAdapter.d.ts.map +1 -1
  19. package/dist/adapters/indexedDbAdapter.js +560 -123
  20. package/dist/adapters/indexedDbAdapter.js.map +1 -1
  21. package/dist/adapters/postgresAdapter.d.ts +159 -3
  22. package/dist/adapters/postgresAdapter.d.ts.map +1 -1
  23. package/dist/adapters/postgresAdapter.js +667 -140
  24. package/dist/adapters/postgresAdapter.js.map +1 -1
  25. package/dist/adapters/sqlJsAdapter.d.ts +21 -3
  26. package/dist/adapters/sqlJsAdapter.d.ts.map +1 -1
  27. package/dist/adapters/sqlJsAdapter.js +29 -26
  28. package/dist/adapters/sqlJsAdapter.js.map +1 -1
  29. package/dist/core/contracts/index.d.ts +9 -0
  30. package/dist/core/contracts/index.d.ts.map +1 -1
  31. package/dist/core/contracts/index.js.map +1 -1
  32. package/dist/core/database.d.ts +43 -8
  33. package/dist/core/database.d.ts.map +1 -1
  34. package/dist/core/database.js +40 -5
  35. package/dist/core/database.js.map +1 -1
  36. package/dist/core/resolver.d.ts +20 -1
  37. package/dist/core/resolver.d.ts.map +1 -1
  38. package/dist/core/resolver.js +33 -11
  39. package/dist/core/resolver.js.map +1 -1
  40. package/dist/features/kv/idb.d.ts +79 -0
  41. package/dist/features/kv/idb.d.ts.map +1 -0
  42. package/dist/features/kv/idb.js +14 -0
  43. package/dist/features/kv/idb.js.map +1 -0
  44. package/dist/features/kv/index.d.ts +14 -0
  45. package/dist/features/kv/index.d.ts.map +1 -0
  46. package/dist/features/kv/index.js +14 -0
  47. package/dist/features/kv/index.js.map +1 -0
  48. package/dist/features/kv/indexedDbKeyValueStore.d.ts +77 -0
  49. package/dist/features/kv/indexedDbKeyValueStore.d.ts.map +1 -0
  50. package/dist/features/kv/indexedDbKeyValueStore.js +127 -0
  51. package/dist/features/kv/indexedDbKeyValueStore.js.map +1 -0
  52. package/dist/features/kv/keyValueStore.d.ts +48 -0
  53. package/dist/features/kv/keyValueStore.d.ts.map +1 -0
  54. package/dist/features/kv/keyValueStore.js +54 -0
  55. package/dist/features/kv/keyValueStore.js.map +1 -0
  56. package/dist/features/kv/sqlKeyValueStore.d.ts +34 -0
  57. package/dist/features/kv/sqlKeyValueStore.d.ts.map +1 -0
  58. package/dist/features/kv/sqlKeyValueStore.js +91 -0
  59. package/dist/features/kv/sqlKeyValueStore.js.map +1 -0
  60. package/dist/features/kv/valueCodec.d.ts +35 -0
  61. package/dist/features/kv/valueCodec.d.ts.map +1 -0
  62. package/dist/features/kv/valueCodec.js +462 -0
  63. package/dist/features/kv/valueCodec.js.map +1 -0
  64. package/dist/features/migrations/dataExport.js +9 -6
  65. package/dist/features/migrations/dataExport.js.map +1 -1
  66. package/dist/index.d.ts +3 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +5 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/shared/errors.d.ts +23 -0
  71. package/dist/shared/errors.d.ts.map +1 -0
  72. package/dist/shared/errors.js +44 -0
  73. package/dist/shared/errors.js.map +1 -0
  74. package/dist/shared/logger.d.ts +26 -0
  75. package/dist/shared/logger.d.ts.map +1 -0
  76. package/dist/shared/logger.js +26 -0
  77. package/dist/shared/logger.js.map +1 -0
  78. package/dist/shared/parameterUtils.d.ts +7 -0
  79. package/dist/shared/parameterUtils.d.ts.map +1 -1
  80. package/dist/shared/parameterUtils.js +25 -0
  81. package/dist/shared/parameterUtils.js.map +1 -1
  82. package/dist/shared/postgresTarget.d.ts +4 -3
  83. package/dist/shared/postgresTarget.d.ts.map +1 -1
  84. package/dist/shared/postgresTarget.js +6 -4
  85. package/dist/shared/postgresTarget.js.map +1 -1
  86. package/dist/shared/segment.d.ts +43 -0
  87. package/dist/shared/segment.d.ts.map +1 -0
  88. package/dist/shared/segment.js +77 -0
  89. package/dist/shared/segment.js.map +1 -0
  90. package/dist/shared/sqlPlaceholders.d.ts +40 -0
  91. package/dist/shared/sqlPlaceholders.d.ts.map +1 -0
  92. package/dist/shared/sqlPlaceholders.js +276 -0
  93. package/dist/shared/sqlPlaceholders.js.map +1 -0
  94. package/package.json +10 -2
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Error checks that read the same failure from every adapter.
3
+ */
4
+ /** better-sqlite3's extended result codes for a unique or primary-key violation. */
5
+ const SQLITE_UNIQUE_CODES = new Set(['SQLITE_CONSTRAINT_UNIQUE', 'SQLITE_CONSTRAINT_PRIMARYKEY']);
6
+ /** SQLite's message for one, which sql.js and the Capacitor plugin pass on without a code. */
7
+ const SQLITE_UNIQUE_MESSAGE = /\bUNIQUE constraint failed\b/;
8
+ /** How deep isUniqueViolation follows `cause`. */
9
+ const MAX_CAUSE_DEPTH = 10;
10
+ /**
11
+ * Whether `error` is a unique or primary-key violation, from any adapter:
12
+ * PostgreSQL's SQLSTATE `23505` (`unique_violation`, pg's `code`),
13
+ * better-sqlite3's `SQLITE_CONSTRAINT_UNIQUE` and
14
+ * `SQLITE_CONSTRAINT_PRIMARYKEY`, and the "UNIQUE constraint failed" message
15
+ * that sql.js, the IndexedDB adapter and the Capacitor plugin give. An error
16
+ * that wraps one as its `cause`, to any depth up to ten, counts too.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * try {
21
+ * await db.run('INSERT INTO users (email) VALUES (?)', [email]);
22
+ * } catch (error) {
23
+ * if (isUniqueViolation(error)) return { taken: true };
24
+ * throw error;
25
+ * }
26
+ * ```
27
+ */
28
+ export const isUniqueViolation = (error) => {
29
+ const seen = new Set();
30
+ let current = error;
31
+ while (current !== null && typeof current === 'object' && !seen.has(current) && seen.size < MAX_CAUSE_DEPTH) {
32
+ seen.add(current);
33
+ const { code, message } = current;
34
+ if (code === '23505')
35
+ return true;
36
+ if (typeof code === 'string' && SQLITE_UNIQUE_CODES.has(code))
37
+ return true;
38
+ if (typeof message === 'string' && SQLITE_UNIQUE_MESSAGE.test(message))
39
+ return true;
40
+ current = current.cause;
41
+ }
42
+ return false;
43
+ };
44
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,oFAAoF;AACpF,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,0BAA0B,EAAE,8BAA8B,CAAC,CAAC,CAAC;AAElG,8FAA8F;AAC9F,MAAM,qBAAqB,GAAG,8BAA8B,CAAC;AAE7D,kDAAkD;AAClD,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAW,EAAE;IAC3D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAW,CAAC;IAChC,IAAI,OAAO,GAAY,KAAK,CAAC;IAC7B,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,eAAe,EAAE,CAAC;QAC5G,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAgD,CAAC;QAC3E,IAAI,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QAClC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3E,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;QACpF,OAAO,GAAI,OAA+B,CAAC,KAAK,CAAC;IACnD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Where the library's log lines go. A host hands its own logger in, and
3
+ * pino's logger fits as it is: each call passes the line's fields first and
4
+ * its message second, as pino takes them. Without one, lines go to the
5
+ * console, as the library has always written them.
6
+ */
7
+ export interface StorageLogger {
8
+ debug?(fields: Record<string, unknown>, message: string): void;
9
+ info(fields: Record<string, unknown>, message: string): void;
10
+ warn(fields: Record<string, unknown>, message: string): void;
11
+ error(fields: Record<string, unknown>, message: string): void;
12
+ }
13
+ /**
14
+ * Routes every line the library writes to `logger`, from then on and in every
15
+ * adapter. `null` routes them back to the console.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import pino from 'pino';
20
+ * setStorageLogger(pino({ name: 'storage' }));
21
+ * ```
22
+ */
23
+ export declare const setStorageLogger: (logger: StorageLogger | null) => void;
24
+ /** The logger the library writes to now. */
25
+ export declare const getStorageLogger: () => StorageLogger;
26
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/D;AAgBD;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,WAAY,aAAa,GAAG,IAAI,KAAG,IAE/D,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB,QAAO,aAAwB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /** The console line's prefix: the field `scope` when a line has one, else StorageAdapter. */
2
+ const prefix = (fields) => `[${typeof fields.scope === 'string' ? fields.scope : 'StorageAdapter'}]`;
3
+ /** The default: one line on the console per call, prefixed as before. */
4
+ const consoleLogger = {
5
+ debug: (fields, message) => console.log(`${prefix(fields)} ${message}`),
6
+ info: (fields, message) => console.info(`${prefix(fields)} ${message}`),
7
+ warn: (fields, message) => console.warn(`${prefix(fields)} ${message}`),
8
+ error: (fields, message) => console.error(`${prefix(fields)} ${message}`),
9
+ };
10
+ let current = consoleLogger;
11
+ /**
12
+ * Routes every line the library writes to `logger`, from then on and in every
13
+ * adapter. `null` routes them back to the console.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import pino from 'pino';
18
+ * setStorageLogger(pino({ name: 'storage' }));
19
+ * ```
20
+ */
21
+ export const setStorageLogger = (logger) => {
22
+ current = logger ?? consoleLogger;
23
+ };
24
+ /** The logger the library writes to now. */
25
+ export const getStorageLogger = () => current;
26
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"AAaA,6FAA6F;AAC7F,MAAM,MAAM,GAAG,CAAC,MAA+B,EAAU,EAAE,CACzD,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,GAAG,CAAC;AAE5E,yEAAyE;AACzE,MAAM,aAAa,GAAkB;IACnC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;IACvE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;IACvE,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;CAC1E,CAAC;AAEF,IAAI,OAAO,GAAkB,aAAa,CAAC;AAE3C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAA4B,EAAQ,EAAE;IACrE,OAAO,GAAG,MAAM,IAAI,aAAa,CAAC;AACpC,CAAC,CAAC;AAEF,4CAA4C;AAC5C,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAkB,EAAE,CAAC,OAAO,CAAC"}
@@ -6,4 +6,11 @@ export declare const normaliseParameters: (parameters?: StorageParameters) => {
6
6
  named?: Record<string, unknown>;
7
7
  positional?: Array<unknown>;
8
8
  };
9
+ /**
10
+ * Named parameters under every key sql.js may look them up by. sql.js binds a
11
+ * named value only under the key that matches the placeholder as written
12
+ * (":id", "@id", "$id"); better-sqlite3 takes the bare key ("id"). Expanding
13
+ * every variant lets one payload work on both.
14
+ */
15
+ export declare const expandNamedParameters: (named: Record<string, unknown>) => Record<string, unknown>;
9
16
  //# sourceMappingURL=parameterUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parameterUtils.d.ts","sourceRoot":"","sources":["../../src/shared/parameterUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,mBAAmB,gBACjB,iBAAiB,KAC7B;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CAehE,CAAC"}
1
+ {"version":3,"file":"parameterUtils.d.ts","sourceRoot":"","sources":["../../src/shared/parameterUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,mBAAmB,gBACjB,iBAAiB,KAC7B;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;CAehE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,UAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAY5F,CAAC"}
@@ -14,4 +14,29 @@ export const normaliseParameters = (parameters) => {
14
14
  // Fall back to positional when unknown primitive is provided.
15
15
  return { positional: [parameters] };
16
16
  };
17
+ /**
18
+ * Named parameters under every key sql.js may look them up by. sql.js binds a
19
+ * named value only under the key that matches the placeholder as written
20
+ * (":id", "@id", "$id"); better-sqlite3 takes the bare key ("id"). Expanding
21
+ * every variant lets one payload work on both.
22
+ */
23
+ export const expandNamedParameters = (named) => {
24
+ const expanded = { ...named };
25
+ for (const [rawKey, value] of Object.entries(named)) {
26
+ if (!rawKey)
27
+ continue;
28
+ const key = rawKey.replace(/^[:@$]/, '');
29
+ if (!key)
30
+ continue;
31
+ if (!(key in expanded))
32
+ expanded[key] = value;
33
+ if (!(`:${key}` in expanded))
34
+ expanded[`:${key}`] = value;
35
+ if (!(`@${key}` in expanded))
36
+ expanded[`@${key}`] = value;
37
+ if (!(`$${key}` in expanded))
38
+ expanded[`$${key}`] = value;
39
+ }
40
+ return expanded;
41
+ };
17
42
  //# sourceMappingURL=parameterUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parameterUtils.js","sourceRoot":"","sources":["../../src/shared/parameterUtils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,UAA8B,EACoC,EAAE;IACpE,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,UAAqC,EAAE,CAAC;IAC1D,CAAC;IAED,8DAA8D;IAC9D,OAAO,EAAE,UAAU,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;AACtC,CAAC,CAAC"}
1
+ {"version":3,"file":"parameterUtils.js","sourceRoot":"","sources":["../../src/shared/parameterUtils.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,UAA8B,EACoC,EAAE;IACpE,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,UAAqC,EAAE,CAAC;IAC1D,CAAC;IAED,8DAA8D;IAC9D,OAAO,EAAE,UAAU,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;AACtC,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAA8B,EAA2B,EAAE;IAC/F,MAAM,QAAQ,GAA4B,EAAE,GAAG,KAAK,EAAE,CAAC;IACvD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC9C,IAAI,CAAC,CAAC,IAAI,GAAG,EAAE,IAAI,QAAQ,CAAC;YAAE,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;QAC1D,IAAI,CAAC,CAAC,IAAI,GAAG,EAAE,IAAI,QAAQ,CAAC;YAAE,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;QAC1D,IAAI,CAAC,CAAC,IAAI,GAAG,EAAE,IAAI,QAAQ,CAAC;YAAE,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC;IAC5D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
@@ -2,9 +2,10 @@ import type { PostgresAdapterOptions } from '../adapters/postgresAdapter.js';
2
2
  /** A string with something in it. */
3
3
  export declare const isNonEmpty: (value: unknown) => value is string;
4
4
  /**
5
- * Whether Postgres options name a server: a connection string, or a host,
6
- * database or user. `{ connectionString: process.env.DATABASE_URL }` with
7
- * DATABASE_URL unset names none.
5
+ * Whether Postgres options name a server: a pool of the caller's, a
6
+ * connection string, or a host, database or user.
7
+ * `{ connectionString: process.env.DATABASE_URL }` with DATABASE_URL unset
8
+ * names none.
8
9
  */
9
10
  export declare const namesPostgresServer: (options: PostgresAdapterOptions | undefined) => boolean;
10
11
  //# sourceMappingURL=postgresTarget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgresTarget.d.ts","sourceRoot":"","sources":["../../src/shared/postgresTarget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,qCAAqC;AACrC,eAAO,MAAM,UAAU,UAAW,OAAO,KAAG,KAAK,IAAI,MAAuD,CAAC;AAE7G;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,YAAa,sBAAsB,GAAG,SAAS,KAAG,OAO/E,CAAC"}
1
+ {"version":3,"file":"postgresTarget.d.ts","sourceRoot":"","sources":["../../src/shared/postgresTarget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,qCAAqC;AACrC,eAAO,MAAM,UAAU,UAAW,OAAO,KAAG,KAAK,IAAI,MAAuD,CAAC;AAE7G;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,YAAa,sBAAsB,GAAG,SAAS,KAAG,OAQ/E,CAAC"}
@@ -1,12 +1,14 @@
1
1
  /** A string with something in it. */
2
2
  export const isNonEmpty = (value) => typeof value === 'string' && value.length > 0;
3
3
  /**
4
- * Whether Postgres options name a server: a connection string, or a host,
5
- * database or user. `{ connectionString: process.env.DATABASE_URL }` with
6
- * DATABASE_URL unset names none.
4
+ * Whether Postgres options name a server: a pool of the caller's, a
5
+ * connection string, or a host, database or user.
6
+ * `{ connectionString: process.env.DATABASE_URL }` with DATABASE_URL unset
7
+ * names none.
7
8
  */
8
9
  export const namesPostgresServer = (options) => Boolean(options &&
9
- (isNonEmpty(options.connectionString) ||
10
+ (Boolean(options.pool) ||
11
+ isNonEmpty(options.connectionString) ||
10
12
  isNonEmpty(options.host) ||
11
13
  isNonEmpty(options.database) ||
12
14
  isNonEmpty(options.user)));
@@ -1 +1 @@
1
- {"version":3,"file":"postgresTarget.js","sourceRoot":"","sources":["../../src/shared/postgresTarget.ts"],"names":[],"mappings":"AAEA,qCAAqC;AACrC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAE7G;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAA2C,EAAW,EAAE,CAC1F,OAAO,CACL,OAAO;IACL,CAAC,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC;QACnC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;QACxB,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC5B,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAC9B,CAAC"}
1
+ {"version":3,"file":"postgresTarget.js","sourceRoot":"","sources":["../../src/shared/postgresTarget.ts"],"names":[],"mappings":"AAEA,qCAAqC;AACrC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAE7G;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAA2C,EAAW,EAAE,CAC1F,OAAO,CACL,OAAO;IACL,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;QACpB,UAAU,CAAC,OAAO,CAAC,gBAAgB,CAAC;QACpC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;QACxB,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC5B,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAC9B,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Segments keep one user's tables apart from another's in a database they
3
+ * share. On PostgreSQL a segment is a schema of its own; on the SQLite family a
4
+ * database file of its own; on IndexedDB and Capacitor a database name of its
5
+ * own. A segment name is the same on every backend, so one name gives a host
6
+ * the same separation on the server, the desktop, the phone and the browser.
7
+ *
8
+ * This module imports nothing, so browser bundles can include it.
9
+ */
10
+ /**
11
+ * Checks a segment name and returns it.
12
+ *
13
+ * A segment name is lower-case letters, digits and underscores, starts with a
14
+ * letter or an underscore, and has at most 63 characters: an unquoted
15
+ * PostgreSQL identifier, and a safe file, IndexedDB and Capacitor database
16
+ * name. It is not `public`, `information_schema` or a name beginning with
17
+ * `pg_`, which PostgreSQL keeps for its own schemas.
18
+ *
19
+ * @throws {Error} When the name is not one a segment can take.
20
+ */
21
+ export declare const validateSegment: (segment: string) => string;
22
+ /**
23
+ * The name of a segment's database: `name` followed by `-` and the segment,
24
+ * or `name` itself when there is no segment. For IndexedDB and Capacitor
25
+ * database names: `app-db` and segment `agentos` give `app-db-agentos`.
26
+ *
27
+ * @throws {Error} When the segment is not one a segment name can take.
28
+ */
29
+ export declare const segmentName: (name: string, segment: string | undefined) => string;
30
+ /**
31
+ * The file of a segment's database: the segment goes between the file's name
32
+ * and its extension (`/data/app.sqlite3` and segment `agentos` give
33
+ * `/data/app-agentos.sqlite3`), or after a name with no extension. A `file:`
34
+ * URI keeps its query, and SQLite's in-memory names (`:memory:`,
35
+ * `file::memory:`) stay as they are, since each in-memory connection is a
36
+ * database of its own. Without a segment the path is returned as it is.
37
+ *
38
+ * @throws {Error} When the segment is not one a segment name can take.
39
+ */
40
+ export declare const segmentFilePath: (filePath: string, segment: string | undefined) => string;
41
+ /** Whether a path names an in-memory SQLite database, which no file holds. */
42
+ export declare const namesInMemoryDatabase: (filePath: string) => boolean;
43
+ //# sourceMappingURL=segment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment.d.ts","sourceRoot":"","sources":["../../src/shared/segment.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,YAAa,MAAM,KAAG,MAajD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,SAAU,MAAM,WAAW,MAAM,GAAG,SAAS,KAAG,MACF,CAAC;AAMvE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,aAAc,MAAM,WAAW,MAAM,GAAG,SAAS,KAAG,MAkB/E,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,aAlCA,MAAM,KAAG,OAkCQ,CAAC"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Segments keep one user's tables apart from another's in a database they
3
+ * share. On PostgreSQL a segment is a schema of its own; on the SQLite family a
4
+ * database file of its own; on IndexedDB and Capacitor a database name of its
5
+ * own. A segment name is the same on every backend, so one name gives a host
6
+ * the same separation on the server, the desktop, the phone and the browser.
7
+ *
8
+ * This module imports nothing, so browser bundles can include it.
9
+ */
10
+ /** PostgreSQL's identifier limit: a schema name has at most 63 bytes. */
11
+ const MAX_SEGMENT_LENGTH = 63;
12
+ /** Lower-case letters, digits and underscores, starting with a letter or an underscore. */
13
+ const SEGMENT_PATTERN = /^[a-z_][a-z0-9_]*$/;
14
+ /** Schemas PostgreSQL keeps for itself, besides the names beginning with pg_. */
15
+ const RESERVED_SEGMENTS = new Set(['public', 'information_schema']);
16
+ /**
17
+ * Checks a segment name and returns it.
18
+ *
19
+ * A segment name is lower-case letters, digits and underscores, starts with a
20
+ * letter or an underscore, and has at most 63 characters: an unquoted
21
+ * PostgreSQL identifier, and a safe file, IndexedDB and Capacitor database
22
+ * name. It is not `public`, `information_schema` or a name beginning with
23
+ * `pg_`, which PostgreSQL keeps for its own schemas.
24
+ *
25
+ * @throws {Error} When the name is not one a segment can take.
26
+ */
27
+ export const validateSegment = (segment) => {
28
+ if (typeof segment !== 'string' || !SEGMENT_PATTERN.test(segment) || segment.length > MAX_SEGMENT_LENGTH) {
29
+ throw new Error(`Invalid segment ${JSON.stringify(segment)}: a segment name is lower-case letters, digits and underscores, ` +
30
+ `starts with a letter or an underscore, and has at most ${MAX_SEGMENT_LENGTH} characters.`);
31
+ }
32
+ if (RESERVED_SEGMENTS.has(segment) || segment.startsWith('pg_')) {
33
+ throw new Error(`Invalid segment "${segment}": PostgreSQL keeps public, information_schema and the names beginning with pg_ for its own schemas.`);
34
+ }
35
+ return segment;
36
+ };
37
+ /**
38
+ * The name of a segment's database: `name` followed by `-` and the segment,
39
+ * or `name` itself when there is no segment. For IndexedDB and Capacitor
40
+ * database names: `app-db` and segment `agentos` give `app-db-agentos`.
41
+ *
42
+ * @throws {Error} When the segment is not one a segment name can take.
43
+ */
44
+ export const segmentName = (name, segment) => segment === undefined ? name : `${name}-${validateSegment(segment)}`;
45
+ /** SQLite's names for a database that lives in its connection alone. */
46
+ const isInMemoryPath = (filePath) => filePath === '' || filePath === ':memory:' || filePath.startsWith('file::memory:');
47
+ /**
48
+ * The file of a segment's database: the segment goes between the file's name
49
+ * and its extension (`/data/app.sqlite3` and segment `agentos` give
50
+ * `/data/app-agentos.sqlite3`), or after a name with no extension. A `file:`
51
+ * URI keeps its query, and SQLite's in-memory names (`:memory:`,
52
+ * `file::memory:`) stay as they are, since each in-memory connection is a
53
+ * database of its own. Without a segment the path is returned as it is.
54
+ *
55
+ * @throws {Error} When the segment is not one a segment name can take.
56
+ */
57
+ export const segmentFilePath = (filePath, segment) => {
58
+ if (segment === undefined)
59
+ return filePath;
60
+ validateSegment(segment);
61
+ if (isInMemoryPath(filePath))
62
+ return filePath;
63
+ // A file: URI's path ends at its query or fragment.
64
+ const queryAt = filePath.startsWith('file:') ? filePath.search(/[?#]/) : -1;
65
+ const pathPart = queryAt === -1 ? filePath : filePath.slice(0, queryAt);
66
+ const rest = queryAt === -1 ? '' : filePath.slice(queryAt);
67
+ const nameAt = Math.max(pathPart.lastIndexOf('/'), pathPart.lastIndexOf('\\'), pathPart.startsWith('file:') ? 4 : -1) + 1;
68
+ const directory = pathPart.slice(0, nameAt);
69
+ const name = pathPart.slice(nameAt);
70
+ // A dot that begins the name (.store) starts no extension.
71
+ const extensionAt = name.lastIndexOf('.');
72
+ const segmented = extensionAt > 0 ? `${name.slice(0, extensionAt)}-${segment}${name.slice(extensionAt)}` : `${name}-${segment}`;
73
+ return `${directory}${segmented}${rest}`;
74
+ };
75
+ /** Whether a path names an in-memory SQLite database, which no file holds. */
76
+ export const namesInMemoryDatabase = isInMemoryPath;
77
+ //# sourceMappingURL=segment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment.js","sourceRoot":"","sources":["../../src/shared/segment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { StorageParameters } from '../core/contracts/index.js';
2
+ /** A statement and its values, ready for node-postgres. */
3
+ export interface PostgresStatement {
4
+ text: string;
5
+ values: unknown[];
6
+ }
7
+ /**
8
+ * Rewrites a statement's placeholders for node-postgres, which takes only
9
+ * `$1`, `$2`, ... Outside literals, quoted identifiers, dollar-quoted strings
10
+ * and comments:
11
+ *
12
+ * - Named parameters: each `@name` becomes the next `$n`, bound to that name's value.
13
+ * - A statement that already uses `$n` placeholders is sent as written, its
14
+ * `?` operators included.
15
+ * - Otherwise `??` becomes `?` (the jsonb key-exists operator), `?|` and `?&`
16
+ * stay operators (`?||` and `?&&` are a placeholder followed by `||` or
17
+ * `&&`), and each other `?` becomes the next `$n`. A statement run without
18
+ * parameters keeps its `?`, so the jsonb `?` operator works in it as written.
19
+ */
20
+ export declare const toPostgresStatement: (statement: string, parameters?: StorageParameters) => PostgresStatement;
21
+ /** A statement and its parameters, ready for a SQLite engine. */
22
+ export interface SqliteStatement {
23
+ statement: string;
24
+ parameters?: StorageParameters;
25
+ }
26
+ /**
27
+ * A value as the SQLite adapters bind it. better-sqlite3 refuses booleans,
28
+ * Dates and objects, and sql.js refuses Dates and binds an array as a blob,
29
+ * so: a boolean binds as 1 or 0, a Date as its ISO 8601 text (an Invalid Date
30
+ * is refused), an array or a plain object as JSON text, and undefined as
31
+ * NULL. Strings, numbers, bigints, null and bytes bind as they are.
32
+ */
33
+ export declare const toSqliteValue: (value: unknown) => unknown;
34
+ /**
35
+ * The statement and values a SQLite adapter binds: `$n` placeholders become
36
+ * `?` (see rewriteDollarPlaceholders above) and each value is converted with
37
+ * toSqliteValue, positional and named alike.
38
+ */
39
+ export declare const toSqliteStatement: (statement: string, parameters?: StorageParameters) => SqliteStatement;
40
+ //# sourceMappingURL=sqlPlaceholders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlPlaceholders.d.ts","sourceRoot":"","sources":["../../src/shared/sqlPlaceholders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA8J3D,2DAA2D;AAC3D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,cAAe,MAAM,eAAe,iBAAiB,KAAG,iBA4DvF,CAAC;AAEF,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AA+CD;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,UAAW,OAAO,KAAG,OAW9C,CAAC;AAeF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,cAAe,MAAM,eAAe,iBAAiB,KAAG,eAGrF,CAAC"}