@peers-app/peers-sdk 0.8.19 → 0.9.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 (58) hide show
  1. package/dist/context/user-context-singleton.d.ts +1 -0
  2. package/dist/context/user-context-singleton.js +8 -0
  3. package/dist/context/user-context.js +3 -0
  4. package/dist/data/assistants.d.ts +1 -1
  5. package/dist/data/assistants.js +1 -1
  6. package/dist/data/change-tracking.d.ts +8 -0
  7. package/dist/data/change-tracking.js +18 -0
  8. package/dist/data/channels.d.ts +2 -2
  9. package/dist/data/channels.js +3 -2
  10. package/dist/data/data-locks.test.js +8 -4
  11. package/dist/data/devices.d.ts +2 -2
  12. package/dist/data/devices.js +3 -2
  13. package/dist/data/embeddings.d.ts +1 -1
  14. package/dist/data/embeddings.js +2 -1
  15. package/dist/data/files/file.types.d.ts +2 -2
  16. package/dist/data/files/file.types.js +3 -2
  17. package/dist/data/groups.d.ts +1 -1
  18. package/dist/data/groups.js +1 -1
  19. package/dist/data/index.d.ts +1 -0
  20. package/dist/data/index.js +1 -0
  21. package/dist/data/messages.d.ts +5 -5
  22. package/dist/data/messages.js +5 -5
  23. package/dist/data/orm/dependency-injection.test.js +5 -2
  24. package/dist/data/orm/sql-db.d.ts +3 -1
  25. package/dist/data/orm/sql.data-source.test.js +5 -3
  26. package/dist/data/orm/table-container.d.ts +23 -0
  27. package/dist/data/orm/table-container.js +152 -8
  28. package/dist/data/orm/table-container.test.d.ts +1 -0
  29. package/dist/data/orm/table-container.test.js +159 -0
  30. package/dist/data/orm/table.d.ts +1 -0
  31. package/dist/data/orm/table.js +13 -1
  32. package/dist/data/orm/types.d.ts +2 -1
  33. package/dist/data/orm/types.js +14 -5
  34. package/dist/data/orm/types.test.js +136 -1
  35. package/dist/data/packages.d.ts +5 -5
  36. package/dist/data/packages.js +6 -5
  37. package/dist/data/peer-events/peer-event-handlers.d.ts +3 -3
  38. package/dist/data/peer-events/peer-event-handlers.js +4 -3
  39. package/dist/data/peer-events/peer-event-types.d.ts +1 -1
  40. package/dist/data/peer-events/peer-event-types.js +2 -1
  41. package/dist/data/persistent-vars.d.ts +1 -1
  42. package/dist/data/persistent-vars.js +2 -1
  43. package/dist/data/table-definitions-table.d.ts +31 -0
  44. package/dist/data/table-definitions-table.js +28 -0
  45. package/dist/data/tool-tests.d.ts +2 -2
  46. package/dist/data/tool-tests.js +3 -2
  47. package/dist/data/tools.d.ts +1 -1
  48. package/dist/data/tools.js +2 -1
  49. package/dist/data/user-trust-levels.d.ts +1 -1
  50. package/dist/data/user-trust-levels.js +2 -1
  51. package/dist/data/users.d.ts +1 -2
  52. package/dist/data/users.js +3 -4
  53. package/dist/data/workflow-logs.d.ts +2 -2
  54. package/dist/data/workflow-runs.d.ts +2 -2
  55. package/dist/types/workflow.d.ts +7 -7
  56. package/dist/types/workflow.js +6 -5
  57. package/dist/types/zod-types.js +2 -0
  58. package/package.json +1 -1
@@ -9,3 +9,4 @@ export declare function setDefaultClientUserContext(userId: string): void;
9
9
  export declare function getAllTables(): {
10
10
  [tableName: string]: Table<any>;
11
11
  };
12
+ export declare const myUserId: () => string;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.myUserId = void 0;
3
4
  exports.getUserContext = getUserContext;
4
5
  exports.setUserContext = setUserContext;
5
6
  exports.getDefaultDataContext = getDefaultDataContext;
