@axium/server 0.36.6 → 0.37.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/dist/acl.d.ts +1 -0
- package/dist/acl.js +1 -1
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +30 -9
- package/dist/database.d.ts +11 -507
- package/dist/database.js +8 -557
- package/dist/db/connection.d.ts +5 -0
- package/dist/db/connection.js +18 -0
- package/dist/db/data.d.ts +119 -0
- package/dist/db/data.js +113 -0
- package/dist/db/delta.d.ts +147 -0
- package/dist/db/delta.js +390 -0
- package/dist/db/schema.d.ts +268 -0
- package/dist/db/schema.js +169 -0
- package/dist/{db.json → db/schema.json} +5 -3
- package/dist/main.js +37 -23
- package/package.json +2 -2
- package/routes/admin/users/+page.svelte +1 -1
- package/schemas/db.json +48 -13
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import type { Expand, MutableRecursive, ReadonlyRecursive } from 'utilium';
|
|
2
|
+
import * as z from 'zod';
|
|
3
|
+
import raw from './schema.json';
|
|
4
|
+
import { Table, type Column, type TableValue } from './data.js';
|
|
5
|
+
import * as delta from './delta.js';
|
|
6
|
+
export * from './data.js';
|
|
7
|
+
export declare const SchemaDecl: z.ZodObject<{
|
|
8
|
+
tables: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
9
|
+
columns: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
10
|
+
type: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"bigint" | "boolean" | "uuid" | "date" | "binary" | "integer" | "int2" | "int4" | "int8" | "smallint" | "real" | "double precision" | "float4" | "float8" | "decimal" | "numeric" | "serial" | "bigserial" | "bool" | "varchar" | "char" | "text" | "datetime" | "time" | "timetz" | "timestamp" | "timestamptz" | "bytea" | "varbinary" | "blob" | "int4range" | "numrange" | "tsrange" | "tstzrange" | "daterange" | "int4multirange" | "int8multirange" | "nummultirange" | "tsmultirange" | "tstzmultirange" | "datemultirange" | "json" | "jsonb">, z.ZodTemplateLiteral<`binary(${number})` | `varchar(${number})` | `char(${number})` | `datetime(${number})` | `time(${number})` | `timetz(${number})` | `timestamp(${number})` | `timestamptz(${number})` | `varbinary(${number})`>, z.ZodTemplateLiteral<`decimal(${number},${number})` | `decimal(${number}, ${number})` | `numeric(${number},${number})` | `numeric(${number}, ${number})`>]>, z.ZodTemplateLiteral<"bigint[]" | "boolean[]" | "uuid[]" | "date[]" | "binary[]" | "integer[]" | "int2[]" | "int4[]" | "int8[]" | "smallint[]" | "real[]" | "double precision[]" | "float4[]" | "float8[]" | "decimal[]" | "numeric[]" | "serial[]" | "bigserial[]" | "bool[]" | "varchar[]" | "char[]" | "text[]" | "datetime[]" | "time[]" | "timetz[]" | "timestamp[]" | "timestamptz[]" | "bytea[]" | "varbinary[]" | "blob[]" | "int4range[]" | "numrange[]" | "tsrange[]" | "tstzrange[]" | "daterange[]" | "int4multirange[]" | "int8multirange[]" | "nummultirange[]" | "tsmultirange[]" | "tstzmultirange[]" | "datemultirange[]" | "json[]" | "jsonb[]" | `binary(${number})[]` | `varchar(${number})[]` | `char(${number})[]` | `datetime(${number})[]` | `time(${number})[]` | `timetz(${number})[]` | `timestamp(${number})[]` | `timestamptz(${number})[]` | `varbinary(${number})[]` | `decimal(${number},${number})[]` | `decimal(${number}, ${number})[]` | `numeric(${number},${number})[]` | `numeric(${number}, ${number})[]` | `bigint[${number}]` | `boolean[${number}]` | `uuid[${number}]` | `date[${number}]` | `binary[${number}]` | `integer[${number}]` | `int2[${number}]` | `int4[${number}]` | `int8[${number}]` | `smallint[${number}]` | `real[${number}]` | `double precision[${number}]` | `float4[${number}]` | `float8[${number}]` | `decimal[${number}]` | `numeric[${number}]` | `serial[${number}]` | `bigserial[${number}]` | `bool[${number}]` | `varchar[${number}]` | `char[${number}]` | `text[${number}]` | `datetime[${number}]` | `time[${number}]` | `timetz[${number}]` | `timestamp[${number}]` | `timestamptz[${number}]` | `bytea[${number}]` | `varbinary[${number}]` | `blob[${number}]` | `int4range[${number}]` | `numrange[${number}]` | `tsrange[${number}]` | `tstzrange[${number}]` | `daterange[${number}]` | `int4multirange[${number}]` | `int8multirange[${number}]` | `nummultirange[${number}]` | `tsmultirange[${number}]` | `tstzmultirange[${number}]` | `datemultirange[${number}]` | `json[${number}]` | `jsonb[${number}]` | `binary(${number})[${number}]` | `varchar(${number})[${number}]` | `char(${number})[${number}]` | `datetime(${number})[${number}]` | `time(${number})[${number}]` | `timetz(${number})[${number}]` | `timestamp(${number})[${number}]` | `timestamptz(${number})[${number}]` | `varbinary(${number})[${number}]` | `decimal(${number},${number})[${number}]` | `decimal(${number}, ${number})[${number}]` | `numeric(${number},${number})[${number}]` | `numeric(${number}, ${number})[${number}]`>]>;
|
|
11
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
12
|
+
unique: z.ZodDefault<z.ZodBoolean>;
|
|
13
|
+
primary: z.ZodDefault<z.ZodBoolean>;
|
|
14
|
+
references: z.ZodOptional<z.ZodString>;
|
|
15
|
+
onDelete: z.ZodOptional<z.ZodEnum<{
|
|
16
|
+
cascade: "cascade";
|
|
17
|
+
restrict: "restrict";
|
|
18
|
+
"no action": "no action";
|
|
19
|
+
"set null": "set null";
|
|
20
|
+
"set default": "set default";
|
|
21
|
+
}>>;
|
|
22
|
+
default: z.ZodOptional<z.ZodAny>;
|
|
23
|
+
check: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, z.core.$strict>>;
|
|
25
|
+
constraints: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
26
|
+
type: z.ZodLiteral<"primary_key">;
|
|
27
|
+
on: z.ZodArray<z.ZodString>;
|
|
28
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
29
|
+
type: z.ZodLiteral<"foreign_key">;
|
|
30
|
+
on: z.ZodArray<z.ZodString>;
|
|
31
|
+
target: z.ZodString;
|
|
32
|
+
references: z.ZodArray<z.ZodString>;
|
|
33
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
34
|
+
type: z.ZodLiteral<"unique">;
|
|
35
|
+
on: z.ZodArray<z.ZodString>;
|
|
36
|
+
nulls_not_distinct: z.ZodOptional<z.ZodBoolean>;
|
|
37
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
38
|
+
type: z.ZodLiteral<"check">;
|
|
39
|
+
check: z.ZodString;
|
|
40
|
+
}, z.core.$strict>], "type">>>>;
|
|
41
|
+
}, z.core.$strict>>;
|
|
42
|
+
indexes: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
43
|
+
on: z.ZodString;
|
|
44
|
+
columns: z.ZodArray<z.ZodString>;
|
|
45
|
+
}, z.core.$strict>>;
|
|
46
|
+
}, z.core.$strict>;
|
|
47
|
+
export interface SchemaDecl extends z.infer<typeof SchemaDecl> {
|
|
48
|
+
}
|
|
49
|
+
export declare const SchemaFile: z.ZodObject<{
|
|
50
|
+
format: z.ZodLiteral<1>;
|
|
51
|
+
versions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
52
|
+
tables: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
53
|
+
columns: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
54
|
+
type: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"bigint" | "boolean" | "uuid" | "date" | "binary" | "integer" | "int2" | "int4" | "int8" | "smallint" | "real" | "double precision" | "float4" | "float8" | "decimal" | "numeric" | "serial" | "bigserial" | "bool" | "varchar" | "char" | "text" | "datetime" | "time" | "timetz" | "timestamp" | "timestamptz" | "bytea" | "varbinary" | "blob" | "int4range" | "numrange" | "tsrange" | "tstzrange" | "daterange" | "int4multirange" | "int8multirange" | "nummultirange" | "tsmultirange" | "tstzmultirange" | "datemultirange" | "json" | "jsonb">, z.ZodTemplateLiteral<`binary(${number})` | `varchar(${number})` | `char(${number})` | `datetime(${number})` | `time(${number})` | `timetz(${number})` | `timestamp(${number})` | `timestamptz(${number})` | `varbinary(${number})`>, z.ZodTemplateLiteral<`decimal(${number},${number})` | `decimal(${number}, ${number})` | `numeric(${number},${number})` | `numeric(${number}, ${number})`>]>, z.ZodTemplateLiteral<"bigint[]" | "boolean[]" | "uuid[]" | "date[]" | "binary[]" | "integer[]" | "int2[]" | "int4[]" | "int8[]" | "smallint[]" | "real[]" | "double precision[]" | "float4[]" | "float8[]" | "decimal[]" | "numeric[]" | "serial[]" | "bigserial[]" | "bool[]" | "varchar[]" | "char[]" | "text[]" | "datetime[]" | "time[]" | "timetz[]" | "timestamp[]" | "timestamptz[]" | "bytea[]" | "varbinary[]" | "blob[]" | "int4range[]" | "numrange[]" | "tsrange[]" | "tstzrange[]" | "daterange[]" | "int4multirange[]" | "int8multirange[]" | "nummultirange[]" | "tsmultirange[]" | "tstzmultirange[]" | "datemultirange[]" | "json[]" | "jsonb[]" | `binary(${number})[]` | `varchar(${number})[]` | `char(${number})[]` | `datetime(${number})[]` | `time(${number})[]` | `timetz(${number})[]` | `timestamp(${number})[]` | `timestamptz(${number})[]` | `varbinary(${number})[]` | `decimal(${number},${number})[]` | `decimal(${number}, ${number})[]` | `numeric(${number},${number})[]` | `numeric(${number}, ${number})[]` | `bigint[${number}]` | `boolean[${number}]` | `uuid[${number}]` | `date[${number}]` | `binary[${number}]` | `integer[${number}]` | `int2[${number}]` | `int4[${number}]` | `int8[${number}]` | `smallint[${number}]` | `real[${number}]` | `double precision[${number}]` | `float4[${number}]` | `float8[${number}]` | `decimal[${number}]` | `numeric[${number}]` | `serial[${number}]` | `bigserial[${number}]` | `bool[${number}]` | `varchar[${number}]` | `char[${number}]` | `text[${number}]` | `datetime[${number}]` | `time[${number}]` | `timetz[${number}]` | `timestamp[${number}]` | `timestamptz[${number}]` | `bytea[${number}]` | `varbinary[${number}]` | `blob[${number}]` | `int4range[${number}]` | `numrange[${number}]` | `tsrange[${number}]` | `tstzrange[${number}]` | `daterange[${number}]` | `int4multirange[${number}]` | `int8multirange[${number}]` | `nummultirange[${number}]` | `tsmultirange[${number}]` | `tstzmultirange[${number}]` | `datemultirange[${number}]` | `json[${number}]` | `jsonb[${number}]` | `binary(${number})[${number}]` | `varchar(${number})[${number}]` | `char(${number})[${number}]` | `datetime(${number})[${number}]` | `time(${number})[${number}]` | `timetz(${number})[${number}]` | `timestamp(${number})[${number}]` | `timestamptz(${number})[${number}]` | `varbinary(${number})[${number}]` | `decimal(${number},${number})[${number}]` | `decimal(${number}, ${number})[${number}]` | `numeric(${number},${number})[${number}]` | `numeric(${number}, ${number})[${number}]`>]>;
|
|
55
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
56
|
+
unique: z.ZodDefault<z.ZodBoolean>;
|
|
57
|
+
primary: z.ZodDefault<z.ZodBoolean>;
|
|
58
|
+
references: z.ZodOptional<z.ZodString>;
|
|
59
|
+
onDelete: z.ZodOptional<z.ZodEnum<{
|
|
60
|
+
cascade: "cascade";
|
|
61
|
+
restrict: "restrict";
|
|
62
|
+
"no action": "no action";
|
|
63
|
+
"set null": "set null";
|
|
64
|
+
"set default": "set default";
|
|
65
|
+
}>>;
|
|
66
|
+
default: z.ZodOptional<z.ZodAny>;
|
|
67
|
+
check: z.ZodOptional<z.ZodString>;
|
|
68
|
+
}, z.core.$strict>>;
|
|
69
|
+
constraints: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
70
|
+
type: z.ZodLiteral<"primary_key">;
|
|
71
|
+
on: z.ZodArray<z.ZodString>;
|
|
72
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
73
|
+
type: z.ZodLiteral<"foreign_key">;
|
|
74
|
+
on: z.ZodArray<z.ZodString>;
|
|
75
|
+
target: z.ZodString;
|
|
76
|
+
references: z.ZodArray<z.ZodString>;
|
|
77
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
78
|
+
type: z.ZodLiteral<"unique">;
|
|
79
|
+
on: z.ZodArray<z.ZodString>;
|
|
80
|
+
nulls_not_distinct: z.ZodOptional<z.ZodBoolean>;
|
|
81
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
82
|
+
type: z.ZodLiteral<"check">;
|
|
83
|
+
check: z.ZodString;
|
|
84
|
+
}, z.core.$strict>], "type">>>>;
|
|
85
|
+
}, z.core.$strict>>;
|
|
86
|
+
indexes: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
87
|
+
on: z.ZodString;
|
|
88
|
+
columns: z.ZodArray<z.ZodString>;
|
|
89
|
+
}, z.core.$strict>>;
|
|
90
|
+
delta: z.ZodLiteral<false>;
|
|
91
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
92
|
+
delta: z.ZodLiteral<true>;
|
|
93
|
+
add_tables: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
94
|
+
columns: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
95
|
+
type: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"bigint" | "boolean" | "uuid" | "date" | "binary" | "integer" | "int2" | "int4" | "int8" | "smallint" | "real" | "double precision" | "float4" | "float8" | "decimal" | "numeric" | "serial" | "bigserial" | "bool" | "varchar" | "char" | "text" | "datetime" | "time" | "timetz" | "timestamp" | "timestamptz" | "bytea" | "varbinary" | "blob" | "int4range" | "numrange" | "tsrange" | "tstzrange" | "daterange" | "int4multirange" | "int8multirange" | "nummultirange" | "tsmultirange" | "tstzmultirange" | "datemultirange" | "json" | "jsonb">, z.ZodTemplateLiteral<`binary(${number})` | `varchar(${number})` | `char(${number})` | `datetime(${number})` | `time(${number})` | `timetz(${number})` | `timestamp(${number})` | `timestamptz(${number})` | `varbinary(${number})`>, z.ZodTemplateLiteral<`decimal(${number},${number})` | `decimal(${number}, ${number})` | `numeric(${number},${number})` | `numeric(${number}, ${number})`>]>, z.ZodTemplateLiteral<"bigint[]" | "boolean[]" | "uuid[]" | "date[]" | "binary[]" | "integer[]" | "int2[]" | "int4[]" | "int8[]" | "smallint[]" | "real[]" | "double precision[]" | "float4[]" | "float8[]" | "decimal[]" | "numeric[]" | "serial[]" | "bigserial[]" | "bool[]" | "varchar[]" | "char[]" | "text[]" | "datetime[]" | "time[]" | "timetz[]" | "timestamp[]" | "timestamptz[]" | "bytea[]" | "varbinary[]" | "blob[]" | "int4range[]" | "numrange[]" | "tsrange[]" | "tstzrange[]" | "daterange[]" | "int4multirange[]" | "int8multirange[]" | "nummultirange[]" | "tsmultirange[]" | "tstzmultirange[]" | "datemultirange[]" | "json[]" | "jsonb[]" | `binary(${number})[]` | `varchar(${number})[]` | `char(${number})[]` | `datetime(${number})[]` | `time(${number})[]` | `timetz(${number})[]` | `timestamp(${number})[]` | `timestamptz(${number})[]` | `varbinary(${number})[]` | `decimal(${number},${number})[]` | `decimal(${number}, ${number})[]` | `numeric(${number},${number})[]` | `numeric(${number}, ${number})[]` | `bigint[${number}]` | `boolean[${number}]` | `uuid[${number}]` | `date[${number}]` | `binary[${number}]` | `integer[${number}]` | `int2[${number}]` | `int4[${number}]` | `int8[${number}]` | `smallint[${number}]` | `real[${number}]` | `double precision[${number}]` | `float4[${number}]` | `float8[${number}]` | `decimal[${number}]` | `numeric[${number}]` | `serial[${number}]` | `bigserial[${number}]` | `bool[${number}]` | `varchar[${number}]` | `char[${number}]` | `text[${number}]` | `datetime[${number}]` | `time[${number}]` | `timetz[${number}]` | `timestamp[${number}]` | `timestamptz[${number}]` | `bytea[${number}]` | `varbinary[${number}]` | `blob[${number}]` | `int4range[${number}]` | `numrange[${number}]` | `tsrange[${number}]` | `tstzrange[${number}]` | `daterange[${number}]` | `int4multirange[${number}]` | `int8multirange[${number}]` | `nummultirange[${number}]` | `tsmultirange[${number}]` | `tstzmultirange[${number}]` | `datemultirange[${number}]` | `json[${number}]` | `jsonb[${number}]` | `binary(${number})[${number}]` | `varchar(${number})[${number}]` | `char(${number})[${number}]` | `datetime(${number})[${number}]` | `time(${number})[${number}]` | `timetz(${number})[${number}]` | `timestamp(${number})[${number}]` | `timestamptz(${number})[${number}]` | `varbinary(${number})[${number}]` | `decimal(${number},${number})[${number}]` | `decimal(${number}, ${number})[${number}]` | `numeric(${number},${number})[${number}]` | `numeric(${number}, ${number})[${number}]`>]>;
|
|
96
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
97
|
+
unique: z.ZodDefault<z.ZodBoolean>;
|
|
98
|
+
primary: z.ZodDefault<z.ZodBoolean>;
|
|
99
|
+
references: z.ZodOptional<z.ZodString>;
|
|
100
|
+
onDelete: z.ZodOptional<z.ZodEnum<{
|
|
101
|
+
cascade: "cascade";
|
|
102
|
+
restrict: "restrict";
|
|
103
|
+
"no action": "no action";
|
|
104
|
+
"set null": "set null";
|
|
105
|
+
"set default": "set default";
|
|
106
|
+
}>>;
|
|
107
|
+
default: z.ZodOptional<z.ZodAny>;
|
|
108
|
+
check: z.ZodOptional<z.ZodString>;
|
|
109
|
+
}, z.core.$strict>>;
|
|
110
|
+
constraints: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
111
|
+
type: z.ZodLiteral<"primary_key">;
|
|
112
|
+
on: z.ZodArray<z.ZodString>;
|
|
113
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
114
|
+
type: z.ZodLiteral<"foreign_key">;
|
|
115
|
+
on: z.ZodArray<z.ZodString>;
|
|
116
|
+
target: z.ZodString;
|
|
117
|
+
references: z.ZodArray<z.ZodString>;
|
|
118
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
119
|
+
type: z.ZodLiteral<"unique">;
|
|
120
|
+
on: z.ZodArray<z.ZodString>;
|
|
121
|
+
nulls_not_distinct: z.ZodOptional<z.ZodBoolean>;
|
|
122
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
123
|
+
type: z.ZodLiteral<"check">;
|
|
124
|
+
check: z.ZodString;
|
|
125
|
+
}, z.core.$strict>], "type">>>>;
|
|
126
|
+
}, z.core.$strict>>>>;
|
|
127
|
+
drop_tables: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
128
|
+
alter_tables: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
129
|
+
add_columns: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
130
|
+
type: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"bigint" | "boolean" | "uuid" | "date" | "binary" | "integer" | "int2" | "int4" | "int8" | "smallint" | "real" | "double precision" | "float4" | "float8" | "decimal" | "numeric" | "serial" | "bigserial" | "bool" | "varchar" | "char" | "text" | "datetime" | "time" | "timetz" | "timestamp" | "timestamptz" | "bytea" | "varbinary" | "blob" | "int4range" | "numrange" | "tsrange" | "tstzrange" | "daterange" | "int4multirange" | "int8multirange" | "nummultirange" | "tsmultirange" | "tstzmultirange" | "datemultirange" | "json" | "jsonb">, z.ZodTemplateLiteral<`binary(${number})` | `varchar(${number})` | `char(${number})` | `datetime(${number})` | `time(${number})` | `timetz(${number})` | `timestamp(${number})` | `timestamptz(${number})` | `varbinary(${number})`>, z.ZodTemplateLiteral<`decimal(${number},${number})` | `decimal(${number}, ${number})` | `numeric(${number},${number})` | `numeric(${number}, ${number})`>]>, z.ZodTemplateLiteral<"bigint[]" | "boolean[]" | "uuid[]" | "date[]" | "binary[]" | "integer[]" | "int2[]" | "int4[]" | "int8[]" | "smallint[]" | "real[]" | "double precision[]" | "float4[]" | "float8[]" | "decimal[]" | "numeric[]" | "serial[]" | "bigserial[]" | "bool[]" | "varchar[]" | "char[]" | "text[]" | "datetime[]" | "time[]" | "timetz[]" | "timestamp[]" | "timestamptz[]" | "bytea[]" | "varbinary[]" | "blob[]" | "int4range[]" | "numrange[]" | "tsrange[]" | "tstzrange[]" | "daterange[]" | "int4multirange[]" | "int8multirange[]" | "nummultirange[]" | "tsmultirange[]" | "tstzmultirange[]" | "datemultirange[]" | "json[]" | "jsonb[]" | `binary(${number})[]` | `varchar(${number})[]` | `char(${number})[]` | `datetime(${number})[]` | `time(${number})[]` | `timetz(${number})[]` | `timestamp(${number})[]` | `timestamptz(${number})[]` | `varbinary(${number})[]` | `decimal(${number},${number})[]` | `decimal(${number}, ${number})[]` | `numeric(${number},${number})[]` | `numeric(${number}, ${number})[]` | `bigint[${number}]` | `boolean[${number}]` | `uuid[${number}]` | `date[${number}]` | `binary[${number}]` | `integer[${number}]` | `int2[${number}]` | `int4[${number}]` | `int8[${number}]` | `smallint[${number}]` | `real[${number}]` | `double precision[${number}]` | `float4[${number}]` | `float8[${number}]` | `decimal[${number}]` | `numeric[${number}]` | `serial[${number}]` | `bigserial[${number}]` | `bool[${number}]` | `varchar[${number}]` | `char[${number}]` | `text[${number}]` | `datetime[${number}]` | `time[${number}]` | `timetz[${number}]` | `timestamp[${number}]` | `timestamptz[${number}]` | `bytea[${number}]` | `varbinary[${number}]` | `blob[${number}]` | `int4range[${number}]` | `numrange[${number}]` | `tsrange[${number}]` | `tstzrange[${number}]` | `daterange[${number}]` | `int4multirange[${number}]` | `int8multirange[${number}]` | `nummultirange[${number}]` | `tsmultirange[${number}]` | `tstzmultirange[${number}]` | `datemultirange[${number}]` | `json[${number}]` | `jsonb[${number}]` | `binary(${number})[${number}]` | `varchar(${number})[${number}]` | `char(${number})[${number}]` | `datetime(${number})[${number}]` | `time(${number})[${number}]` | `timetz(${number})[${number}]` | `timestamp(${number})[${number}]` | `timestamptz(${number})[${number}]` | `varbinary(${number})[${number}]` | `decimal(${number},${number})[${number}]` | `decimal(${number}, ${number})[${number}]` | `numeric(${number},${number})[${number}]` | `numeric(${number}, ${number})[${number}]`>]>;
|
|
131
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
132
|
+
unique: z.ZodDefault<z.ZodBoolean>;
|
|
133
|
+
primary: z.ZodDefault<z.ZodBoolean>;
|
|
134
|
+
references: z.ZodOptional<z.ZodString>;
|
|
135
|
+
onDelete: z.ZodOptional<z.ZodEnum<{
|
|
136
|
+
cascade: "cascade";
|
|
137
|
+
restrict: "restrict";
|
|
138
|
+
"no action": "no action";
|
|
139
|
+
"set null": "set null";
|
|
140
|
+
"set default": "set default";
|
|
141
|
+
}>>;
|
|
142
|
+
default: z.ZodOptional<z.ZodAny>;
|
|
143
|
+
check: z.ZodOptional<z.ZodString>;
|
|
144
|
+
}, z.core.$strict>>>>;
|
|
145
|
+
drop_columns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
146
|
+
alter_columns: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
147
|
+
type: z.ZodOptional<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodLiteral<"bigint" | "boolean" | "uuid" | "date" | "binary" | "integer" | "int2" | "int4" | "int8" | "smallint" | "real" | "double precision" | "float4" | "float8" | "decimal" | "numeric" | "serial" | "bigserial" | "bool" | "varchar" | "char" | "text" | "datetime" | "time" | "timetz" | "timestamp" | "timestamptz" | "bytea" | "varbinary" | "blob" | "int4range" | "numrange" | "tsrange" | "tstzrange" | "daterange" | "int4multirange" | "int8multirange" | "nummultirange" | "tsmultirange" | "tstzmultirange" | "datemultirange" | "json" | "jsonb">, z.ZodTemplateLiteral<`binary(${number})` | `varchar(${number})` | `char(${number})` | `datetime(${number})` | `time(${number})` | `timetz(${number})` | `timestamp(${number})` | `timestamptz(${number})` | `varbinary(${number})`>, z.ZodTemplateLiteral<`decimal(${number},${number})` | `decimal(${number}, ${number})` | `numeric(${number},${number})` | `numeric(${number}, ${number})`>]>, z.ZodTemplateLiteral<"bigint[]" | "boolean[]" | "uuid[]" | "date[]" | "binary[]" | "integer[]" | "int2[]" | "int4[]" | "int8[]" | "smallint[]" | "real[]" | "double precision[]" | "float4[]" | "float8[]" | "decimal[]" | "numeric[]" | "serial[]" | "bigserial[]" | "bool[]" | "varchar[]" | "char[]" | "text[]" | "datetime[]" | "time[]" | "timetz[]" | "timestamp[]" | "timestamptz[]" | "bytea[]" | "varbinary[]" | "blob[]" | "int4range[]" | "numrange[]" | "tsrange[]" | "tstzrange[]" | "daterange[]" | "int4multirange[]" | "int8multirange[]" | "nummultirange[]" | "tsmultirange[]" | "tstzmultirange[]" | "datemultirange[]" | "json[]" | "jsonb[]" | `binary(${number})[]` | `varchar(${number})[]` | `char(${number})[]` | `datetime(${number})[]` | `time(${number})[]` | `timetz(${number})[]` | `timestamp(${number})[]` | `timestamptz(${number})[]` | `varbinary(${number})[]` | `decimal(${number},${number})[]` | `decimal(${number}, ${number})[]` | `numeric(${number},${number})[]` | `numeric(${number}, ${number})[]` | `bigint[${number}]` | `boolean[${number}]` | `uuid[${number}]` | `date[${number}]` | `binary[${number}]` | `integer[${number}]` | `int2[${number}]` | `int4[${number}]` | `int8[${number}]` | `smallint[${number}]` | `real[${number}]` | `double precision[${number}]` | `float4[${number}]` | `float8[${number}]` | `decimal[${number}]` | `numeric[${number}]` | `serial[${number}]` | `bigserial[${number}]` | `bool[${number}]` | `varchar[${number}]` | `char[${number}]` | `text[${number}]` | `datetime[${number}]` | `time[${number}]` | `timetz[${number}]` | `timestamp[${number}]` | `timestamptz[${number}]` | `bytea[${number}]` | `varbinary[${number}]` | `blob[${number}]` | `int4range[${number}]` | `numrange[${number}]` | `tsrange[${number}]` | `tstzrange[${number}]` | `daterange[${number}]` | `int4multirange[${number}]` | `int8multirange[${number}]` | `nummultirange[${number}]` | `tsmultirange[${number}]` | `tstzmultirange[${number}]` | `datemultirange[${number}]` | `json[${number}]` | `jsonb[${number}]` | `binary(${number})[${number}]` | `varchar(${number})[${number}]` | `char(${number})[${number}]` | `datetime(${number})[${number}]` | `time(${number})[${number}]` | `timetz(${number})[${number}]` | `timestamp(${number})[${number}]` | `timestamptz(${number})[${number}]` | `varbinary(${number})[${number}]` | `decimal(${number},${number})[${number}]` | `decimal(${number}, ${number})[${number}]` | `numeric(${number},${number})[${number}]` | `numeric(${number}, ${number})[${number}]`>]>>;
|
|
148
|
+
default: z.ZodOptional<z.ZodString>;
|
|
149
|
+
ops: z.ZodOptional<z.ZodArray<z.ZodLiteral<"drop_default" | "set_required" | "drop_required">>>;
|
|
150
|
+
}, z.core.$strict>>>>;
|
|
151
|
+
add_constraints: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
152
|
+
type: z.ZodLiteral<"primary_key">;
|
|
153
|
+
on: z.ZodArray<z.ZodString>;
|
|
154
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
155
|
+
type: z.ZodLiteral<"foreign_key">;
|
|
156
|
+
on: z.ZodArray<z.ZodString>;
|
|
157
|
+
target: z.ZodString;
|
|
158
|
+
references: z.ZodArray<z.ZodString>;
|
|
159
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
160
|
+
type: z.ZodLiteral<"unique">;
|
|
161
|
+
on: z.ZodArray<z.ZodString>;
|
|
162
|
+
nulls_not_distinct: z.ZodOptional<z.ZodBoolean>;
|
|
163
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
164
|
+
type: z.ZodLiteral<"check">;
|
|
165
|
+
check: z.ZodString;
|
|
166
|
+
}, z.core.$strict>], "type">>>>;
|
|
167
|
+
drop_constraints: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
168
|
+
}, z.core.$strict>>>>;
|
|
169
|
+
add_indexes: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
170
|
+
on: z.ZodString;
|
|
171
|
+
columns: z.ZodArray<z.ZodString>;
|
|
172
|
+
}, z.core.$strict>>>>;
|
|
173
|
+
drop_indexes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
174
|
+
}, z.core.$strict>], "delta">>;
|
|
175
|
+
wipe: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
176
|
+
latest: z.ZodOptional<z.ZodInt32>;
|
|
177
|
+
acl_tables: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>>;
|
|
178
|
+
}, z.core.$strip>;
|
|
179
|
+
export interface SchemaFile extends z.infer<typeof SchemaFile> {
|
|
180
|
+
}
|
|
181
|
+
export declare function getFiles(): Generator<[string, SchemaFile]>;
|
|
182
|
+
export type ApplyColumnDelta<C extends z.input<typeof Column>, D extends z.input<typeof delta.Column>> = Omit<C, 'type' | 'default' | 'required'> & {
|
|
183
|
+
type: D extends {
|
|
184
|
+
type: infer T;
|
|
185
|
+
} ? T : C['type'];
|
|
186
|
+
default: D extends {
|
|
187
|
+
ops: readonly any[];
|
|
188
|
+
} ? 'drop_default' extends D['ops'][number] ? undefined : D extends {
|
|
189
|
+
default: infer Def;
|
|
190
|
+
} ? Def : C['default'] : D extends {
|
|
191
|
+
default: infer Def;
|
|
192
|
+
} ? Def : C['default'];
|
|
193
|
+
required: D extends {
|
|
194
|
+
ops: readonly any[];
|
|
195
|
+
} ? 'set_required' extends D['ops'][number] ? true : 'drop_required' extends D['ops'][number] ? false : C['required'] : C['required'];
|
|
196
|
+
};
|
|
197
|
+
export type ApplyTableDelta<T extends z.input<typeof Table>, D extends z.input<typeof delta.Table>> = {
|
|
198
|
+
columns: {
|
|
199
|
+
[K in keyof T['columns'] as K extends (D extends {
|
|
200
|
+
drop_columns: any[];
|
|
201
|
+
} ? D['drop_columns'][number] : never) ? never : K]: K extends keyof (D extends {
|
|
202
|
+
alter_columns: any;
|
|
203
|
+
} ? D['alter_columns'] : {}) ? ApplyColumnDelta<T['columns'][K], (D['alter_columns'] & {})[K & keyof D['alter_columns']]> : T['columns'][K];
|
|
204
|
+
} & (D extends {
|
|
205
|
+
add_columns: infer A;
|
|
206
|
+
} ? A : {});
|
|
207
|
+
constraints: {
|
|
208
|
+
[K in keyof T['constraints'] as K extends (D extends {
|
|
209
|
+
drop_constraints: any[];
|
|
210
|
+
} ? D['drop_constraints'][number] : never) ? never : K]: T['constraints'][K];
|
|
211
|
+
} & (D extends {
|
|
212
|
+
add_constraints: infer A;
|
|
213
|
+
} ? A : {});
|
|
214
|
+
};
|
|
215
|
+
export type ApplySchemaDelta<S extends z.input<typeof SchemaDecl>, D extends z.input<typeof delta.Version>> = {
|
|
216
|
+
tables: {
|
|
217
|
+
[K in keyof S['tables'] as K extends (D extends {
|
|
218
|
+
drop_tables: any[];
|
|
219
|
+
} ? D['drop_tables'][number] : never) ? never : K]: K extends keyof (D extends {
|
|
220
|
+
alter_tables: any;
|
|
221
|
+
} ? D['alter_tables'] : {}) ? ApplyTableDelta<S['tables'][K], (D['alter_tables'] & {})[K & keyof D['alter_tables']]> : S['tables'][K];
|
|
222
|
+
} & (D extends {
|
|
223
|
+
add_tables: infer A;
|
|
224
|
+
} ? A : {});
|
|
225
|
+
indexes: {
|
|
226
|
+
[K in keyof S['indexes'] as K extends (D extends {
|
|
227
|
+
drop_indexes: any[];
|
|
228
|
+
} ? D['drop_indexes'][number] : never) ? never : K]: S['indexes'][K];
|
|
229
|
+
};
|
|
230
|
+
};
|
|
231
|
+
type ResolveVersions<V extends readonly any[], Current extends z.input<typeof SchemaDecl> = {
|
|
232
|
+
tables: {};
|
|
233
|
+
indexes: {};
|
|
234
|
+
}> = V extends readonly [
|
|
235
|
+
infer Head extends z.input<typeof delta.Version> | (z.input<typeof SchemaDecl> & {
|
|
236
|
+
delta: false;
|
|
237
|
+
}),
|
|
238
|
+
...infer Tail extends (z.input<typeof delta.Version> | (z.input<typeof SchemaDecl> & {
|
|
239
|
+
delta: false;
|
|
240
|
+
}))[]
|
|
241
|
+
] ? Head extends z.input<typeof delta.Version> ? ResolveVersions<Tail, ApplySchemaDelta<Current, Head>> : Head extends z.input<typeof SchemaDecl> ? ResolveVersions<Tail, Head> : never : Current;
|
|
242
|
+
export type FullSchema<S extends z.input<typeof SchemaFile>> = ResolveVersions<S['versions']>;
|
|
243
|
+
type _DBFromSchema<TBs extends Record<string, z.input<typeof Table>>> = {
|
|
244
|
+
[K in keyof TBs]: Expand<TableValue<TBs[K]>>;
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Convert an entire schema definition file info the Kysely database schema type
|
|
248
|
+
*/
|
|
249
|
+
export type FromFile<S extends ReadonlyRecursive<z.input<typeof SchemaFile>>> = _DBFromSchema<FullSchema<MutableRecursive<S>>['tables']>;
|
|
250
|
+
/**@deprecated use {@link FromFile} */
|
|
251
|
+
export type DatabaseFromSchemaFile<S extends ReadonlyRecursive<z.input<typeof SchemaFile>>> = FromFile<S>;
|
|
252
|
+
/** @internal @hidden */
|
|
253
|
+
export type Raw = FromFile<typeof raw>;
|
|
254
|
+
/**
|
|
255
|
+
* Get the active schema
|
|
256
|
+
*/
|
|
257
|
+
export declare function getFull(opt?: {
|
|
258
|
+
exclude?: string[];
|
|
259
|
+
}): SchemaDecl & {
|
|
260
|
+
versions: Record<string, number>;
|
|
261
|
+
};
|
|
262
|
+
export declare function toSQL(schema: SchemaDecl): Generator<string>;
|
|
263
|
+
export declare function toGraph(schema: SchemaDecl): Generator<string>;
|
|
264
|
+
export declare const toIntrospected: {
|
|
265
|
+
boolean: string;
|
|
266
|
+
integer: string;
|
|
267
|
+
'text[]': string;
|
|
268
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as io from '@axium/core/node/io';
|
|
2
|
+
import { plugins } from '@axium/core/plugins';
|
|
3
|
+
import { sql } from 'kysely';
|
|
4
|
+
import * as z from 'zod';
|
|
5
|
+
import raw from './schema.json' with { type: 'json' };
|
|
6
|
+
import { database } from './connection.js';
|
|
7
|
+
import { buildColumn, Index, Table } from './data.js';
|
|
8
|
+
import * as delta from './delta.js';
|
|
9
|
+
export * from './data.js';
|
|
10
|
+
export const SchemaDecl = z.strictObject({
|
|
11
|
+
tables: z.record(z.string(), Table),
|
|
12
|
+
indexes: z.record(z.string(), Index),
|
|
13
|
+
});
|
|
14
|
+
export const SchemaFile = z.object({
|
|
15
|
+
format: z.literal(1),
|
|
16
|
+
versions: z.discriminatedUnion('delta', [SchemaDecl.extend({ delta: z.literal(false) }), delta.Version]).array(),
|
|
17
|
+
/** List of tables to wipe */
|
|
18
|
+
wipe: z.string().array().optional().default([]),
|
|
19
|
+
/** Set the latest version, defaults to the last one */
|
|
20
|
+
latest: z.int32().nonnegative().optional(),
|
|
21
|
+
/** Maps tables to their ACL tables, e.g. `"storage": "acl.storage"` */
|
|
22
|
+
acl_tables: z.record(z.string(), z.string()).optional().default({}),
|
|
23
|
+
});
|
|
24
|
+
const { data, error } = SchemaFile.safeParse(raw);
|
|
25
|
+
if (error)
|
|
26
|
+
io.error('Invalid base database schema:\n' + z.prettifyError(error));
|
|
27
|
+
const schema = data;
|
|
28
|
+
export function* getFiles() {
|
|
29
|
+
yield ['@axium/server', schema];
|
|
30
|
+
for (const [name, plugin] of plugins) {
|
|
31
|
+
if (!plugin._db)
|
|
32
|
+
continue;
|
|
33
|
+
try {
|
|
34
|
+
yield [name, SchemaFile.parse(plugin._db)];
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
throw `Invalid database configuration for plugin "${name}":\n${io.errorText(e)}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the active schema
|
|
43
|
+
*/
|
|
44
|
+
export function getFull(opt = {}) {
|
|
45
|
+
const fullSchema = { tables: {}, indexes: {}, versions: {} };
|
|
46
|
+
for (const [pluginName, file] of getFiles()) {
|
|
47
|
+
if (opt.exclude?.includes(pluginName))
|
|
48
|
+
continue;
|
|
49
|
+
file.latest ??= file.versions.length - 1;
|
|
50
|
+
let currentSchema = { tables: {}, indexes: {} };
|
|
51
|
+
fullSchema.versions[pluginName] = file.latest;
|
|
52
|
+
for (const [version, schema] of file.versions.entries()) {
|
|
53
|
+
if (!schema.delta)
|
|
54
|
+
currentSchema = schema;
|
|
55
|
+
else {
|
|
56
|
+
try {
|
|
57
|
+
delta.applyToSchema(currentSchema, schema);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
throw `Failed to apply version ${version - 1}->${version} delta to ${pluginName}: ${io.errorText(e)}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (version === file.latest)
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
for (const name of Object.keys(currentSchema.tables)) {
|
|
67
|
+
if (name in fullSchema.tables)
|
|
68
|
+
throw 'Duplicate table name in database schema: ' + name;
|
|
69
|
+
fullSchema.tables[name] = currentSchema.tables[name];
|
|
70
|
+
}
|
|
71
|
+
for (const index of Object.keys(currentSchema.indexes)) {
|
|
72
|
+
if (fullSchema.indexes[index])
|
|
73
|
+
throw 'Duplicate index in database schema: ' + index;
|
|
74
|
+
fullSchema.indexes[index] = currentSchema.indexes[index];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return fullSchema;
|
|
78
|
+
}
|
|
79
|
+
export function* toSQL(schema) {
|
|
80
|
+
for (const [tableName, table] of Object.entries(schema.tables)) {
|
|
81
|
+
let query = database.schema.createTable(tableName);
|
|
82
|
+
const columns = Object.entries(table.columns);
|
|
83
|
+
const pkColumns = columns.filter(([, column]) => column.primary).map(([name, column]) => ({ name, ...column }));
|
|
84
|
+
const needsSpecialConstraint = pkColumns.length > 1 || pkColumns.some(col => !col.required);
|
|
85
|
+
for (const [colName, column] of columns) {
|
|
86
|
+
query = query.addColumn(colName, sql.raw(column.type), buildColumn(column, !needsSpecialConstraint));
|
|
87
|
+
}
|
|
88
|
+
if (needsSpecialConstraint) {
|
|
89
|
+
query = query.addPrimaryKeyConstraint('PK_' + tableName.replaceAll('.', '_'), pkColumns.map(col => col.name));
|
|
90
|
+
}
|
|
91
|
+
yield query.compile().sql.replace('(', '(\n\t').replaceAll(', ', ',\n\t').replace(/\)$/, '\n);\n');
|
|
92
|
+
}
|
|
93
|
+
for (const [indexName, index] of Object.entries(schema.indexes)) {
|
|
94
|
+
const query = database.schema.createIndex(indexName).on(index.on).columns(index.columns).compile().sql;
|
|
95
|
+
yield query + ';\n';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export function* toGraph(schema) {
|
|
99
|
+
const esc = (s) => s.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
|
|
100
|
+
const nodeId = (table) => table.replaceAll('.', '__');
|
|
101
|
+
const edges = [];
|
|
102
|
+
yield `digraph schema {
|
|
103
|
+
graph [
|
|
104
|
+
bgcolor="#111111",
|
|
105
|
+
overlap=false,
|
|
106
|
+
pad=0.5,
|
|
107
|
+
concentrate=true,
|
|
108
|
+
nodesep=1.0,
|
|
109
|
+
rankdir=LR,
|
|
110
|
+
size="16,9!",
|
|
111
|
+
ratio="fill"
|
|
112
|
+
];
|
|
113
|
+
node [color="#c6c5fe",
|
|
114
|
+
fontcolor="#c6c5fe",
|
|
115
|
+
fontname=monospace,
|
|
116
|
+
fontsize="14px",
|
|
117
|
+
height=0,
|
|
118
|
+
label="\\N",
|
|
119
|
+
shape=plain,
|
|
120
|
+
style=rounded
|
|
121
|
+
];
|
|
122
|
+
edge [color="#757575"];
|
|
123
|
+
`;
|
|
124
|
+
for (const [tableName, table] of Object.entries(schema.tables)) {
|
|
125
|
+
const id = nodeId(tableName);
|
|
126
|
+
for (const constraint of Object.values(table.constraints)) {
|
|
127
|
+
if (constraint.type !== 'foreign_key')
|
|
128
|
+
continue;
|
|
129
|
+
for (let i = 0; i < constraint.on.length; i++) {
|
|
130
|
+
edges.push({
|
|
131
|
+
fromTable: tableName,
|
|
132
|
+
fromCol: constraint.on[i],
|
|
133
|
+
toTable: constraint.target,
|
|
134
|
+
toCol: constraint.references[i],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
yield `\t${id} [label=<\n`;
|
|
139
|
+
yield '\t\t<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="4">\n';
|
|
140
|
+
yield `\t\t\t<TR><TD COLSPAN="3" BGCOLOR="#44C2C4"><B>${esc(tableName)}</B></TD></TR>\n`;
|
|
141
|
+
for (const [colName, column] of Object.entries(table.columns)) {
|
|
142
|
+
const nullable = !column.required ? '?' : '';
|
|
143
|
+
const typeText = esc(column.type) + nullable;
|
|
144
|
+
let label = `${esc(colName)}: ${column.references ? `<I>${typeText}</I>` : typeText}`;
|
|
145
|
+
if (column.primary)
|
|
146
|
+
label = `<B>${label}</B>`;
|
|
147
|
+
if (column.references) {
|
|
148
|
+
const [toTable, toCol] = column.references.split('.');
|
|
149
|
+
edges.push({ fromTable: tableName, fromCol: colName, toTable, toCol });
|
|
150
|
+
}
|
|
151
|
+
yield `\t\t\t<TR><TD PORT="${esc(colName)}_l" WIDTH="2"></TD><TD ALIGN="LEFT">${label}</TD><TD PORT="${esc(colName)}_r" WIDTH="2"></TD></TR>\n`;
|
|
152
|
+
}
|
|
153
|
+
yield '\t\t</TABLE>\n\t>];\n\n';
|
|
154
|
+
}
|
|
155
|
+
for (const { fromTable, fromCol, toTable, toCol } of edges) {
|
|
156
|
+
if (fromTable != toTable) {
|
|
157
|
+
yield `\t${nodeId(fromTable)}:${fromCol}_r -> ${nodeId(toTable)}:${toCol}_l;\n`;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const id = nodeId(fromTable);
|
|
161
|
+
yield `\t${id}:${fromCol}_l:w -> ${id}:${toCol}_l:w [constraint=false];\n`;
|
|
162
|
+
}
|
|
163
|
+
yield '}\n';
|
|
164
|
+
}
|
|
165
|
+
export const toIntrospected = {
|
|
166
|
+
boolean: 'bool',
|
|
167
|
+
integer: 'int4',
|
|
168
|
+
'text[]': '_text',
|
|
169
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
3
|
-
"format":
|
|
2
|
+
"$schema": "../../schemas/db.json",
|
|
3
|
+
"format": 1,
|
|
4
4
|
"versions": [
|
|
5
5
|
{
|
|
6
6
|
"delta": false,
|
|
@@ -64,7 +64,9 @@
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
|
-
"indexes":
|
|
67
|
+
"indexes": {
|
|
68
|
+
"passkeys_userId": { "on": "passkeys", "columns": ["userId"] }
|
|
69
|
+
}
|
|
68
70
|
},
|
|
69
71
|
{
|
|
70
72
|
"delta": true,
|
package/dist/main.js
CHANGED
|
@@ -85,15 +85,15 @@ async function dbInitTables() {
|
|
|
85
85
|
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
86
86
|
try {
|
|
87
87
|
const info = db.getUpgradeInfo();
|
|
88
|
-
const schema = db.
|
|
89
|
-
const delta = db.
|
|
90
|
-
if (db.
|
|
88
|
+
const schema = db.schema.getFull({ exclude: Object.keys(info.current) });
|
|
89
|
+
const delta = db.delta.compute({ tables: {}, indexes: {} }, schema);
|
|
90
|
+
if (db.delta.isEmpty(delta))
|
|
91
91
|
return;
|
|
92
|
-
for (const text of db.
|
|
92
|
+
for (const text of db.delta.display(delta))
|
|
93
93
|
console.log(text);
|
|
94
94
|
await rlConfirm();
|
|
95
95
|
const _ = __addDisposableResource(env_2, db.connect(), true);
|
|
96
|
-
await db.
|
|
96
|
+
await db.delta.apply(delta);
|
|
97
97
|
Object.assign(info.current, schema.versions);
|
|
98
98
|
db.setUpgradeInfo(info);
|
|
99
99
|
}
|
|
@@ -248,7 +248,7 @@ try {
|
|
|
248
248
|
.addOption(opts.force)
|
|
249
249
|
.action(async (opt) => {
|
|
250
250
|
const tables = new Map();
|
|
251
|
-
for (const [plugin, schema] of db.
|
|
251
|
+
for (const [plugin, schema] of db.schema.getFiles()) {
|
|
252
252
|
for (const table of schema.wipe) {
|
|
253
253
|
const maybePlugin = tables.get(table);
|
|
254
254
|
tables.set(table, maybePlugin ? `${maybePlugin}, ${plugin}` : plugin);
|
|
@@ -309,7 +309,7 @@ try {
|
|
|
309
309
|
io.start('Resolving database schemas');
|
|
310
310
|
let schema;
|
|
311
311
|
try {
|
|
312
|
-
schema = db.
|
|
312
|
+
schema = db.schema.getFull();
|
|
313
313
|
io.done();
|
|
314
314
|
}
|
|
315
315
|
catch (e) {
|
|
@@ -350,12 +350,12 @@ try {
|
|
|
350
350
|
.description('Generate a new password for the database user and update the config')
|
|
351
351
|
.action(db.rotatePassword);
|
|
352
352
|
axiumDB
|
|
353
|
-
.command('schema')
|
|
353
|
+
.command('json-schema')
|
|
354
354
|
.description('Get the JSON schema for the database configuration file')
|
|
355
355
|
.option('-j, --json', 'values are JSON encoded')
|
|
356
356
|
.action(opt => {
|
|
357
357
|
try {
|
|
358
|
-
const schema = z.toJSONSchema(db.SchemaFile, { io: 'input' });
|
|
358
|
+
const schema = z.toJSONSchema(db.schema.SchemaFile, { io: 'input' });
|
|
359
359
|
console.log(opt.json ? JSON.stringify(schema, null, 4) : schema);
|
|
360
360
|
}
|
|
361
361
|
catch (e) {
|
|
@@ -373,7 +373,7 @@ try {
|
|
|
373
373
|
const info = db.getUpgradeInfo();
|
|
374
374
|
let empty = true;
|
|
375
375
|
const from = {}, to = {};
|
|
376
|
-
for (const [name, schema] of db.
|
|
376
|
+
for (const [name, schema] of db.schema.getFiles()) {
|
|
377
377
|
if (!(name in info.current))
|
|
378
378
|
io.exit('Plugin is not initialized: ' + name);
|
|
379
379
|
const currentVersion = info.current[name];
|
|
@@ -390,15 +390,15 @@ try {
|
|
|
390
390
|
for (const [i, v] of versions.toReversed().entries()) {
|
|
391
391
|
if (v.delta || v == v0)
|
|
392
392
|
continue;
|
|
393
|
-
versions = [db.
|
|
393
|
+
versions = [db.delta.compute(v0, v), ...versions.slice(-i)];
|
|
394
394
|
break;
|
|
395
395
|
}
|
|
396
|
-
const delta = db.
|
|
396
|
+
const delta = db.delta.collapse(versions);
|
|
397
397
|
deltas.push(delta);
|
|
398
398
|
console.log('Upgrading', name, styleText('dim', currentVersion.toString() + '->') + styleText('blueBright', target.toString()) + ':');
|
|
399
|
-
if (!db.
|
|
399
|
+
if (!db.delta.isEmpty(delta))
|
|
400
400
|
empty = false;
|
|
401
|
-
for (const text of db.
|
|
401
|
+
for (const text of db.delta.display(delta))
|
|
402
402
|
console.log(text);
|
|
403
403
|
}
|
|
404
404
|
if (empty) {
|
|
@@ -412,7 +412,7 @@ try {
|
|
|
412
412
|
io.start('Computing delta');
|
|
413
413
|
let delta;
|
|
414
414
|
try {
|
|
415
|
-
delta = db.
|
|
415
|
+
delta = db.delta.collapse(deltas);
|
|
416
416
|
io.done();
|
|
417
417
|
}
|
|
418
418
|
catch (e) {
|
|
@@ -420,14 +420,14 @@ try {
|
|
|
420
420
|
}
|
|
421
421
|
io.start('Validating delta');
|
|
422
422
|
try {
|
|
423
|
-
db.
|
|
423
|
+
db.delta.validate(delta);
|
|
424
424
|
io.done();
|
|
425
425
|
}
|
|
426
426
|
catch (e) {
|
|
427
427
|
io.exit(e);
|
|
428
428
|
}
|
|
429
429
|
console.log('Applying delta.');
|
|
430
|
-
await db.
|
|
430
|
+
await db.delta.apply(delta, opt.abort).catch(io.exit);
|
|
431
431
|
info.upgrades.push({ timestamp: new Date(), from, to });
|
|
432
432
|
db.setUpgradeInfo(info);
|
|
433
433
|
});
|
|
@@ -457,7 +457,7 @@ try {
|
|
|
457
457
|
const entries = [
|
|
458
458
|
{ name: 'Name', current: 'Current', latest: 'Latest', available: 'Available' },
|
|
459
459
|
];
|
|
460
|
-
for (const [name, file] of db.
|
|
460
|
+
for (const [name, file] of db.schema.getFiles()) {
|
|
461
461
|
const available = (file.versions.length - 1).toString();
|
|
462
462
|
const latest = (file.latest ?? available).toString();
|
|
463
463
|
const current = currentVersions[name]?.toString();
|
|
@@ -471,6 +471,20 @@ try {
|
|
|
471
471
|
console.log(...['name', 'current', 'latest', 'available'].map(key => styleText(i === 0 ? ['whiteBright', 'underline'] : entry[key] === undefined ? 'reset' : [], entry[key].padStart(lengths[key]))));
|
|
472
472
|
}
|
|
473
473
|
});
|
|
474
|
+
axiumDB
|
|
475
|
+
.command('export-schema')
|
|
476
|
+
.description('Export the DB schema')
|
|
477
|
+
.addOption(new Option('-f, --format <format>', 'Output format').choices(['sql', 'graph']).default('sql'))
|
|
478
|
+
.option('-o, --output <file>', 'Output file path')
|
|
479
|
+
.action(opt => {
|
|
480
|
+
const schema = db.schema.getFull();
|
|
481
|
+
const it = opt.format == 'sql' ? db.schema.toSQL(schema) : db.schema.toGraph(schema);
|
|
482
|
+
const out = opt.output ? createWriteStream(opt.output) : process.stdout;
|
|
483
|
+
for (const data of it)
|
|
484
|
+
out.write(data);
|
|
485
|
+
if (opt.output)
|
|
486
|
+
out.close();
|
|
487
|
+
});
|
|
474
488
|
axiumConfig = program
|
|
475
489
|
.command('config')
|
|
476
490
|
.description('Manage the configuration')
|
|
@@ -594,16 +608,16 @@ try {
|
|
|
594
608
|
const exclude = Object.keys(info.current);
|
|
595
609
|
if (exclude.includes(plugin.name))
|
|
596
610
|
io.exit('Plugin is already initialized (database)');
|
|
597
|
-
const schema = db.
|
|
598
|
-
const delta = db.
|
|
599
|
-
if (db.
|
|
611
|
+
const schema = db.schema.getFull({ exclude });
|
|
612
|
+
const delta = db.delta.compute({ tables: {}, indexes: {} }, schema);
|
|
613
|
+
if (db.delta.isEmpty(delta)) {
|
|
600
614
|
io.info('Plugin does not define any database schema.');
|
|
601
615
|
return;
|
|
602
616
|
}
|
|
603
|
-
for (const text of db.
|
|
617
|
+
for (const text of db.delta.display(delta))
|
|
604
618
|
console.log(text);
|
|
605
619
|
await rlConfirm();
|
|
606
|
-
await db.
|
|
620
|
+
await db.delta.apply(delta);
|
|
607
621
|
Object.assign(info.current, schema.versions);
|
|
608
622
|
db.setUpgradeInfo(info);
|
|
609
623
|
}
|