@syncular/typegen 0.15.11 → 0.15.12
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 +11 -1
- package/dist/sql.js +35 -3
- package/package.json +3 -3
- package/src/sql.ts +47 -3
package/README.md
CHANGED
|
@@ -184,6 +184,7 @@ duplicate ordinals are errors). The parser accepts exactly:
|
|
|
184
184
|
- `CREATE TABLE [IF NOT EXISTS] name ( column-defs…, [PRIMARY KEY (col)] ) [WITHOUT ROWID]`
|
|
185
185
|
- `ALTER TABLE name ADD [COLUMN] column-def`
|
|
186
186
|
- `CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON table ( col [, col…] )`
|
|
187
|
+
- `DROP INDEX [IF EXISTS] name`
|
|
187
188
|
- `DROP TABLE [IF EXISTS] name`
|
|
188
189
|
- `CREATE VIRTUAL TABLE [IF NOT EXISTS] name USING fts5( text-col [, text-col…], content = table [, tokenize = 'allowlisted tokenizer'] )`
|
|
189
190
|
- column-def: `name TYPE [PRIMARY KEY] [NOT NULL] [NULL] [DEFAULT literal]`
|
|
@@ -217,6 +218,15 @@ is bare column names: **ASC/DESC**, **expression** columns (`lower(a)`), and
|
|
|
217
218
|
**partial** (`WHERE …`) indexes are hard errors (the IR models column names
|
|
218
219
|
only, so accepting a direction/expression would silently drop it).
|
|
219
220
|
|
|
221
|
+
**Index replacement** (`DROP INDEX`). A previously declared secondary index
|
|
222
|
+
may be removed with `DROP INDEX name` or conditionally with `IF EXISTS`.
|
|
223
|
+
Generation removes it from the head IR; a later `CREATE INDEX` may reuse the
|
|
224
|
+
name with a different uniqueness or column definition. On a server schema
|
|
225
|
+
bump, Syncular rebuilds the declared secondary indexes for its owned
|
|
226
|
+
relational projection tables before advancing the version marker. Client
|
|
227
|
+
mirrors already wipe and re-bootstrap application tables on every schema
|
|
228
|
+
version change.
|
|
229
|
+
|
|
220
230
|
**Table retirement** (`DROP TABLE`). A table created earlier in migration
|
|
221
231
|
history and dropped before the head version is absent from the IR and must be
|
|
222
232
|
omitted from the manifest's `tables` list. `IF EXISTS` is supported. Reusing a
|
|
@@ -246,7 +256,7 @@ There is no automatic `LIKE` fallback when FTS5 is unavailable; local schema
|
|
|
246
256
|
creation fails loudly.
|
|
247
257
|
|
|
248
258
|
**Hard errors** (each names the construct and source file): any other
|
|
249
|
-
statement (`CREATE TRIGGER/VIEW`,
|
|
259
|
+
statement (`CREATE TRIGGER/VIEW`, DML, `ALTER … RENAME`, …); unknown
|
|
250
260
|
or parameterized types (`VARCHAR(36)`); quoted identifiers
|
|
251
261
|
(`"t"`, `` `t` ``, `[t]`); table constraints (`FOREIGN KEY`, `UNIQUE`,
|
|
252
262
|
`CHECK`, `CONSTRAINT`); column constraints beyond the list above
|
package/dist/sql.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* [WITHOUT ROWID]`
|
|
8
8
|
* - `ALTER TABLE name ADD [COLUMN] coldef`
|
|
9
9
|
* - `CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON table (col [, col…])`
|
|
10
|
+
* - `DROP INDEX [IF EXISTS] name`
|
|
10
11
|
* - `DROP TABLE [IF EXISTS] name`
|
|
11
12
|
* - `CREATE VIRTUAL TABLE name USING fts5(cols…, content=table,
|
|
12
13
|
* [tokenize='allowlisted tokenizer'])` (RFC 0005 local projection)
|
|
@@ -548,7 +549,6 @@ function parseAlterTable(cursor, tables) {
|
|
|
548
549
|
}
|
|
549
550
|
/** `DROP TABLE [IF EXISTS] name`; table-name reuse remains unsupported. */
|
|
550
551
|
function parseDropTable(cursor, tables, droppedTables) {
|
|
551
|
-
cursor.expectWord('TABLE', 'after DROP');
|
|
552
552
|
let ifExists = false;
|
|
553
553
|
if (cursor.eatWord('IF')) {
|
|
554
554
|
cursor.expectWord('EXISTS', 'after IF');
|
|
@@ -564,6 +564,38 @@ function parseDropTable(cursor, tables, droppedTables) {
|
|
|
564
564
|
tables.delete(name);
|
|
565
565
|
droppedTables.add(name);
|
|
566
566
|
}
|
|
567
|
+
/** Remove one declared secondary index from the accumulated head schema. */
|
|
568
|
+
function parseDropIndex(cursor, tables) {
|
|
569
|
+
let ifExists = false;
|
|
570
|
+
if (cursor.eatWord('IF')) {
|
|
571
|
+
cursor.expectWord('EXISTS', 'after IF');
|
|
572
|
+
ifExists = true;
|
|
573
|
+
}
|
|
574
|
+
const name = cursor.identifier('an index name');
|
|
575
|
+
cursor.expectEnd();
|
|
576
|
+
for (const table of tables.values()) {
|
|
577
|
+
const index = table.indexes.findIndex((candidate) => candidate.name === name);
|
|
578
|
+
if (index < 0)
|
|
579
|
+
continue;
|
|
580
|
+
table.indexes.splice(index, 1);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
if (!ifExists) {
|
|
584
|
+
cursor.fail(`DROP INDEX ${name}: index does not exist at this point`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
function parseDrop(cursor, tables, droppedTables) {
|
|
588
|
+
if (cursor.eatWord('TABLE')) {
|
|
589
|
+
parseDropTable(cursor, tables, droppedTables);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (cursor.eatWord('INDEX')) {
|
|
593
|
+
parseDropIndex(cursor, tables);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const token = cursor.peek();
|
|
597
|
+
cursor.fail(`unsupported DROP statement (only DROP TABLE and DROP INDEX), found ${JSON.stringify(token?.text ?? '')}`);
|
|
598
|
+
}
|
|
567
599
|
/**
|
|
568
600
|
* Apply one migration file's SQL to the accumulated table map. Columns
|
|
569
601
|
* accumulate in declaration order — the §2.4 row-codec positional order.
|
|
@@ -580,10 +612,10 @@ export function applyMigrationSql(tables, sql, source, droppedTables = new Set()
|
|
|
580
612
|
parseAlterTable(cursor, tables);
|
|
581
613
|
}
|
|
582
614
|
else if (word === 'DROP') {
|
|
583
|
-
|
|
615
|
+
parseDrop(cursor, tables, droppedTables);
|
|
584
616
|
}
|
|
585
617
|
else {
|
|
586
|
-
throw new TypegenError(source, `unsupported SQL statement starting with ${JSON.stringify(head.text)} (only CREATE TABLE, CREATE [UNIQUE] INDEX, CREATE VIRTUAL TABLE … USING fts5, ALTER TABLE … ADD COLUMN, and DROP TABLE)`);
|
|
618
|
+
throw new TypegenError(source, `unsupported SQL statement starting with ${JSON.stringify(head.text)} (only CREATE TABLE, CREATE [UNIQUE] INDEX, CREATE VIRTUAL TABLE … USING fts5, ALTER TABLE … ADD COLUMN, DROP INDEX, and DROP TABLE)`);
|
|
587
619
|
}
|
|
588
620
|
}
|
|
589
621
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncular/typegen",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.12",
|
|
4
4
|
"description": "Syncular schema-to-TypeScript type generator and the `syncular` CLI",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"!dist/**/*.test.d.ts"
|
|
49
49
|
],
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@syncular/core": "0.15.
|
|
52
|
-
"@syncular/server": "0.15.
|
|
51
|
+
"@syncular/core": "0.15.12",
|
|
52
|
+
"@syncular/server": "0.15.12"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/sql.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* [WITHOUT ROWID]`
|
|
8
8
|
* - `ALTER TABLE name ADD [COLUMN] coldef`
|
|
9
9
|
* - `CREATE [UNIQUE] INDEX [IF NOT EXISTS] name ON table (col [, col…])`
|
|
10
|
+
* - `DROP INDEX [IF EXISTS] name`
|
|
10
11
|
* - `DROP TABLE [IF EXISTS] name`
|
|
11
12
|
* - `CREATE VIRTUAL TABLE name USING fts5(cols…, content=table,
|
|
12
13
|
* [tokenize='allowlisted tokenizer'])` (RFC 0005 local projection)
|
|
@@ -680,7 +681,6 @@ function parseDropTable(
|
|
|
680
681
|
tables: Map<string, ParsedTable>,
|
|
681
682
|
droppedTables: Set<string>,
|
|
682
683
|
): void {
|
|
683
|
-
cursor.expectWord('TABLE', 'after DROP');
|
|
684
684
|
let ifExists = false;
|
|
685
685
|
if (cursor.eatWord('IF')) {
|
|
686
686
|
cursor.expectWord('EXISTS', 'after IF');
|
|
@@ -696,6 +696,50 @@ function parseDropTable(
|
|
|
696
696
|
droppedTables.add(name);
|
|
697
697
|
}
|
|
698
698
|
|
|
699
|
+
/** Remove one declared secondary index from the accumulated head schema. */
|
|
700
|
+
function parseDropIndex(
|
|
701
|
+
cursor: Cursor,
|
|
702
|
+
tables: Map<string, ParsedTable>,
|
|
703
|
+
): void {
|
|
704
|
+
let ifExists = false;
|
|
705
|
+
if (cursor.eatWord('IF')) {
|
|
706
|
+
cursor.expectWord('EXISTS', 'after IF');
|
|
707
|
+
ifExists = true;
|
|
708
|
+
}
|
|
709
|
+
const name = cursor.identifier('an index name');
|
|
710
|
+
cursor.expectEnd();
|
|
711
|
+
for (const table of tables.values()) {
|
|
712
|
+
const index = table.indexes.findIndex(
|
|
713
|
+
(candidate) => candidate.name === name,
|
|
714
|
+
);
|
|
715
|
+
if (index < 0) continue;
|
|
716
|
+
table.indexes.splice(index, 1);
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
if (!ifExists) {
|
|
720
|
+
cursor.fail(`DROP INDEX ${name}: index does not exist at this point`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function parseDrop(
|
|
725
|
+
cursor: Cursor,
|
|
726
|
+
tables: Map<string, ParsedTable>,
|
|
727
|
+
droppedTables: Set<string>,
|
|
728
|
+
): void {
|
|
729
|
+
if (cursor.eatWord('TABLE')) {
|
|
730
|
+
parseDropTable(cursor, tables, droppedTables);
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (cursor.eatWord('INDEX')) {
|
|
734
|
+
parseDropIndex(cursor, tables);
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
const token = cursor.peek();
|
|
738
|
+
cursor.fail(
|
|
739
|
+
`unsupported DROP statement (only DROP TABLE and DROP INDEX), found ${JSON.stringify(token?.text ?? '')}`,
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
|
|
699
743
|
/**
|
|
700
744
|
* Apply one migration file's SQL to the accumulated table map. Columns
|
|
701
745
|
* accumulate in declaration order — the §2.4 row-codec positional order.
|
|
@@ -715,11 +759,11 @@ export function applyMigrationSql(
|
|
|
715
759
|
} else if (word === 'ALTER') {
|
|
716
760
|
parseAlterTable(cursor, tables);
|
|
717
761
|
} else if (word === 'DROP') {
|
|
718
|
-
|
|
762
|
+
parseDrop(cursor, tables, droppedTables);
|
|
719
763
|
} else {
|
|
720
764
|
throw new TypegenError(
|
|
721
765
|
source,
|
|
722
|
-
`unsupported SQL statement starting with ${JSON.stringify(head.text)} (only CREATE TABLE, CREATE [UNIQUE] INDEX, CREATE VIRTUAL TABLE … USING fts5, ALTER TABLE … ADD COLUMN, and DROP TABLE)`,
|
|
766
|
+
`unsupported SQL statement starting with ${JSON.stringify(head.text)} (only CREATE TABLE, CREATE [UNIQUE] INDEX, CREATE VIRTUAL TABLE … USING fts5, ALTER TABLE … ADD COLUMN, DROP INDEX, and DROP TABLE)`,
|
|
723
767
|
);
|
|
724
768
|
}
|
|
725
769
|
}
|