@@ -103,3 +104,10 @@ if (!rpc_types_1.isClient) {
103
104
  return table[methodName](...args);
104
105
  };
105
106
  }
107
+ const myUserId = () => {
108
+ if (!userContextInstance) {
109
+ throw new Error(`myUserId called before userContext singleton was initialized`);
110
+ }
111
+ return userContextInstance.userId;
112
+ };
113
+ exports.myUserId = myUserId;
@@ -90,6 +90,9 @@ class UserContext {
90
90
  this.currentlyActiveGroupId(group.dataContextId);
91
91
  }
92
92
  });
93
+ if (!this.currentlyActiveGroupId()) {
94
+ this.currentlyActiveGroupId(this.defaultDataContext().dataContextId || this.userId);
95
+ }
93
96
  }
94
97
  getDataContext(groupId) {
95
98
  if (!groupId || groupId === this.userId) {
@@ -11,7 +11,7 @@ export declare const assistantSchema: z.ZodObject<{
11
11
  createdAt: z.ZodDefault<z.ZodDate>;
12
12
  updatedAt: z.ZodOptional<z.ZodDate>;
13
13
  description: z.ZodOptional<z.ZodString>;
14
- assistantRunnerToolId: z.ZodDefault<z.ZodString>;
14
+ assistantRunnerToolId: z.ZodDefault<z.ZodEffects<z.ZodString, string, string>>;
15
15
  assistantRunnerConfig: z.ZodDefault<z.ZodObject<{}, "strip", z.ZodAny, z.objectOutputType<{}, z.ZodAny, "strip">, z.objectInputType<{}, z.ZodAny, "strip">>>;
16
16
  toolsToInclude: z.ZodDefault<z.ZodString>;
17
17
  toolInclusionStrategy: z.ZodDefault<z.ZodNativeEnum<typeof ToolInclusionStrategy>>;
@@ -23,7 +23,7 @@ exports.assistantSchema = zod_1.z.object({
23
23
  createdAt: zod_1.z.date().default(() => new Date()),
24
24
  updatedAt: zod_1.z.date().optional(),
25
25
  description: zod_1.z.string().optional().describe(`Information about the assistant that won't be used in the interaction but can still be used to differentiate between assistants`),
26
- assistantRunnerToolId: zod_1.z.string().default(system_ids_1.defaultAssistantRunnerToolId).describe('The tool id of the model to use to run the assistant'),
26
+ assistantRunnerToolId: zod_types_1.zodPeerId.default(system_ids_1.defaultAssistantRunnerToolId).describe('The tool id of the model to use to run the assistant'),
27
27
  assistantRunnerConfig: zod_types_1.zodAnyObject.default({}).describe('The configuration to use when running the assistant'),
28
28
  toolsToInclude: zod_1.z.string().default('').describe('Link the tools that should always be available to this assistant. Only linked tools will be included. All other content will be ignored.\n\nex: `$hello-world-tool`'),
29
29
  // toolsToExclude: z.string().optional().describe('Describe or link the tools that should never be available to this assistant'),
@@ -160,6 +160,14 @@ export declare class ChangeTrackingTable extends SQLDataSource<IChangeRecord> {
160
160
  * @param beforeTimestamp - Delete changes superseded before this timestamp
161
161
  */
162
162
  deleteChanges(changeIds: string[]): Promise<void>;
163
+ /**
164
+ * Clear inline values on insert changes (op='set', path='/') for a specific table.
165
+ * These values are no longer needed since they are resolved from the source table at query time.
166
+ * Used during compaction to reclaim space from pre-migration insert changes that still have inline values.
167
+ *
168
+ * @param tableName - Name of the table to clear insert values for
169
+ */
170
+ clearInsertChangeValues(tableName: string): Promise<void>;
163
171
  /**
164
172
  * Get table metadata
165
173
  */
@@ -345,6 +345,24 @@ class ChangeTrackingTable extends orm_1.SQLDataSource {
345
345
  WHERE changeId IN (${changeIds.map(c => "?").join()})
346
346
  `, changeIds);
347
347
  }
348
+ /**
349
+ * Clear inline values on insert changes (op='set', path='/') for a specific table.
350
+ * These values are no longer needed since they are resolved from the source table at query time.
351
+ * Used during compaction to reclaim space from pre-migration insert changes that still have inline values.
352
+ *
353
+ * @param tableName - Name of the table to clear insert values for
354
+ */
355
+ async clearInsertChangeValues(tableName) {
356
+ await this.initTable();
357
+ await this.db.exec(`
358
+ UPDATE "${this.tableName}"
359
+ SET value = NULL
360
+ WHERE tableName = ?
361
+ AND op = 'set'
362
+ AND path = '/'
363
+ AND value IS NOT NULL
364
+ `, [tableName]);
365
+ }
348
366
  /**
349
367
  * Get table metadata
350
368
  */
@@ -1,11 +1,11 @@
1
1
  import { z } from "zod";
2
2
  import type { DataContext } from "../context/data-context";
3
3
  export declare const channelSchema: z.ZodObject<{
4
- channelId: z.ZodString;
4
+ channelId: z.ZodEffects<z.ZodString, string, string>;
5
5
  name: z.ZodString;
6
6
  description: z.ZodString;
7
7
  createdAt: z.ZodDate;
8
- owningGroupId: z.ZodString;
8
+ owningGroupId: z.ZodEffects<z.ZodString, string, string>;
9
9
  }, "strip", z.ZodTypeAny, {
10
10
  name: string;
11
11
  description: string;
@@ -6,12 +6,13 @@ const zod_1 = require("zod");
6
6
  const types_1 = require("./orm/types");
7
7
  const user_context_singleton_1 = require("../context/user-context-singleton");
8
8
  const table_definitions_system_1 = require("./orm/table-definitions.system");
9
+ const zod_types_1 = require("../types/zod-types");
9
10
  exports.channelSchema = zod_1.z.object({
10
- channelId: zod_1.z.string(),
11
+ channelId: zod_types_1.zodPeerId,
11
12
  name: zod_1.z.string(),
12
13
  description: zod_1.z.string(),
13
14
  createdAt: zod_1.z.date(),
14
- owningGroupId: zod_1.z.string(),
15
+ owningGroupId: zod_types_1.zodPeerId,
15
16
  });
16
17
  const metaData = {
17
18
  name: 'Channels',
@@ -22,7 +22,8 @@ class DBHarness {
22
22
  return this.database.prepare(sql).all(params);
23
23
  }
24
24
  async exec(sql, params = []) {
25
- this.database.prepare(sql).run(params);
25
+ const result = this.database.prepare(sql).run(params);
26
+ return { changes: result.changes };
26
27
  }
27
28
  async close() {
28
29
  this._db?.close();
@@ -284,19 +285,22 @@ describe('data-locks.ts', () => {
284
285
  });
285
286
  it('should reject renewal when lock is no longer current', async () => {
286
287
  const recordId = (0, utils_1.newid)();
288
+ // getCurrentLock returns the lock with the lexicographically first dataLockId,
289
+ // so ensure newLockId sorts before oldLockId
290
+ const [newLockId, oldLockId] = [(0, utils_1.newid)(), (0, utils_1.newid)()].sort();
287
291
  const oldLock = {
288
- dataLockId: 'old-lock',
292
+ dataLockId: oldLockId,
289
293
  recordId,
290
294
  lockedUntil: Date.now() + 60000,
291
295
  };
292
296
  const newLock = {
293
- dataLockId: 'new-lock', // Lexicographically later, but inserted after
297
+ dataLockId: newLockId,
294
298
  recordId,
295
299
  lockedUntil: Date.now() + 60000,
296
300
  };
297
301
  await dataLocksTable.insert(oldLock);
298
302
  await dataLocksTable.insert(newLock);
299
- // Try to renew the old lock - should fail because new lock is current
303
+ // Try to renew the old lock - should fail because new lock is current (sorts first)
300
304
  const result = await dataLocksTable.renewLock(oldLock);
301
305
  expect(result).toBeUndefined();
302
306
  });
@@ -2,8 +2,8 @@ import { z } from "zod";
2
2
  import { TrustLevel } from "../device/socket.type";
3
3
  import type { DataContext } from "../context/data-context";
4
4
  export declare const deviceSchema: z.ZodObject<{
5
- deviceId: z.ZodString;
6
- userId: z.ZodString;
5
+ deviceId: z.ZodEffects<z.ZodString, string, string>;
6
+ userId: z.ZodEffects<z.ZodString, string, string>;
7
7
  firstSeen: z.ZodDate;
8
8
  lastSeen: z.ZodDate;
9
9
  name: z.ZodOptional<z.ZodString>;
@@ -8,9 +8,10 @@ const persistent_vars_1 = require("./persistent-vars");
8
8
  const user_context_singleton_1 = require("../context/user-context-singleton");
9
9
  const table_definitions_system_1 = require("./orm/table-definitions.system");
10
10
  const socket_type_1 = require("../device/socket.type");
11
+ const zod_types_1 = require("../types/zod-types");
11
12
  exports.deviceSchema = zod_1.z.object({
12
- deviceId: zod_1.z.string(),
13
- userId: zod_1.z.string(),
13
+ deviceId: zod_types_1.zodPeerId,
14
+ userId: zod_types_1.zodPeerId,
14
15
  firstSeen: zod_1.z.date(),
15
16
  lastSeen: zod_1.z.date(),
16
17
  name: zod_1.z.string().optional(),
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import type { DataContext } from "../context/data-context";
3
3
  export declare const embeddingSchema: z.ZodObject<{
4
- embeddingId: z.ZodString;
4
+ embeddingId: z.ZodEffects<z.ZodString, string, string>;
5
5
  textHash: z.ZodString;
6
6
  embedding: z.ZodArray<z.ZodNumber, "many">;
7
7
  embeddingType: z.ZodString;
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.embeddingSchema = void 0;
4
4
  exports.Embeddings = Embeddings;
5
5
  const zod_1 = require("zod");
6
+ const zod_types_1 = require("../types/zod-types");
6
7
  const types_1 = require("./orm/types");
7
8
  const user_context_singleton_1 = require("../context/user-context-singleton");
8
9
  const table_definitions_system_1 = require("./orm/table-definitions.system");
9
10
  exports.embeddingSchema = zod_1.z.object({
10
- embeddingId: zod_1.z.string(),
11
+ embeddingId: zod_types_1.zodPeerId,
11
12
  textHash: zod_1.z.string().describe('The hash of the text'),
12
13
  embedding: zod_1.z.array(zod_1.z.number()).describe('The embedding of the text'),
13
14
  embeddingType: zod_1.z.string().describe('The type of embedding used'),
@@ -1,14 +1,14 @@
1
1
  import { z } from "zod";
2
2
  import { ITableMetaData } from "../orm/types";
3
3
  export declare const fileSchema: z.ZodObject<{
4
- fileId: z.ZodString;
4
+ fileId: z.ZodEffects<z.ZodString, string, string>;
5
5
  name: z.ZodString;
6
6
  fileSize: z.ZodNumber;
7
7
  fileHash: z.ZodString;
8
8
  mimeType: z.ZodOptional<z.ZodString>;
9
9
  chunkHashes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
10
10
  isIndexFile: z.ZodOptional<z.ZodBoolean>;
11
- indexFileId: z.ZodOptional<z.ZodString>;
11
+ indexFileId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
12
12
  }, "strip", z.ZodTypeAny, {
13
13
  name: string;
14
14
  fileId: string;
@@ -6,16 +6,17 @@ exports.setFileOps = setFileOps;
6
6
  exports.getFileOps = getFileOps;
7
7
  exports.resetFileOps = resetFileOps;
8
8
  const zod_1 = require("zod");
9
+ const zod_types_1 = require("../../types/zod-types");
9
10
  const types_1 = require("../orm/types");
10
11
  exports.fileSchema = zod_1.z.object({
11
- fileId: zod_1.z.string(),
12
+ fileId: zod_types_1.zodPeerId,
12
13
  name: zod_1.z.string().describe('The name of the file'),
13
14
  fileSize: zod_1.z.number().describe('The size of the file in bytes'),
14
15
  fileHash: zod_1.z.string().describe('Hash of the chunk hashes array for integrity verification'),
15
16
  mimeType: zod_1.z.string().optional().describe('The MIME type of the file'),
16
17
  chunkHashes: zod_1.z.array(zod_1.z.string()).optional().describe('SHA-256 hashes of each chunk in order (for small files)'),
17
18
  isIndexFile: zod_1.z.boolean().optional().describe('True if this is an index file for another large file'),
18
- indexFileId: zod_1.z.string().optional().describe('FileId of index file (for large files)'),
19
+ indexFileId: zod_types_1.zodPeerId.optional().describe('FileId of index file (for large files)'),
19
20
  });
20
21
  exports.filesMetaData = {
21
22
  name: 'Files',
@@ -10,7 +10,7 @@ export declare const groupSchema: z.ZodObject<{
10
10
  iconClassName: z.ZodOptional<z.ZodString>;
11
11
  publicRole: z.ZodOptional<z.ZodNativeEnum<typeof GroupMemberRole>>;
12
12
  disabled: z.ZodOptional<z.ZodBoolean>;
13
- founderUserId: z.ZodString;
13
+ founderUserId: z.ZodEffects<z.ZodString, string, string>;
14
14
  signature: z.ZodString;
15
15
  publicKey: z.ZodString;
16
16
  publicBoxKey: z.ZodString;
@@ -52,7 +52,7 @@ exports.groupSchema = zod_1.z.object({
52
52
  iconClassName: zod_1.z.string().optional().describe('Icon class name for the group (e.g., bi-people-fill)'),
53
53
  publicRole: zod_1.z.nativeEnum(group_member_roles_1.GroupMemberRole).optional().describe('Whether the group is publicly readable'),
54
54
  disabled: zod_1.z.boolean().optional().describe('Whether the group is currently disabled'),
55
- founderUserId: zod_1.z.string().describe('The user ID of the group founder'),
55
+ founderUserId: zod_types_1.zodPeerId.describe('The user ID of the group founder'),
56
56
  signature: zod_1.z.string().describe('The signed hash of this data excluding the signature itself'),
57
57
  publicKey: zod_1.z.string().describe('The public key of the group used to verify a data has come from a group member with write permissions or higher'),
58
58
  publicBoxKey: zod_1.z.string().describe('The public key used to encrypt data that only group members with writer permissions or higher can decrypt'),
@@ -19,6 +19,7 @@ export * from "./knowledge/predicates";
19
19
  export * from "./messages";
20
20
  export * from "./packages";
21
21
  export * from "./packages.utils";
22
+ export * from "./table-definitions-table";
22
23
  export * from "./peer-events/peer-event-handlers";
23
24
  export * from "./peer-events/peer-event-types";
24
25
  export * from "./peer-events/peer-events";
@@ -35,6 +35,7 @@ __exportStar(require("./knowledge/predicates"), exports);
35
35
  __exportStar(require("./messages"), exports);
36
36
  __exportStar(require("./packages"), exports);
37
37
  __exportStar(require("./packages.utils"), exports);
38
+ __exportStar(require("./table-definitions-table"), exports);
38
39
  __exportStar(require("./peer-events/peer-event-handlers"), exports);
39
40
  __exportStar(require("./peer-events/peer-event-types"), exports);
40
41
  __exportStar(require("./peer-events/peer-events"), exports);
@@ -2,14 +2,14 @@ import { z } from 'zod';
2
2
  import { DataContext } from "../context/data-context";
3
3
  export declare const messageSchema: z.ZodObject<{
4
4
  messageId: z.ZodEffects<z.ZodString, string, string>;
5
- channelId: z.ZodString;
6
- userId: z.ZodString;
7
- messageParentId: z.ZodOptional<z.ZodString>;
8
- assistantId: z.ZodOptional<z.ZodString>;
5
+ channelId: z.ZodEffects<z.ZodString, string, string>;
6
+ userId: z.ZodEffects<z.ZodString, string, string>;
7
+ messageParentId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
8
+ assistantId: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
9
9
  message: z.ZodString;
10
10
  createdAt: z.ZodDate;
11
11
  editedAt: z.ZodOptional<z.ZodDate>;
12
- fileIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
12
+ fileIds: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">>;
13
13
  vars: z.ZodOptional<z.ZodObject<{}, "strip", z.ZodAny, z.objectOutputType<{}, z.ZodAny, "strip">, z.objectInputType<{}, z.ZodAny, "strip">>>;
14
14
  }, "strip", z.ZodTypeAny, {
15
15
  message: string;
@@ -15,14 +15,14 @@ const user_context_singleton_1 = require("../context/user-context-singleton");
15
15
  const table_definitions_system_1 = require("./orm/table-definitions.system");
16
16
  exports.messageSchema = zod_1.z.object({
17
17
  messageId: zod_types_1.zodPeerId,
18
- channelId: zod_1.z.string().describe('The id of the channel this message entry belongs to'),
19
- userId: zod_1.z.string().describe('The id of the user who created this message entry'),
20
- messageParentId: zod_1.z.string().optional().describe('The id of the parent message entry if this is part of a thread'),
21
- assistantId: zod_1.z.string().optional().describe(`The id of the user's assistant that created this message entry operating on behalf of the user`),
18
+ channelId: zod_types_1.zodPeerId.describe('The id of the channel this message entry belongs to'),
19
+ userId: zod_types_1.zodPeerId.describe('The id of the user who created this message entry'),
20
+ messageParentId: zod_types_1.zodPeerId.optional().describe('The id of the parent message entry if this is part of a thread'),
21
+ assistantId: zod_types_1.zodPeerId.optional().describe(`The id of the user's assistant that created this message entry operating on behalf of the user`),
22
22
  message: zod_1.z.string().describe('The markdown content of this message entry'),
23
23
  createdAt: zod_1.z.date(),
24
24
  editedAt: zod_1.z.date().optional().describe('The time this message entry was last edited, if it was edited'),
25
- fileIds: zod_1.z.string().array().optional().describe('The ids of files attached to this message entry'),
25
+ fileIds: zod_types_1.zodPeerId.array().optional().describe('The ids of files attached to this message entry'),
26
26
  vars: zod_types_1.zodAnyObject.optional().describe('The variables that are associated with this message entry'),
27
27
  });
28
28
  const metaData = {
@@ -147,7 +147,9 @@ describe('Dependency Injection Pattern', () => {
147
147
  // Verify table was created correctly
148
148
  expect(table).toBeInstanceOf(_1.Table);
149
149
  expect(table.tableName).toBe('TestTable');
150
- expect(table.schema).toBe(testSchema);
150
+ // Table merges fields-derived schema with code schema, so it's not the same reference
151
+ const testData = { id: 'test-id', name: 'test-name' };
152
+ expect(() => table.schema.parse(testData)).not.toThrow();
151
153
  });
152
154
  it('should create tables through TableFactory using new DI pattern internally', () => {
153
155
  // Create mock DataContext
@@ -165,7 +167,8 @@ describe('Dependency Injection Pattern', () => {
165
167
  // Verify table was created correctly through TableFactory
166
168
  expect(table).toBeInstanceOf(_1.Table);
167
169
  expect(table.tableName).toBe('TestTable');
168
- expect(table.schema).toBe(testSchema);
170
+ // Table merges fields-derived schema with code schema, so it's not the same reference
171
+ expect(() => table.schema.parse({ id: 'test-id', name: 'test-name' })).not.toThrow();
169
172
  expect(table.metaData).toBe(testMetaData);
170
173
  });
171
174
  });
@@ -1,7 +1,9 @@
1
1
  export interface ISqlDb {
2
2
  get: (sql: string, params?: any) => Promise<any>;
3
3
  all: (sql: string, params?: any) => Promise<any[]>;
4
- exec: (sql: string, params?: any) => Promise<void>;
4
+ exec: (sql: string, params?: any) => Promise<{
5
+ changes: number;
6
+ }>;
5
7
  close: () => Promise<void>;
6
8
  execSync?: (sql: string, params?: any) => void;
7
9
  getSync?: (sql: string, params?: any) => any;
@@ -5,6 +5,7 @@ const lodash_1 = require("lodash");
5
5
  const zod_1 = require("zod");
6
6
  const utils_1 = require("../../utils");
7
7
  const field_type_1 = require("../../types/field-type");
8
+ const zod_types_1 = require("../../types/zod-types");
8
9
  const sql_data_source_1 = require("./sql.data-source");
9
10
  const types_1 = require("./types");
10
11
  class DBHarness {
@@ -23,7 +24,8 @@ class DBHarness {
23
24
  return this.db.prepare(sql).all(params);
24
25
  }
25
26
  async exec(sql, params = []) {
26
- await this.db.prepare(sql).run(params);
27
+ const result = await this.db.prepare(sql).run(params);
28
+ return { changes: result.changes };
27
29
  }
28
30
  async close() {
29
31
  this._db?.close();
@@ -39,12 +41,12 @@ describe('table', () => {
39
41
  });
40
42
  describe('when type is defined in code', () => {
41
43
  const taskSchema = zod_1.z.object({
42
- taskId: zod_1.z.string().default(() => (0, utils_1.newid)()),
44
+ taskId: zod_types_1.zodPeerId.default(() => (0, utils_1.newid)()),
43
45
  title: zod_1.z.string(),
44
46
  body: zod_1.z.string().default(''),
45
47
  dueDate: zod_1.z.date().optional(),
46
48
  completeDT: zod_1.z.date().optional(),
47
- parentTaskId: zod_1.z.string().optional(),
49
+ parentTaskId: zod_types_1.zodPeerId.optional(),
48
50
  });
49
51
  const taskFields = (0, types_1.schemaToFields)(taskSchema);
50
52
  const tasksTableType = {
@@ -2,11 +2,21 @@ import { z } from 'zod';
2
2
  import { ITableMetaData } from './types';
3
3
  import { Table } from './table';
4
4
  import { ITableDefinition, TableFactory, TableConstructor } from './table-definitions.type';
5
+ import type { ITableDefinitionRecord } from '../table-definitions-table';
6
+ /**
7
+ * Compare two table definition versions and decide whether to update.
8
+ * @returns 'update' to proceed, 'skip' to keep existing, 'update-warn-unversioned' to proceed with a warning,
9
+ * 'skip-warn-conflict' to skip with a warning about mismatched definitions at the same version.
10
+ */
11
+ export declare function checkVersionedUpdate(existingVersion: number, incomingVersion: number, existingMetaData: any, incomingMetaData: any): 'update' | 'skip' | 'update-warn-unversioned' | 'skip-warn-conflict';
5
12
  export declare class TableContainer {
6
13
  readonly tableFactory: TableFactory;
7
14
  readonly groupId?: string | undefined;
8
15
  private readonly tableDefinitions;
9
16
  private tableInstances;
17
+ private savingDefinitions;
18
+ private readonly fallbackDefinitions;
19
+ private fallbackInstances;
10
20
  constructor(tableFactory: TableFactory, groupId?: string | undefined);
11
21
  registerTableDefinition<T extends {
12
22
  [key: string]: any;
@@ -26,11 +36,24 @@ export declare class TableContainer {
26
36
  getTable<T extends {
27
37
  [key: string]: any;
28
38
  }>(metaData: ITableMetaData, schema?: z.AnyZodObject, tableConstructor?: TableConstructor<T>): Table<T>;
39
+ /**
40
+ * Auto-save table definition to the TableDefinitions system table.
41
+ * Only runs on server side, only for tables with a tableId (skips system tables),
42
+ * and skips saving the TableDefinitions table itself to avoid recursion.
43
+ */
44
+ private saveTableDefinition;
29
45
  getTableByName<T extends {
30
46
  [key: string]: any;
31
47
  }>(tableName: string): Table<T>;
48
+ /**
49
+ * Register a table definition from a synced TableDefinitions record.
50
+ * These go into the fallback tier (no custom constructor) so they never
51
+ * block full code-defined instances from being created later.
52
+ */
53
+ registerFromTableDefinitionRecord(record: ITableDefinitionRecord): void;
32
54
  /**
33
55
  * This ensures all tables have been new'ed up and then returns the entire list of them.
56
+ * Full (code-defined) instances take precedence over fallback (synced-definition) instances.
34
57
  *
35
58
  * This is primarily intended to be used by the peer-device sync operation which needs all
36
59
  * tables to be able to apply changes correctly.