@syncular/typegen 0.15.39 → 0.15.42
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/README.md +12 -4
- package/dist/sql.js +8 -1
- package/package.json +3 -3
- package/src/sql.ts +12 -1
package/README.md
CHANGED
|
@@ -148,12 +148,20 @@ silently invent a value for them. `baseline`, `migrations check`, and
|
|
|
148
148
|
`generate` therefore reject `ALTER TABLE … ADD COLUMN … NOT NULL`, including
|
|
149
149
|
one with a literal default.
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
### Data changes and backfills
|
|
152
|
+
|
|
153
|
+
Migration SQL is schema-only. `UPDATE`, `INSERT`, and `DELETE` do not mutate
|
|
154
|
+
accepted Syncular row payloads and are rejected before their inner SQL is
|
|
155
|
+
parsed, with a diagnostic linking to this rollout contract. Keep the old
|
|
156
|
+
representation available until the new one is proven complete.
|
|
157
|
+
|
|
158
|
+
Use an expand/backfill/validate/retire rollout instead: add the trailing column as
|
|
152
159
|
nullable; deploy that schema; fill existing rows with versioned,
|
|
153
160
|
server-authoritative writes under a new idempotency key; then enforce the
|
|
154
|
-
required value in host validation.
|
|
155
|
-
|
|
156
|
-
the
|
|
161
|
+
required value in host validation. Validate the backfill and every supported
|
|
162
|
+
client before retiring an old column or table in a later schema version. Do not
|
|
163
|
+
tighten the synced column's nullability in a later migration. `generate`
|
|
164
|
+
appends a valid new migration to the lock, while
|
|
157
165
|
`generate --check` fails until that updated lock and generated outputs are
|
|
158
166
|
committed. Drift diagnostics name the locked migration and the first affected
|
|
159
167
|
table/column without printing SQL or local paths.
|
package/dist/sql.js
CHANGED
|
@@ -54,6 +54,8 @@ const DEFAULT_CRDT_TYPE = 'yjs-doc';
|
|
|
54
54
|
const WORD_START = /[\p{L}_]/u;
|
|
55
55
|
const WORD_PART = /[\p{L}\p{M}\p{N}_]/u;
|
|
56
56
|
const DIGIT = /[0-9]/;
|
|
57
|
+
const DATA_MUTATION_STATEMENTS = new Set(['UPDATE', 'INSERT', 'DELETE']);
|
|
58
|
+
const DATA_MUTATION_GUIDANCE = 'Syncular migration SQL is schema-only: retain the old representation, deploy a nullable expansion, backfill through versioned server-authoritative Syncular writes under a new idempotency key, validate future writes, then retire the old representation in a later schema version. See https://syncular.dev/guide-schema/#data-changes-and-backfills';
|
|
57
59
|
const tableIdentifierSources = new WeakMap();
|
|
58
60
|
const columnIdentifierSources = new WeakMap();
|
|
59
61
|
const indexIdentifierSources = new WeakMap();
|
|
@@ -139,7 +141,12 @@ function tokenizeStatements(sql, source) {
|
|
|
139
141
|
let end = i + 1;
|
|
140
142
|
while (end < sql.length && WORD_PART.test(sql[end]))
|
|
141
143
|
end += 1;
|
|
142
|
-
|
|
144
|
+
const text = sql.slice(i, end);
|
|
145
|
+
current.push({ kind: 'word', text });
|
|
146
|
+
const statementKind = text.toUpperCase();
|
|
147
|
+
if (current.length === 1 && DATA_MUTATION_STATEMENTS.has(statementKind)) {
|
|
148
|
+
throw new TypegenError(source, `${statementKind} data migration is unsupported. ${DATA_MUTATION_GUIDANCE}`);
|
|
149
|
+
}
|
|
143
150
|
i = end;
|
|
144
151
|
}
|
|
145
152
|
else if (DIGIT.test(ch)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncular/typegen",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.42",
|
|
4
4
|
"description": "Syncular schema-to-TypeScript type generator and the `syncular` CLI",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"!dist/**/*.test.d.ts"
|
|
57
57
|
],
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@syncular/core": "0.15.
|
|
59
|
+
"@syncular/core": "0.15.42"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@syncular/server": "0.15.
|
|
62
|
+
"@syncular/server": "0.15.42"
|
|
63
63
|
}
|
|
64
64
|
}
|
package/src/sql.ts
CHANGED
|
@@ -73,6 +73,9 @@ interface Token {
|
|
|
73
73
|
const WORD_START = /[\p{L}_]/u;
|
|
74
74
|
const WORD_PART = /[\p{L}\p{M}\p{N}_]/u;
|
|
75
75
|
const DIGIT = /[0-9]/;
|
|
76
|
+
const DATA_MUTATION_STATEMENTS = new Set(['UPDATE', 'INSERT', 'DELETE']);
|
|
77
|
+
const DATA_MUTATION_GUIDANCE =
|
|
78
|
+
'Syncular migration SQL is schema-only: retain the old representation, deploy a nullable expansion, backfill through versioned server-authoritative Syncular writes under a new idempotency key, validate future writes, then retire the old representation in a later schema version. See https://syncular.dev/guide-schema/#data-changes-and-backfills';
|
|
76
79
|
|
|
77
80
|
const tableIdentifierSources = new WeakMap<ParsedTable, string>();
|
|
78
81
|
const columnIdentifierSources = new WeakMap<IrColumn, string>();
|
|
@@ -170,7 +173,15 @@ function tokenizeStatements(sql: string, source: string): Token[][] {
|
|
|
170
173
|
} else if (WORD_START.test(ch)) {
|
|
171
174
|
let end = i + 1;
|
|
172
175
|
while (end < sql.length && WORD_PART.test(sql[end] as string)) end += 1;
|
|
173
|
-
|
|
176
|
+
const text = sql.slice(i, end);
|
|
177
|
+
current.push({ kind: 'word', text });
|
|
178
|
+
const statementKind = text.toUpperCase();
|
|
179
|
+
if (current.length === 1 && DATA_MUTATION_STATEMENTS.has(statementKind)) {
|
|
180
|
+
throw new TypegenError(
|
|
181
|
+
source,
|
|
182
|
+
`${statementKind} data migration is unsupported. ${DATA_MUTATION_GUIDANCE}`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
174
185
|
i = end;
|
|
175
186
|
} else if (DIGIT.test(ch)) {
|
|
176
187
|
let end = i + 1;
|