create-syncular-app 0.59.0 → 0.60.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-syncular-app",
3
- "version": "0.59.0",
3
+ "version": "0.60.1",
4
4
  "author": "Benjamin Kniffler",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,6 +9,7 @@
9
9
  * clients`). Both talk real HTTP to http://localhost:8787.
10
10
  */
11
11
  import { makeClient } from './make-client';
12
+ import { todosInListSubscription } from './syncular.generated';
12
13
 
13
14
  const BASE_URL = process.env.SERVER_URL ?? 'http://localhost:8787';
14
15
  const LIST_ID = 'groceries';
@@ -18,10 +19,11 @@ const b = makeClient(BASE_URL, 'client-b');
18
19
  await a.start();
19
20
  await b.start();
20
21
 
21
- // Both clients subscribe to the same list (the requested scope).
22
- const sub = { id: 'todos', table: 'todos', scopes: { list_id: [LIST_ID] } };
23
- a.subscribe(sub);
24
- b.subscribe(sub);
22
+ // Both clients subscribe to the list's unit: one scope map covers every table
23
+ // scoped by `list_id`.
24
+ const list = todosInListSubscription.scopes({ listId: LIST_ID });
25
+ a.subscribe(list);
26
+ b.subscribe(list);
25
27
 
26
28
  // A writes a todo. mutate() records it locally + queues it for the next push.
27
29
  a.mutate([
@@ -13,7 +13,7 @@ import {
13
13
  } from '@syncular/server';
14
14
  import { createSyncularHono } from '@syncular/server-hono';
15
15
  import { makeClient } from './make-client';
16
- import { schema } from './syncular.generated';
16
+ import { schema, todosInListSubscription } from './syncular.generated';
17
17
 
18
18
  let server: ReturnType<typeof Bun.serve>;
19
19
  let baseUrl: string;
@@ -43,13 +43,9 @@ test('two clients converge through the server', async () => {
43
43
  await a.start();
44
44
  await b.start();
45
45
 
46
- const sub = {
47
- id: 'todos',
48
- table: 'todos',
49
- scopes: { list_id: ['groceries'] },
50
- };
51
- a.subscribe(sub);
52
- b.subscribe(sub);
46
+ const list = todosInListSubscription.scopes({ listId: 'groceries' });
47
+ a.subscribe(list);
48
+ b.subscribe(list);
53
49
 
54
50
  a.mutate([
55
51
  {
@@ -1,6 +1,6 @@
1
1
  // Generated by @syncular/typegen — DO NOT EDIT.
2
2
  // irVersion: 1
3
- // irHash: sha256:87f3b0e11fc0434b220472a00110771ac69dc0d56068d8ce69d0c1eb2930894e
3
+ // irHash: sha256:7a54dda11222e7937ece27856682da95d651ebc94cb95f9db77748f3282ffba2
4
4
 
5
5
  /** Structural descriptor consumed by renderer bindings; phantom type
6
6
  * fields make row/insert/update/id inference available without imports. */
@@ -106,11 +106,10 @@ export interface TodosInListParams {
106
106
  listId: string;
107
107
  }
108
108
 
109
- /** Requested-scope template for the 'todosInList' subscription. */
109
+ /** Unit template for the 'todosInList' subscription (SPEC §4.1). */
110
110
  export const todosInListSubscription = {
111
111
  name: 'todosInList',
112
- table: 'todos',
113
- scopes: (params: TodosInListParams): Record<string, string[]> => ({
114
- list_id: [params.listId],
112
+ scopes: (params: TodosInListParams): Record<string, string> => ({
113
+ list_id: params.listId,
115
114
  }),
116
115
  } as const;
@@ -58,16 +58,13 @@
58
58
  "subscriptions": [
59
59
  {
60
60
  "name": "todosInList",
61
- "table": "todos",
62
61
  "scopes": [
63
62
  {
64
63
  "variable": "list_id",
65
- "values": [
66
- {
67
- "kind": "parameter",
68
- "name": "listId"
69
- }
70
- ]
64
+ "value": {
65
+ "kind": "parameter",
66
+ "name": "listId"
67
+ }
71
68
  }
72
69
  ]
73
70
  }
@@ -8,10 +8,6 @@
8
8
  "schemaVersions": [{ "version": 1, "through": "0001_initial" }],
9
9
  "tables": [{ "name": "todos", "scopes": ["list:{list_id}"] }],
10
10
  "subscriptions": [
11
- {
12
- "name": "todosInList",
13
- "table": "todos",
14
- "scopes": { "list_id": ["{listId}"] }
15
- }
11
+ { "name": "todosInList", "scopes": { "list_id": "{listId}" } }
16
12
  ]
17
13
  }
@@ -9,3 +9,6 @@ CREATE TABLE todos (
9
9
  position INTEGER NOT NULL,
10
10
  updated_at_ms INTEGER NOT NULL
11
11
  );
12
+
13
+ -- listTodos reads one list at a time; this index lets SQLite search it.
14
+ CREATE INDEX idx_todos_list ON todos (list_id);
@@ -63,9 +63,9 @@ test('two clients converge through the scaffolded server config', async () => {
63
63
  await a.start();
64
64
  await b.start();
65
65
 
66
- const scopes = todoListSubscription.scopes({ listId: 'welcome' });
67
- a.subscribe({ id: 'todos', table: 'todos', scopes });
68
- b.subscribe({ id: 'todos', table: 'todos', scopes });
66
+ const list = todoListSubscription.scopes({ listId: 'welcome' });
67
+ a.subscribe(list);
68
+ b.subscribe(list);
69
69
 
70
70
  a.mutate([
71
71
  {
@@ -1,6 +1,6 @@
1
1
  // Generated by @syncular/typegen — DO NOT EDIT.
2
2
  // irVersion: 1
3
- // irHash: sha256:2ffc5b70cb96cd546326de9c06868bd988c9fa3459fb3bac8428a81dcc85fca0
3
+ // irHash: sha256:6bcec8061116d46f6e483f2f338f9d706972d272572c67b510e54a78e6b966c8
4
4
 
5
5
  /** Structural descriptor consumed by renderer bindings; phantom type
6
6
  * fields make row/insert/update/id inference available without imports. */
@@ -60,6 +60,15 @@ export const schema = {
60
60
  "pattern": "list:{list_id}",
61
61
  "column": "list_id"
62
62
  }
63
+ ],
64
+ "indexes": [
65
+ {
66
+ "name": "idx_todos_list",
67
+ "columns": [
68
+ "list_id"
69
+ ],
70
+ "unique": false
71
+ }
63
72
  ]
64
73
  }
65
74
  ]
@@ -106,11 +115,10 @@ export interface TodoListParams {
106
115
  listId: string;
107
116
  }
108
117
 
109
- /** Requested-scope template for the 'todoList' subscription. */
118
+ /** Unit template for the 'todoList' subscription (SPEC §4.1). */
110
119
  export const todoListSubscription = {
111
120
  name: 'todoList',
112
- table: 'todos',
113
- scopes: (params: TodoListParams): Record<string, string[]> => ({
114
- list_id: [params.listId],
121
+ scopes: (params: TodoListParams): Record<string, string> => ({
122
+ list_id: params.listId,
115
123
  }),
116
124
  } as const;
@@ -98,12 +98,11 @@ export interface QueryResultColumn {
98
98
  readonly nullable: boolean;
99
99
  }
100
100
 
101
+ /** A window base (SPEC §4.8) and the unit values a query reads. */
101
102
  export interface WindowCoverage {
102
103
  readonly base: {
103
- readonly table: string;
104
104
  readonly variable: string;
105
- readonly fixedScopes?: Readonly<Record<string, readonly string[]>>;
106
- readonly params?: string;
105
+ readonly fixedScopes?: Readonly<Record<string, string>>;
107
106
  };
108
107
  readonly units: readonly string[];
109
108
  }
@@ -21,7 +21,7 @@ tauri = { version = "2", features = [] }
21
21
  # The syncular plugin from crates.io. `native-transport` gives the core its
22
22
  # real HTTP + WebSocket transport (ureq + tungstenite) inside the host
23
23
  # process — the webview never talks to the sync server directly.
24
- tauri-plugin-syncular = { version = "0.59.0", features = ["native-transport"] }
24
+ tauri-plugin-syncular = { version = "0.60.1", features = ["native-transport"] }
25
25
 
26
26
  [features]
27
27
  default = []
@@ -52,22 +52,28 @@
52
52
  "column": "list_id"
53
53
  }
54
54
  ],
55
+ "indexes": [
56
+ {
57
+ "name": "idx_todos_list",
58
+ "columns": [
59
+ "list_id"
60
+ ],
61
+ "unique": false
62
+ }
63
+ ],
55
64
  "extensions": {}
56
65
  }
57
66
  ],
58
67
  "subscriptions": [
59
68
  {
60
69
  "name": "todoList",
61
- "table": "todos",
62
70
  "scopes": [
63
71
  {
64
72
  "variable": "list_id",
65
- "values": [
66
- {
67
- "kind": "parameter",
68
- "name": "listId"
69
- }
70
- ]
73
+ "value": {
74
+ "kind": "parameter",
75
+ "name": "listId"
76
+ }
71
77
  }
72
78
  ]
73
79
  }
@@ -10,10 +10,6 @@
10
10
  "schemaVersions": [{ "version": 1, "through": "0001_initial" }],
11
11
  "tables": [{ "name": "todos", "scopes": ["list:{list_id}"] }],
12
12
  "subscriptions": [
13
- {
14
- "name": "todoList",
15
- "table": "todos",
16
- "scopes": { "list_id": ["{listId}"] }
17
- }
13
+ { "name": "todoList", "scopes": { "list_id": "{listId}" } }
18
14
  ]
19
15
  }
@@ -3,7 +3,7 @@
3
3
  "migrations": [
4
4
  {
5
5
  "name": "0001_initial",
6
- "sha256": "87b23cd0f8e3677ca6fa7ca67eb7c8373a285607b6de10854cc43df1290bb0fa",
6
+ "sha256": "33fdb7df2e4dc4c598137acdacf009922ea1d107b2c4284efe62ec25eb681116",
7
7
  "schemaVersion": 1
8
8
  }
9
9
  ],
@@ -72,11 +72,8 @@ async function main(): Promise<void> {
72
72
  onSynced: () => void refresh(),
73
73
  });
74
74
 
75
- await handle.subscribe({
76
- id: 'todos',
77
- table: 'todos',
78
- scopes: todoListSubscription.scopes({ listId: LIST_ID }),
79
- });
75
+ // One unit per list: the scope map covers every table scoped by `list_id`.
76
+ await handle.subscribe(todoListSubscription.scopes({ listId: LIST_ID }));
80
77
 
81
78
  // The supported host policy owns connect + catch-up, retries transient
82
79
  // startup/socket loss, and suspends while this page is offline.
@@ -62,9 +62,9 @@ test('two clients converge through the scaffolded server config', async () => {
62
62
  await a.start();
63
63
  await b.start();
64
64
 
65
- const scopes = todoListSubscription.scopes({ listId: 'welcome' });
66
- a.subscribe({ id: 'todos', table: 'todos', scopes });
67
- b.subscribe({ id: 'todos', table: 'todos', scopes });
65
+ const list = todoListSubscription.scopes({ listId: 'welcome' });
66
+ a.subscribe(list);
67
+ b.subscribe(list);
68
68
 
69
69
  a.mutate([
70
70
  {
@@ -1,6 +1,6 @@
1
1
  // Generated by @syncular/typegen — DO NOT EDIT.
2
2
  // irVersion: 1
3
- // irHash: sha256:2ffc5b70cb96cd546326de9c06868bd988c9fa3459fb3bac8428a81dcc85fca0
3
+ // irHash: sha256:9c3077b1f537f8d84725f38d0b5234f7a53520777265f36f10059651d2cddd32
4
4
 
5
5
  /** Structural descriptor consumed by renderer bindings; phantom type
6
6
  * fields make row/insert/update/id inference available without imports. */
@@ -106,11 +106,10 @@ export interface TodoListParams {
106
106
  listId: string;
107
107
  }
108
108
 
109
- /** Requested-scope template for the 'todoList' subscription. */
109
+ /** Unit template for the 'todoList' subscription (SPEC §4.1). */
110
110
  export const todoListSubscription = {
111
111
  name: 'todoList',
112
- table: 'todos',
113
- scopes: (params: TodoListParams): Record<string, string[]> => ({
114
- list_id: [params.listId],
112
+ scopes: (params: TodoListParams): Record<string, string> => ({
113
+ list_id: params.listId,
115
114
  }),
116
115
  } as const;
@@ -58,16 +58,13 @@
58
58
  "subscriptions": [
59
59
  {
60
60
  "name": "todoList",
61
- "table": "todos",
62
61
  "scopes": [
63
62
  {
64
63
  "variable": "list_id",
65
- "values": [
66
- {
67
- "kind": "parameter",
68
- "name": "listId"
69
- }
70
- ]
64
+ "value": {
65
+ "kind": "parameter",
66
+ "name": "listId"
67
+ }
71
68
  }
72
69
  ]
73
70
  }
@@ -8,10 +8,6 @@
8
8
  "schemaVersions": [{ "version": 1, "through": "0001_initial" }],
9
9
  "tables": [{ "name": "todos", "scopes": ["list:{list_id}"] }],
10
10
  "subscriptions": [
11
- {
12
- "name": "todoList",
13
- "table": "todos",
14
- "scopes": { "list_id": ["{listId}"] }
15
- }
11
+ { "name": "todoList", "scopes": { "list_id": "{listId}" } }
16
12
  ]
17
13
  }