@crombolo/data 0.0.0-stage → 0.10.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/LICENSE +21 -0
- package/NOTICE +69 -0
- package/package.json +31 -4
- package/src/bundle-tables/builder.ts +264 -0
- package/src/bundle-tables/capability.ts +377 -0
- package/src/bundle-tables/chain.ts +105 -0
- package/src/bundle-tables/ddl.ts +124 -0
- package/src/bundle-tables/guard.ts +116 -0
- package/src/bundle-tables/index.ts +7 -0
- package/src/bundle-tables/names.ts +58 -0
- package/src/bundle-tables/schema.ts +485 -0
- package/src/change-report.ts +166 -0
- package/src/cluster.ts +108 -0
- package/src/database.ts +121 -0
- package/src/dialect.ts +136 -0
- package/src/index.ts +63 -0
- package/src/locks.ts +103 -0
- package/src/maintenance.ts +51 -0
- package/src/migrations.ts +547 -0
- package/src/node-ref.ts +107 -0
- package/src/pending.ts +25 -0
- package/src/repositories/bundles.ts +223 -0
- package/src/repositories/content-types.ts +831 -0
- package/src/repositories/data-types.ts +222 -0
- package/src/repositories/dictionary.ts +259 -0
- package/src/repositories/documents.ts +2389 -0
- package/src/repositories/domains.ts +108 -0
- package/src/repositories/folders.ts +120 -0
- package/src/repositories/form-entries.ts +314 -0
- package/src/repositories/form-workflows.ts +213 -0
- package/src/repositories/languages.ts +108 -0
- package/src/repositories/log-searches.ts +33 -0
- package/src/repositories/members.ts +427 -0
- package/src/repositories/nodes.ts +361 -0
- package/src/repositories/notifications.ts +54 -0
- package/src/repositories/public-access.ts +187 -0
- package/src/repositories/redirects.ts +274 -0
- package/src/repositories/references.ts +162 -0
- package/src/repositories/tags.ts +93 -0
- package/src/repositories/templates.ts +114 -0
- package/src/repositories/transfer-runs.ts +208 -0
- package/src/repositories/user-data.ts +90 -0
- package/src/repositories/users.ts +898 -0
- package/src/schema/assistant.ts +74 -0
- package/src/schema/built-in-content-types.ts +106 -0
- package/src/schema/built-in-media-types.ts +335 -0
- package/src/schema/built-in-member-types.ts +61 -0
- package/src/schema/bundle-components.ts +49 -0
- package/src/schema/bundle-package.ts +27 -0
- package/src/schema/bundles-rename.ts +32 -0
- package/src/schema/change-report.ts +46 -0
- package/src/schema/client-id-prefix.ts +43 -0
- package/src/schema/content-editing.ts +50 -0
- package/src/schema/content-seed.ts +586 -0
- package/src/schema/content.ts +263 -0
- package/src/schema/created-packages.ts +56 -0
- package/src/schema/elements.ts +62 -0
- package/src/schema/form-permission-prefix.ts +50 -0
- package/src/schema/form-permissions.ts +26 -0
- package/src/schema/form-workflows.ts +54 -0
- package/src/schema/forms.ts +63 -0
- package/src/schema/group-permissions.ts +20 -0
- package/src/schema/identity.ts +176 -0
- package/src/schema/log-viewer.ts +68 -0
- package/src/schema/member-property-type.ts +30 -0
- package/src/schema/members.ts +97 -0
- package/src/schema/plan.ts +77 -0
- package/src/schema/public-access.ts +56 -0
- package/src/schema/recycle-bin.ts +21 -0
- package/src/schema/redirects.ts +57 -0
- package/src/schema/rich-text-ui.ts +34 -0
- package/src/schema/seed.ts +298 -0
- package/src/schema/server-role.ts +21 -0
- package/src/schema/since-version.ts +26 -0
- package/src/schema/transfer-run-package.ts +27 -0
- package/src/schema/transfer-runs.ts +71 -0
- package/src/schema/upgrade-report.ts +43 -0
- package/src/schema/users-localisation.ts +85 -0
- package/src/schema/values.ts +108 -0
- package/src/schema-ops.ts +35 -0
- package/src/schema-state.ts +196 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kineco
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
crombolo
|
|
2
|
+
Copyright (c) 2026 Kineco
|
|
3
|
+
|
|
4
|
+
This product includes third-party software. crombolo is an independent project.
|
|
5
|
+
It is not affiliated with, endorsed by, or sponsored by Umbraco A/S, which owns
|
|
6
|
+
the Umbraco trademark.
|
|
7
|
+
|
|
8
|
+
There are three places third-party material is redistributed, rather than merely
|
|
9
|
+
depended on:
|
|
10
|
+
|
|
11
|
+
@crombolo/backoffice-dist the built Umbraco backoffice and the browser
|
|
12
|
+
packages bundled into it, produced by
|
|
13
|
+
`bun run vendor:backoffice`
|
|
14
|
+
@crombolo/backoffice-dist three CSS files copied unmodified from the Umbraco
|
|
15
|
+
client source tree
|
|
16
|
+
@crombolo/contracts the Umbraco Management API OpenAPI document,
|
|
17
|
+
copied unmodified
|
|
18
|
+
|
|
19
|
+
No Umbraco trademark is redistributed. The Umbraco wordmark, the "U" roundel
|
|
20
|
+
favicon and the installer illustration are deliberately not carried in this
|
|
21
|
+
repository: MIT grants copyright permission and says nothing about trademarks, so
|
|
22
|
+
crombolo's own marks are served at those paths instead. See `BRANDED_ASSETS` in
|
|
23
|
+
`@crombolo/backoffice-host`.
|
|
24
|
+
|
|
25
|
+
The Umbraco backoffice
|
|
26
|
+
----------------------
|
|
27
|
+
@umbraco-cms/backoffice 18.2.0 — MIT — https://github.com/umbraco/Umbraco-CMS
|
|
28
|
+
@umbraco-ui/uui 2.0.2 — MIT — https://github.com/umbraco/Umbraco.UI
|
|
29
|
+
|
|
30
|
+
Static files from the Umbraco client source tree
|
|
31
|
+
------------------------------------------------
|
|
32
|
+
css/umb-css.css, css/rte-content.css, css/umbraco-blockgridlayout.css
|
|
33
|
+
— copied unmodified from Umbraco-CMS release-18.2.0 — MIT
|
|
34
|
+
— https://github.com/umbraco/Umbraco-CMS
|
|
35
|
+
Shipped in @crombolo/backoffice-dist under `upstream-static/`.
|
|
36
|
+
|
|
37
|
+
`rte-content.css` itself carries Tiptap's default editor styles, copied from
|
|
38
|
+
tiptap v2.11.7 (MIT); the file records this in its own header.
|
|
39
|
+
|
|
40
|
+
The Umbraco Management API contract
|
|
41
|
+
-----------------------------------
|
|
42
|
+
OpenApi.json — copied unmodified from Umbraco-CMS release-18.2.0
|
|
43
|
+
(src/Umbraco.Cms.Api.Management/OpenApi.json) — MIT
|
|
44
|
+
— https://github.com/umbraco/Umbraco-CMS
|
|
45
|
+
Shipped in @crombolo/contracts, which also ships the TypeScript types generated
|
|
46
|
+
from it.
|
|
47
|
+
|
|
48
|
+
Browser runtime dependencies bundled into the backoffice build
|
|
49
|
+
--------------------------------------------------------------
|
|
50
|
+
@heximal/expressions 0.1.5 — BSD-3-Clause
|
|
51
|
+
@microsoft/signalr 10.0.11 — MIT
|
|
52
|
+
@tiptap/* 3.31.3 — MIT
|
|
53
|
+
diff 9.0.0 — BSD-3-Clause
|
|
54
|
+
dompurify 3.4.16 — Apache-2.0, elected from "MPL-2.0 OR Apache-2.0"
|
|
55
|
+
element-internals-polyfill 3.0.2 — MIT
|
|
56
|
+
lit 3.3.3 — BSD-3-Clause
|
|
57
|
+
luxon 3.7.2 — MIT
|
|
58
|
+
marked 18.0.14 — MIT
|
|
59
|
+
monaco-editor 0.57.0 — MIT
|
|
60
|
+
rxjs 7.8.2 — Apache-2.0
|
|
61
|
+
uuid 14.0.2 — MIT
|
|
62
|
+
|
|
63
|
+
dompurify is offered under either licence; Apache-2.0 is elected here, so no
|
|
64
|
+
MPL-2.0 obligation attaches to the copy bundled into the backoffice build. Of the
|
|
65
|
+
Apache-2.0 packages above, none ships a NOTICE file of its own, so Apache-2.0
|
|
66
|
+
section 4(d) adds nothing to this file.
|
|
67
|
+
|
|
68
|
+
Each package's own licence text ships inside its npm distribution and applies
|
|
69
|
+
unchanged to the copies bundled here.
|
package/package.json
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crombolo/data",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "SQLite and Postgres storage for crombolo: schema, migrations and repositories.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Crombolo",
|
|
7
|
+
"homepage": "https://github.com/kineco-au/crombolo-cms#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kineco-au/crombolo-cms.git",
|
|
11
|
+
"directory": "packages/data"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/kineco-au/crombolo-cms/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"bun": ">=1.3.0"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./src/index.ts"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"NOTICE"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@crombolo/core": "0.10.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The declarative builder a bundle writes its tables with. `docs/bundles.md`,
|
|
3
|
+
* Part 4.
|
|
4
|
+
*
|
|
5
|
+
* It is the only way a bundle writes schema: there is no SQL in it, and no
|
|
6
|
+
* escape hatch to some. A step's `up` returns the operations it wants, as plain
|
|
7
|
+
* data, which is what makes a step checkable before it runs — linted for
|
|
8
|
+
* expand and contract, hashed for its checksum, rendered for `upgrade --plan` —
|
|
9
|
+
* and what lets the final shape of every table be worked out from the
|
|
10
|
+
* declaration's types alone.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export type ColumnType =
|
|
14
|
+
| 'uuid'
|
|
15
|
+
| 'varchar'
|
|
16
|
+
| 'text'
|
|
17
|
+
| 'integer'
|
|
18
|
+
| 'bigint'
|
|
19
|
+
| 'boolean'
|
|
20
|
+
| 'timestamp'
|
|
21
|
+
| 'json'
|
|
22
|
+
|
|
23
|
+
/** A scalar a default may be: what DDL can carry as a literal. */
|
|
24
|
+
export type DefaultValue = string | number | boolean
|
|
25
|
+
|
|
26
|
+
export interface ColumnSpec {
|
|
27
|
+
type: ColumnType
|
|
28
|
+
/** For `varchar`. */
|
|
29
|
+
length?: number
|
|
30
|
+
nullable: boolean
|
|
31
|
+
default?: DefaultValue
|
|
32
|
+
primaryKey: boolean
|
|
33
|
+
indexed: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** What a column holds, as the capability reads and writes it. */
|
|
37
|
+
export type JsonValue =
|
|
38
|
+
| string
|
|
39
|
+
| number
|
|
40
|
+
| boolean
|
|
41
|
+
| null
|
|
42
|
+
| JsonValue[]
|
|
43
|
+
| { [key: string]: JsonValue }
|
|
44
|
+
|
|
45
|
+
interface ValueOf {
|
|
46
|
+
uuid: string
|
|
47
|
+
varchar: string
|
|
48
|
+
text: string
|
|
49
|
+
integer: number
|
|
50
|
+
bigint: number
|
|
51
|
+
boolean: boolean
|
|
52
|
+
timestamp: Date
|
|
53
|
+
json: JsonValue
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A column being described. Its type parameters carry what the declaration
|
|
58
|
+
* says, so a table's row type can be read off it.
|
|
59
|
+
*/
|
|
60
|
+
export interface Column<
|
|
61
|
+
T extends ColumnType = ColumnType,
|
|
62
|
+
N extends boolean = false,
|
|
63
|
+
D extends boolean = false,
|
|
64
|
+
> {
|
|
65
|
+
readonly spec: ColumnSpec
|
|
66
|
+
/** Allows null. */
|
|
67
|
+
nullable(): Column<T, true, D>
|
|
68
|
+
/** What a row gets when an insert leaves it out. */
|
|
69
|
+
default(
|
|
70
|
+
value: T extends 'json' ? never : ValueOf[T] extends Date ? never : ValueOf[T],
|
|
71
|
+
): Column<T, N, true>
|
|
72
|
+
primaryKey(): Column<T, N, D>
|
|
73
|
+
/** Gives the column an index of its own. */
|
|
74
|
+
indexed(): Column<T, N, D>
|
|
75
|
+
/** Type-level only: what the column holds. */
|
|
76
|
+
readonly __value?: ValueOf[T]
|
|
77
|
+
readonly __nullable?: N
|
|
78
|
+
readonly __defaulted?: D
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function column<T extends ColumnType>(type: T, spec: Partial<ColumnSpec> = {}): Column<T> {
|
|
82
|
+
const make = (s: ColumnSpec): Column<T, boolean, boolean> =>
|
|
83
|
+
Object.freeze({
|
|
84
|
+
spec: Object.freeze(s),
|
|
85
|
+
nullable: () => make({ ...s, nullable: true }),
|
|
86
|
+
default: (value: DefaultValue) => make({ ...s, default: value }),
|
|
87
|
+
primaryKey: () => make({ ...s, primaryKey: true }),
|
|
88
|
+
indexed: () => make({ ...s, indexed: true }),
|
|
89
|
+
}) as Column<T, boolean, boolean>
|
|
90
|
+
return make({ type, nullable: false, primaryKey: false, indexed: false, ...spec }) as Column<T>
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type Columns = Record<string, Column<ColumnType, boolean, boolean>>
|
|
94
|
+
|
|
95
|
+
export type Operation =
|
|
96
|
+
| { op: 'createTable'; table: string; columns: Record<string, ColumnSpec> }
|
|
97
|
+
| { op: 'addColumn'; table: string; column: string; spec: ColumnSpec }
|
|
98
|
+
| { op: 'addIndex'; table: string; columns: string[]; unique: boolean }
|
|
99
|
+
| { op: 'widenColumn'; table: string; column: string; spec: ColumnSpec }
|
|
100
|
+
| { op: 'dropTable'; table: string }
|
|
101
|
+
| { op: 'dropColumn'; table: string; column: string }
|
|
102
|
+
| { op: 'dropIndex'; table: string; columns: string[] }
|
|
103
|
+
|
|
104
|
+
/** An operation, carrying at the type level what it does to the schema. */
|
|
105
|
+
export type Op<Effect = never> = Operation & { readonly __effect?: Effect }
|
|
106
|
+
|
|
107
|
+
export interface CreateTable<T extends string, C extends Columns> {
|
|
108
|
+
kind: 'create'
|
|
109
|
+
table: T
|
|
110
|
+
columns: C
|
|
111
|
+
}
|
|
112
|
+
export interface AddColumn<
|
|
113
|
+
T extends string,
|
|
114
|
+
K extends string,
|
|
115
|
+
C extends Column<ColumnType, boolean, boolean>,
|
|
116
|
+
> {
|
|
117
|
+
kind: 'add'
|
|
118
|
+
table: T
|
|
119
|
+
column: K
|
|
120
|
+
spec: C
|
|
121
|
+
}
|
|
122
|
+
export interface DropTable<T extends string> {
|
|
123
|
+
kind: 'dropTable'
|
|
124
|
+
table: T
|
|
125
|
+
}
|
|
126
|
+
export interface DropColumn<T extends string, K extends string> {
|
|
127
|
+
kind: 'dropColumn'
|
|
128
|
+
table: T
|
|
129
|
+
column: K
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** What a step's `up` is handed. */
|
|
133
|
+
export interface SchemaBuilder {
|
|
134
|
+
uuid(): Column<'uuid'>
|
|
135
|
+
varchar(length: number): Column<'varchar'>
|
|
136
|
+
text(): Column<'text'>
|
|
137
|
+
integer(): Column<'integer'>
|
|
138
|
+
bigint(): Column<'bigint'>
|
|
139
|
+
boolean(): Column<'boolean'>
|
|
140
|
+
timestamp(): Column<'timestamp'>
|
|
141
|
+
json(): Column<'json'>
|
|
142
|
+
|
|
143
|
+
createTable<T extends string, C extends Columns>(table: T, columns: C): Op<CreateTable<T, C>>
|
|
144
|
+
/** A new column must be nullable or have a default, so it adds under live rows. */
|
|
145
|
+
addColumn<T extends string, K extends string, C extends Column<ColumnType, boolean, boolean>>(
|
|
146
|
+
table: T,
|
|
147
|
+
column: K,
|
|
148
|
+
spec: C,
|
|
149
|
+
): Op<AddColumn<T, K, C>>
|
|
150
|
+
addIndex(table: string, columns: readonly string[], options?: { unique?: boolean }): Op
|
|
151
|
+
/** Longer text, or a wider integer; never narrower, never another kind. */
|
|
152
|
+
widenColumn(table: string, column: string, spec: Column<ColumnType, boolean, boolean>): Op
|
|
153
|
+
dropTable<T extends string>(table: T): Op<DropTable<T>>
|
|
154
|
+
dropColumn<T extends string, K extends string>(table: T, column: K): Op<DropColumn<T, K>>
|
|
155
|
+
dropIndex(table: string, columns: readonly string[]): Op
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const specs = (columns: Columns): Record<string, ColumnSpec> => {
|
|
159
|
+
const out: Record<string, ColumnSpec> = {}
|
|
160
|
+
for (const [name, col] of Object.entries(columns)) out[name] = col.spec
|
|
161
|
+
return out
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** The builder: every method returns plain data. */
|
|
165
|
+
export const schemaBuilder: SchemaBuilder = Object.freeze<SchemaBuilder>({
|
|
166
|
+
uuid: () => column('uuid'),
|
|
167
|
+
varchar: (length: number) => column('varchar', { length }),
|
|
168
|
+
text: () => column('text'),
|
|
169
|
+
integer: () => column('integer'),
|
|
170
|
+
bigint: () => column('bigint'),
|
|
171
|
+
boolean: () => column('boolean'),
|
|
172
|
+
timestamp: () => column('timestamp'),
|
|
173
|
+
json: () => column('json'),
|
|
174
|
+
createTable: (table, columns) => ({ op: 'createTable', table, columns: specs(columns) }) as never,
|
|
175
|
+
addColumn: (table, name, spec) =>
|
|
176
|
+
({ op: 'addColumn', table, column: name, spec: spec.spec }) as never,
|
|
177
|
+
addIndex: (table, columns, options = {}) => ({
|
|
178
|
+
op: 'addIndex',
|
|
179
|
+
table,
|
|
180
|
+
columns: [...columns],
|
|
181
|
+
unique: options.unique ?? false,
|
|
182
|
+
}),
|
|
183
|
+
widenColumn: (table, name, spec) => ({ op: 'widenColumn', table, column: name, spec: spec.spec }),
|
|
184
|
+
dropTable: (table) => ({ op: 'dropTable', table }) as never,
|
|
185
|
+
dropColumn: (table, name) => ({ op: 'dropColumn', table, column: name }) as never,
|
|
186
|
+
dropIndex: (table, columns) => ({ op: 'dropIndex', table, columns: [...columns] }),
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
// ------------------------------------------------------------ the row types
|
|
190
|
+
|
|
191
|
+
type ColumnValue<C> =
|
|
192
|
+
C extends Column<infer T, infer N, boolean>
|
|
193
|
+
? N extends true
|
|
194
|
+
? ValueOf[T] | null
|
|
195
|
+
: ValueOf[T]
|
|
196
|
+
: never
|
|
197
|
+
|
|
198
|
+
/** A table's row, from its columns. */
|
|
199
|
+
export type RowOf<C extends Columns> = { [K in keyof C]: ColumnValue<C[K]> }
|
|
200
|
+
|
|
201
|
+
type Optional<C extends Columns> = {
|
|
202
|
+
[K in keyof C]: C[K] extends Column<ColumnType, infer N, infer D>
|
|
203
|
+
? N extends true
|
|
204
|
+
? K
|
|
205
|
+
: D extends true
|
|
206
|
+
? K
|
|
207
|
+
: never
|
|
208
|
+
: never
|
|
209
|
+
}[keyof C]
|
|
210
|
+
|
|
211
|
+
/** What an insert must and may supply: a nullable or defaulted column may be left out. */
|
|
212
|
+
export type InsertOf<C extends Columns> = Omit<RowOf<C>, Optional<C>> &
|
|
213
|
+
Partial<Pick<RowOf<C>, Optional<C>>>
|
|
214
|
+
|
|
215
|
+
/** Every table's columns, after a run of operations. */
|
|
216
|
+
export type TablesShape = Record<string, Columns>
|
|
217
|
+
|
|
218
|
+
type Effects<R> = R extends readonly unknown[] ? R[number] : R
|
|
219
|
+
type EffectOf<O> = O extends Op<infer E> ? E : never
|
|
220
|
+
|
|
221
|
+
type Apply<S extends TablesShape, E> =
|
|
222
|
+
E extends CreateTable<infer T, infer C>
|
|
223
|
+
? Omit<S, T> & { [K in T]: C }
|
|
224
|
+
: E extends AddColumn<infer T, infer K, infer C>
|
|
225
|
+
? T extends keyof S
|
|
226
|
+
? Omit<S, T> & { [P in T]: S[T] & { [Q in K]: C } }
|
|
227
|
+
: S
|
|
228
|
+
: E extends DropTable<infer T>
|
|
229
|
+
? Omit<S, T>
|
|
230
|
+
: E extends DropColumn<infer T, infer K>
|
|
231
|
+
? T extends keyof S
|
|
232
|
+
? Omit<S, T> & { [P in T]: Omit<S[T], K> }
|
|
233
|
+
: S
|
|
234
|
+
: S
|
|
235
|
+
|
|
236
|
+
type ApplyAll<S extends TablesShape, E> = [E] extends [never]
|
|
237
|
+
? S
|
|
238
|
+
: // A union of effects within one step is applied one member at a time.
|
|
239
|
+
UnionToTuple<E> extends infer L
|
|
240
|
+
? L extends readonly [infer H, ...infer Rest]
|
|
241
|
+
? ApplyAll<Flatten<Apply<S, H>>, Rest[number]>
|
|
242
|
+
: S
|
|
243
|
+
: S
|
|
244
|
+
|
|
245
|
+
type Flatten<T> = { [K in keyof T]: T[K] } & {}
|
|
246
|
+
|
|
247
|
+
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
|
|
248
|
+
k: infer I,
|
|
249
|
+
) => void
|
|
250
|
+
? I
|
|
251
|
+
: never
|
|
252
|
+
type LastOf<U> =
|
|
253
|
+
UnionToIntersection<U extends unknown ? () => U : never> extends () => infer R ? R : never
|
|
254
|
+
type UnionToTuple<U, L = LastOf<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, L>>, L]
|
|
255
|
+
|
|
256
|
+
/** The shape after every step, in order: what `context.host.tables` is typed from. */
|
|
257
|
+
export type ShapeOf<
|
|
258
|
+
Steps extends readonly unknown[],
|
|
259
|
+
S extends TablesShape = Record<never, never>,
|
|
260
|
+
> = Steps extends readonly [infer First, ...infer Rest]
|
|
261
|
+
? First extends { up: (s: SchemaBuilder) => infer R }
|
|
262
|
+
? ShapeOf<Rest, Flatten<ApplyAll<S, EffectOf<Effects<R>>>>>
|
|
263
|
+
: ShapeOf<Rest, S>
|
|
264
|
+
: S
|