@axium/server 0.39.4 → 0.39.6

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.
@@ -8,6 +8,7 @@ export declare const Column: z.ZodObject<{
8
8
  }, z.core.$strict>;
9
9
  export interface Column extends z.infer<typeof Column> {
10
10
  }
11
+ export declare function applyToColumn(column: data.Column, delta: Column): void;
11
12
  export declare const Table: z.ZodObject<{
12
13
  add_columns: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
13
14
  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}]`>]>;
package/dist/db/delta.js CHANGED
@@ -9,6 +9,25 @@ export const Column = z.strictObject({
9
9
  default: z.string().optional(),
10
10
  ops: z.literal(['drop_default', 'set_required', 'drop_required']).array().optional(),
11
11
  });
12
+ export function applyToColumn(column, delta) {
13
+ if (delta.type)
14
+ column.type = delta.type;
15
+ if (delta.default)
16
+ column.default = delta.default;
17
+ for (const op of delta.ops || []) {
18
+ switch (op) {
19
+ case 'drop_default':
20
+ delete column.default;
21
+ break;
22
+ case 'set_required':
23
+ column.required = true;
24
+ break;
25
+ case 'drop_required':
26
+ column.required = false;
27
+ break;
28
+ }
29
+ }
30
+ }
12
31
  export const Table = z.strictObject({
13
32
  add_columns: z.record(z.string(), data.Column).optional().default({}),
14
33
  drop_columns: z.string().array().optional().default([]),
@@ -32,23 +51,7 @@ export function applyToTable(table, delta) {
32
51
  const column = table.columns[name];
33
52
  if (!column)
34
53
  throw `can't modify column ${name} because it does not exist`;
35
- if (columnDelta.type)
36
- column.type = columnDelta.type;
37
- if (columnDelta.default)
38
- column.default = columnDelta.default;
39
- for (const op of columnDelta.ops || []) {
40
- switch (op) {
41
- case 'drop_default':
42
- delete column.default;
43
- break;
44
- case 'set_required':
45
- column.required = true;
46
- break;
47
- case 'drop_required':
48
- column.required = false;
49
- break;
50
- }
51
- }
54
+ applyToColumn(column, columnDelta);
52
55
  }
