create-syncular-app 0.59.0 → 0.60.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.
- package/package.json +1 -1
- package/template/minimal/src/clients.ts +6 -4
- package/template/minimal/src/smoke.test.ts +4 -8
- package/template/minimal/src/syncular.generated.ts +4 -5
- package/template/minimal/syncular.ir.json +4 -7
- package/template/minimal/syncular.json +1 -5
- package/template/tauri/migrations/0001_initial/up.sql +3 -0
- package/template/tauri/src/smoke.test.ts +3 -3
- package/template/tauri/src/syncular.generated.ts +13 -5
- package/template/tauri/src/syncular.queries.ts +2 -3
- package/template/tauri/src-tauri/Cargo.toml +1 -1
- package/template/tauri/syncular.ir.json +13 -7
- package/template/tauri/syncular.json +1 -5
- package/template/tauri/syncular.migrations.lock.json +1 -1
- package/template/web/src/frontend/main.ts +2 -5
- package/template/web/src/smoke.test.ts +3 -3
- package/template/web/src/syncular.generated.ts +4 -5
- package/template/web/syncular.ir.json +4 -7
- package/template/web/syncular.json +1 -5
package/package.json
CHANGED
|
@@ -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
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
47
|
-
|
|
48
|
-
|
|
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:
|
|
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
|
-
/**
|
|
109
|
+
/** Unit template for the 'todosInList' subscription (SPEC §4.1). */
|
|
110
110
|
export const todosInListSubscription = {
|
|
111
111
|
name: 'todosInList',
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
}
|
|
@@ -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
|
|
67
|
-
a.subscribe(
|
|
68
|
-
b.subscribe(
|
|
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:
|
|
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
|
-
/**
|
|
118
|
+
/** Unit template for the 'todoList' subscription (SPEC §4.1). */
|
|
110
119
|
export const todoListSubscription = {
|
|
111
120
|
name: 'todoList',
|
|
112
|
-
|
|
113
|
-
|
|
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,
|
|
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.
|
|
24
|
+
tauri-plugin-syncular = { version = "0.60.0", 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
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
}
|
|
@@ -72,11 +72,8 @@ async function main(): Promise<void> {
|
|
|
72
72
|
onSynced: () => void refresh(),
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
66
|
-
a.subscribe(
|
|
67
|
-
b.subscribe(
|
|
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:
|
|
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
|
-
/**
|
|
109
|
+
/** Unit template for the 'todoList' subscription (SPEC §4.1). */
|
|
110
110
|
export const todoListSubscription = {
|
|
111
111
|
name: 'todoList',
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
}
|