create-syncular-app 0.5.1 → 0.6.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-syncular-app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Scaffold a new Syncular app: `create-syncular-app`",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -49,6 +49,6 @@
|
|
|
49
49
|
"!dist/**/*.test.d.ts"
|
|
50
50
|
],
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@syncular/typegen": "0.
|
|
52
|
+
"@syncular/typegen": "0.6.0"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
query listTodos(listId) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
sql {
|
|
3
|
+
select id, list_id, title, done, position, updated_at_ms
|
|
4
|
+
from todos
|
|
5
|
+
where @scope(todos.list_id = :listId)
|
|
6
|
+
order by position, id
|
|
7
|
+
}
|
|
6
8
|
}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
// Generated by @syncular/typegen — DO NOT EDIT.
|
|
2
2
|
// irVersion: 1
|
|
3
|
-
// irHash: sha256:
|
|
3
|
+
// irHash: sha256:14904cd41e8ae90720d152cd47a944d2f01bf8572b97e32fa71cda8909cab768
|
|
4
|
+
|
|
5
|
+
export type SyqlRuntimeErrorCode =
|
|
6
|
+
| 'SYQL_RUNTIME_MISSING_REQUIRED_INPUT'
|
|
7
|
+
| 'SYQL_RUNTIME_UNKNOWN_INPUT'
|
|
8
|
+
| 'SYQL_RUNTIME_INVALID_INPUT'
|
|
9
|
+
| 'SYQL_RUNTIME_INVALID_GROUP'
|
|
10
|
+
| 'SYQL_RUNTIME_INVALID_SORT'
|
|
11
|
+
| 'SYQL_RUNTIME_INVALID_PAGE';
|
|
12
|
+
|
|
13
|
+
export class SyqlInputError extends Error {
|
|
14
|
+
readonly name = 'SyqlInputError';
|
|
15
|
+
constructor(readonly code: SyqlRuntimeErrorCode, message: string) {
|
|
16
|
+
super(message);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface SyqlPresent<T> {
|
|
21
|
+
readonly present: true;
|
|
22
|
+
readonly value: T;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function syqlPresent<T>(value: T): SyqlPresent<T> {
|
|
26
|
+
return { present: true, value };
|
|
27
|
+
}
|
|
4
28
|
|
|
5
29
|
/** A bindable SQL param/row value (the wrapper's SqlValue subset). */
|
|
6
30
|
export type QueryValue =
|
|
@@ -25,8 +49,7 @@ export interface QueryClient {
|
|
|
25
49
|
* `bind(params)` → positional args. Consumed by
|
|
26
50
|
* `@syncular/react`'s `useQuery`. `Row` is the projection row
|
|
27
51
|
* type; `Params` is `undefined` for a param-less query. `sqlFor`
|
|
28
|
-
*
|
|
29
|
-
* generate-time-checked column allowlist. */
|
|
52
|
+
* selects a checked revision-1 SYQL physical statement when needed. */
|
|
30
53
|
export interface NamedQuery<Row, Params = undefined> {
|
|
31
54
|
readonly id: string;
|
|
32
55
|
readonly hasParams: boolean;
|
|
@@ -66,34 +89,55 @@ export interface ListTodosRow {
|
|
|
66
89
|
updatedAtMs: number;
|
|
67
90
|
}
|
|
68
91
|
|
|
69
|
-
/**
|
|
92
|
+
/** Public revision-1 SYQL inputs for 'listTodos'. */
|
|
70
93
|
export interface ListTodosParams {
|
|
71
94
|
listId: string;
|
|
72
95
|
}
|
|
73
96
|
|
|
97
|
+
function listTodosValidate(raw?: ListTodosParams): ListTodosParams {
|
|
98
|
+
const params = raw ?? ({} as ListTodosParams);
|
|
99
|
+
const allowed = new Set(['listId']);
|
|
100
|
+
for (const key of Object.keys(params)) {
|
|
101
|
+
if (!allowed.has(key)) throw new SyqlInputError('SYQL_RUNTIME_UNKNOWN_INPUT', 'listTodos' + ': unknown input ' + key);
|
|
102
|
+
}
|
|
103
|
+
if (!Object.prototype.hasOwnProperty.call(params, 'listId')) throw new SyqlInputError('SYQL_RUNTIME_MISSING_REQUIRED_INPUT', 'listTodos: missing required input listId');
|
|
104
|
+
if (!(typeof params.listId === 'string')) throw new SyqlInputError('SYQL_RUNTIME_INVALID_INPUT', 'listTodos: invalid input listId');
|
|
105
|
+
return params;
|
|
106
|
+
}
|
|
107
|
+
|
|
74
108
|
/** Tables 'listTodos' reads (compatibility/export surface). */
|
|
75
109
|
export const listTodosTables = ['todos'] as const;
|
|
76
110
|
|
|
77
|
-
const
|
|
111
|
+
const listTodosStatements: { sql: string; bind: (params: ListTodosParams) => QueryValue[] }[] = [
|
|
112
|
+
{ sql: 'select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos where (todos.list_id = ?) order by position, id', bind: (params) => [params.listId] },
|
|
113
|
+
];
|
|
114
|
+
function listTodosSelect(raw: ListTodosParams): { sql: string; bind: QueryValue[] } {
|
|
115
|
+
const params = listTodosValidate(raw);
|
|
116
|
+
let mask = 0;
|
|
117
|
+
const statement = listTodosStatements[mask * 1 + 0];
|
|
118
|
+
if (statement === undefined) throw new Error('invalid generated SYQL statement index');
|
|
119
|
+
return { sql: statement.sql, bind: statement.bind(params) };
|
|
120
|
+
}
|
|
78
121
|
|
|
79
122
|
/** Run the 'listTodos' named query (SELECT-only). */
|
|
80
123
|
export async function listTodos(client: QueryClient, params: ListTodosParams): Promise<ListTodosRow[]> {
|
|
81
|
-
const
|
|
124
|
+
const selected = listTodosSelect(params);
|
|
125
|
+
const rows = await client.query(selected.sql, selected.bind);
|
|
82
126
|
return rows as unknown as ListTodosRow[];
|
|
83
127
|
}
|
|
84
128
|
|
|
85
129
|
/** Revisioned reactive descriptor for `useQuery(listTodosQuery, params)`. */
|
|
86
130
|
export const listTodosQuery: NamedQuery<ListTodosRow, ListTodosParams> = {
|
|
87
|
-
id: 'sha256:
|
|
131
|
+
id: 'sha256:14904cd41e8ae90720d152cd47a944d2f01bf8572b97e32fa71cda8909cab768/listTodos',
|
|
88
132
|
hasParams: true,
|
|
89
|
-
sql:
|
|
133
|
+
sql: 'select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos where (todos.list_id = ?) order by position, id',
|
|
134
|
+
sqlFor: (params: ListTodosParams) => listTodosSelect(params).sql,
|
|
90
135
|
tables: listTodosTables,
|
|
91
136
|
dependencies: (params) => [
|
|
92
137
|
{ table: 'todos', scopeKeys: ['list:' + String(params.listId) + ''] },
|
|
93
138
|
],
|
|
94
|
-
coverage: (
|
|
95
|
-
{ base: { table: 'todos', variable: 'list_id' }, units: [String(params.listId)] },
|
|
139
|
+
coverage: () => [
|
|
96
140
|
],
|
|
97
|
-
bind: (params: ListTodosParams) =>
|
|
141
|
+
bind: (params: ListTodosParams) => listTodosSelect(params).bind,
|
|
98
142
|
rowKey: (row) => [row.id],
|
|
99
143
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"queryIrVersion":
|
|
2
|
+
"queryIrVersion": 3,
|
|
3
3
|
"queries": [
|
|
4
4
|
{
|
|
5
5
|
"name": "listTodos",
|
|
6
|
-
"file": "list-todos.syql
|
|
7
|
-
"sourceSql": "select id, list_id, title, done, position, updated_at_ms
|
|
8
|
-
"sql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos
|
|
9
|
-
"positionalSql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos where list_id = ? order by position, id",
|
|
6
|
+
"file": "list-todos.syql",
|
|
7
|
+
"sourceSql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos\n where (todos.list_id = :listId)\n order by position, id",
|
|
8
|
+
"sql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos\n where (todos.list_id = :listId)\n order by position, id",
|
|
9
|
+
"positionalSql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos where (todos.list_id = ?) order by position, id",
|
|
10
10
|
"params": [
|
|
11
11
|
{
|
|
12
12
|
"name": "listId",
|
|
@@ -100,17 +100,44 @@
|
|
|
100
100
|
]
|
|
101
101
|
}
|
|
102
102
|
],
|
|
103
|
-
"coverage": [
|
|
103
|
+
"coverage": [],
|
|
104
|
+
"rowKey": [
|
|
105
|
+
"id"
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"syql": {
|
|
109
|
+
"revision": 1,
|
|
110
|
+
"inputs": [
|
|
104
111
|
{
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"
|
|
112
|
+
"kind": "value",
|
|
113
|
+
"name": "listId",
|
|
114
|
+
"langName": "listId",
|
|
115
|
+
"type": "string",
|
|
116
|
+
"nullable": false,
|
|
117
|
+
"required": true
|
|
111
118
|
}
|
|
112
119
|
],
|
|
113
|
-
"
|
|
120
|
+
"plan": {
|
|
121
|
+
"backend": "variants",
|
|
122
|
+
"activationControls": [],
|
|
123
|
+
"conditions": [],
|
|
124
|
+
"statements": [
|
|
125
|
+
{
|
|
126
|
+
"activationMask": 0,
|
|
127
|
+
"sql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos\n where (todos.list_id = :listId)\n order by position, id",
|
|
128
|
+
"positionalSql": "select id, list_id AS listId, title, done, position, updated_at_ms AS updatedAtMs from todos where (todos.list_id = ?) order by position, id",
|
|
129
|
+
"binds": [
|
|
130
|
+
{
|
|
131
|
+
"kind": "value",
|
|
132
|
+
"name": "listId",
|
|
133
|
+
"type": "string",
|
|
134
|
+
"input": "listId"
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
"identity": [
|
|
114
141
|
"id"
|
|
115
142
|
]
|
|
116
143
|
}
|