53
56
  for (const name of delta.drop_constraints) {
54
57
  if (table.constraints[name])
@@ -192,21 +195,62 @@ export function collapse(deltas) {
192
195
  for (const [name, table] of Object.entries(delta.alter_tables)) {
193
196
  if (name in add_tables) {
194
197
  applyToTable(add_tables[name], table);
198
+ continue;
195
199
  }
196
- else if (name in alter_tables) {
197
- const existing = alter_tables[name];
198
- for (const [colName, column] of Object.entries(table.add_columns)) {
199
- existing.add_columns[colName] = column;
200
+ const existing = alter_tables[name];
201
+ if (!existing) {
202
+ alter_tables[name] = table;
203
+ continue;
204
+ }
205
+ for (const [colName, column] of Object.entries(table.add_columns)) {
206
+ existing.add_columns[colName] = column;
207
+ }
208
+ for (const colName of table.drop_columns) {
209
+ if (colName in existing.add_columns)
210
+ delete existing.add_columns[colName];
211
+ else
212
+ existing.drop_columns.push(colName);
213
+ }
214
+ for (const [colName, delta] of Object.entries(table.alter_columns)) {
215
+ if (colName in existing.add_columns) {
216
+ applyToColumn(existing.add_columns[colName], delta);
217
+ continue;
200
218
  }
201
- for (const colName of table.drop_columns) {
202
- if (colName in existing.add_columns)
203
- delete existing.add_columns[colName];
204
- else
205
- existing.drop_columns.push(colName);
219
+ const existingCol = existing.alter_columns[colName];
220
+ if (!existingCol) {
221
+ existing.alter_columns[colName] = delta;
222
+ continue;
223
+ }
224
+ if ('default' in delta)
225
+ existingCol.default = delta.default;
226
+ if ('type' in delta)
227
+ existingCol.type = delta.type;
228
+ existingCol.ops ||= [];
229
+ const { ops } = existingCol;
230
+ for (const op of delta.ops || []) {
231
+ if (ops.includes(op)) {
232
+ io.debug(`Ignoring duplicate operation whilst resolving delta for ${name}.${colName}`);
233
+ continue;
234
+ }
235
+ switch (op) {
236
+ case 'drop_default':
237
+ if ('default' in existingCol)
238
+ delete existingCol.default;
239
+ else
240
+ ops.push(op);
241
+ break;
242
+ case 'set_required':
243
+ case 'drop_required': {
244
+ const i = ops.indexOf(op == 'set_required' ? 'drop_required' : 'set_required');
245
+ if (i == -1)
246
+ ops.push(op);
247
+ else
248
+ ops.splice(i, 1);
249
+ break;
250
+ }
251
+ }
206
252
  }
207
253
  }
208
- else
209
- alter_tables[name] = table;
210
254
  }
211
255
  for (const table of delta.drop_tables) {
212
256
  if (table in add_tables)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axium/server",
3
- "version": "0.39.4",
3
+ "version": "0.39.6",
4
4
  "author": "James Prevett <axium@jamespre.dev>",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -1,4 +1,4 @@
1
- <div class="main">
1
+ <div id="default">
2
2
  <h1>It works!</h1>
3
3
  <p>This is the default Axium page. You'll want to change it.</p>
4
4
  <h3>Helpful links</h3>
@@ -9,3 +9,14 @@
9
9
  <li><a href="/account">Account</a></li>
10
10
  </ul>
11
11
  </div>
12
+
13
+ <style>
14
+ #default {
15
+ padding: 2em;
16
+ border-radius: 1em;
17
+ background-color: var(--bg-menu);
18
+ display: flex;
19
+ flex-direction: column;
20
+ gap: 1em;
21
+ }
22
+ </style>
@@ -38,7 +38,7 @@
38
38
  </div>
39
39
  <p class="greeting">{text('page.account.greeting', { name: user.name })}</p>
40
40
 
41
- <div id="info" class="section main">
41
+ <div id="info" class="section">
42
42
  <h3>{text('page.account.personal_info')}</h3>
43
43
  <div class="item info">
44
44
  <p class="subtle">{text('generic.username')}</p>
@@ -96,7 +96,7 @@
96
96
  </div>
97
97
  </div>
98
98
 
99
- <div id="passkeys" class="section main">
99
+ <div id="passkeys" class="section">
100
100
  <h3>{text('page.account.passkeys.title')}</h3>
101
101
  {#each passkeys as passkey}
102
102
  <div class="item passkey">
@@ -163,12 +163,12 @@
163
163
  </button>
164
164
  </div>
165
165
 
166
- <div id="sessions" class="section main">
166
+ <div id="sessions" class="section">
167
167
  <h3>{text('page.account.sessions')}</h3>
168
168
  <SessionList {sessions} {currentSession} {user} redirectAfterLogoutAll />
169
169
  </div>
170
170
 
171
- <div id="preferences" class="section main">
171
+ <div id="preferences" class="section">
172
172
  <h3>{text('page.account.preferences')}</h3>
173
173
  <ZodForm
174
174
  bind:rootValue={user.preferences}
@@ -36,7 +36,7 @@
36
36
 
37
37
  <h2>{text('page.admin.users.manage_heading')}</h2>
38
38
 
39
- <div id="info" class="section main">
39
+ <div id="info" class="section">
40
40
  <div class="item info">
41
41
  <p>{text('page.admin.users.uuid')}</p>
42
42
  <p>{user.id}</p>
@@ -126,12 +126,12 @@
126
126
  </FormDialog>
127
127
  </div>
128
128
 
129
- <div id="sessions" class="section main">
129
+ <div id="sessions" class="section">
130
130
  <h3>{text('generic.sessions')}</h3>
131
131
  <SessionList {sessions} {user} />
132
132
  </div>
133
133
 
134
- <div id="preferences" class="section main">
134
+ <div id="preferences" class="section">
135
135
  <h3>{text('generic.preferences')}</h3>
136
136
  <ZodForm
137
137
  bind:rootValue={user.preferences}