@hot-updater/server 1.0.0-rc.17 → 1.0.0-rc.18
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/adapters/drizzle.cjs +5 -5
- package/dist/adapters/drizzle.mjs +4 -4
- package/dist/adapters/kysely.cjs +3 -3
- package/dist/adapters/kysely.mjs +2 -2
- package/dist/adapters/mongodb.cjs +3 -3
- package/dist/adapters/mongodb.mjs +2 -2
- package/dist/adapters/mongodbAdapter.cjs +19 -1
- package/dist/adapters/mongodbAdapter.mjs +19 -1
- package/dist/adapters/prisma.cjs +5 -5
- package/dist/adapters/prisma.mjs +4 -4
- package/dist/assembly/assemblePlugins.cjs +47 -28
- package/dist/assembly/assemblePlugins.d.cts +3 -7
- package/dist/assembly/assemblePlugins.d.mts +3 -7
- package/dist/assembly/assemblePlugins.mjs +46 -27
- package/dist/assembly/clientPlugins.cjs +86 -0
- package/dist/assembly/clientPlugins.d.cts +16 -0
- package/dist/assembly/clientPlugins.d.mts +16 -0
- package/dist/assembly/clientPlugins.mjs +86 -0
- package/dist/assembly/configError.cjs +7 -0
- package/dist/assembly/configError.d.cts +7 -0
- package/dist/assembly/configError.d.mts +7 -0
- package/dist/assembly/configError.mjs +7 -0
- package/dist/assembly/databasePlugins.cjs +5 -1
- package/dist/assembly/databasePlugins.d.cts +5 -5
- package/dist/assembly/databasePlugins.d.mts +5 -5
- package/dist/assembly/databasePlugins.mjs +5 -1
- package/dist/assembly/pluginCli.cjs +125 -0
- package/dist/assembly/pluginCli.d.cts +59 -0
- package/dist/assembly/pluginCli.d.mts +59 -0
- package/dist/assembly/pluginCli.mjs +121 -0
- package/dist/createHotUpdaterCore.cjs +14 -16
- package/dist/createHotUpdaterCore.d.cts +10 -3
- package/dist/createHotUpdaterCore.d.mts +10 -3
- package/dist/createHotUpdaterCore.mjs +11 -13
- package/dist/database/aggregateBatching.cjs +626 -0
- package/dist/database/aggregateBatching.d.cts +10 -0
- package/dist/database/aggregateBatching.d.mts +10 -0
- package/dist/database/aggregateBatching.mjs +625 -0
- package/dist/{insights/errors.cjs → database/busy.cjs} +2 -15
- package/dist/database/busy.d.cts +12 -0
- package/dist/database/busy.d.mts +12 -0
- package/dist/{insights/errors.mjs → database/busy.mjs} +3 -14
- package/dist/database/database.cjs +22 -3
- package/dist/database/database.d.cts +15 -2
- package/dist/database/database.d.mts +15 -2
- package/dist/database/database.mjs +22 -3
- package/dist/database/definitions.d.cts +10 -0
- package/dist/database/definitions.d.mts +10 -0
- package/dist/database/engine.d.cts +2 -1
- package/dist/database/engine.d.mts +2 -1
- package/dist/database/engineAggregates.cjs +7 -4
- package/dist/database/engineAggregates.mjs +8 -5
- package/dist/database/engineReads.cjs +5 -3
- package/dist/database/engineReads.mjs +6 -4
- package/dist/database/engineTransaction.cjs +2 -6
- package/dist/database/engineTransaction.mjs +2 -6
- package/dist/database/fence.cjs +2 -1
- package/dist/database/fence.mjs +2 -1
- package/dist/database/index.cjs +17 -8
- package/dist/database/index.d.cts +5 -4
- package/dist/database/index.d.mts +5 -4
- package/dist/database/index.mjs +6 -5
- package/dist/database/kv/kvAdapter.cjs +15 -3
- package/dist/database/kv/kvAdapter.d.cts +8 -0
- package/dist/database/kv/kvAdapter.d.mts +8 -0
- package/dist/database/kv/kvAdapter.mjs +16 -4
- package/dist/database/resolveSchema.cjs +4 -1
- package/dist/database/resolveSchema.d.cts +1 -1
- package/dist/database/resolveSchema.d.mts +1 -1
- package/dist/database/resolveSchema.mjs +4 -1
- package/dist/database/retention.cjs +92 -0
- package/dist/database/retention.mjs +90 -0
- package/dist/database/schema.cjs +5 -2
- package/dist/database/schema.d.cts +30 -1
- package/dist/database/schema.d.mts +30 -1
- package/dist/database/schema.mjs +5 -2
- package/dist/database/sql/sqlAdapter.cjs +8 -0
- package/dist/database/sql/sqlAdapter.mjs +9 -1
- package/dist/database/sql/sqlSchema.cjs +56 -0
- package/dist/database/sql/sqlSchema.mjs +55 -1
- package/dist/db/coreDatabase.cjs +85 -0
- package/dist/db/coreDatabase.d.cts +57 -0
- package/dist/db/coreDatabase.d.mts +57 -0
- package/dist/db/coreDatabase.mjs +78 -0
- package/dist/db/index.cjs +11 -1
- package/dist/db/index.d.cts +7 -2
- package/dist/db/index.d.mts +7 -2
- package/dist/db/index.mjs +6 -2
- package/dist/db/types.d.cts +3 -3
- package/dist/db/types.d.mts +3 -3
- package/dist/handler.cjs +2 -14
- package/dist/handler.mjs +1 -13
- package/dist/handlerReleaseCatalogRoutes.cjs +21 -2
- package/dist/handlerReleaseCatalogRoutes.mjs +21 -2
- package/dist/index.cjs +2 -6
- package/dist/index.d.cts +4 -7
- package/dist/index.d.mts +4 -7
- package/dist/index.mjs +2 -4
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/{apiKeys.cjs → plugins/api-keys/apiKeys.cjs} +1 -1
- package/dist/{apiKeys.d.cts → plugins/api-keys/apiKeys.d.cts} +2 -2
- package/dist/{apiKeys.d.mts → plugins/api-keys/apiKeys.d.mts} +2 -2
- package/dist/{apiKeys.mjs → plugins/api-keys/apiKeys.mjs} +1 -1
- package/dist/plugins/api-keys/cli.cjs +115 -0
- package/dist/plugins/api-keys/cli.mjs +114 -0
- package/dist/plugins/api-keys/index.cjs +9 -6
- package/dist/plugins/api-keys/index.d.cts +4 -5
- package/dist/plugins/api-keys/index.d.mts +4 -5
- package/dist/plugins/api-keys/index.mjs +9 -7
- package/dist/plugins/api-keys/model.d.cts +20 -2
- package/dist/plugins/api-keys/model.d.mts +20 -2
- package/dist/plugins/definePlugin.cjs +1 -1
- package/dist/plugins/definePlugin.d.cts +130 -3
- package/dist/plugins/definePlugin.d.mts +130 -3
- package/dist/plugins/definePlugin.mjs +1 -1
- package/dist/plugins/index.cjs +25 -4
- package/dist/plugins/index.d.cts +7 -4
- package/dist/plugins/index.d.mts +7 -4
- package/dist/plugins/index.mjs +6 -4
- package/dist/plugins/insights/contract.cjs +193 -0
- package/dist/plugins/insights/contract.mjs +189 -0
- package/dist/{insights → plugins/insights}/domain.d.cts +60 -15
- package/dist/{insights → plugins/insights}/domain.d.mts +60 -15
- package/dist/plugins/insights/errors.cjs +15 -0
- package/dist/plugins/insights/errors.mjs +14 -0
- package/dist/{insights → plugins/insights}/eventInput.cjs +155 -22
- package/dist/{insights → plugins/insights}/eventInput.mjs +155 -22
- package/dist/plugins/insights/eventRow.cjs +49 -0
- package/dist/plugins/insights/eventRow.d.cts +64 -0
- package/dist/plugins/insights/eventRow.d.mts +64 -0
- package/dist/plugins/insights/eventRow.mjs +47 -0
- package/dist/plugins/insights/index.cjs +106 -26
- package/dist/plugins/insights/index.d.cts +130 -27
- package/dist/plugins/insights/index.d.mts +130 -27
- package/dist/plugins/insights/index.mjs +106 -29
- package/dist/plugins/insights/model.cjs +2 -2
- package/dist/plugins/insights/model.d.cts +1 -1
- package/dist/plugins/insights/model.d.mts +1 -1
- package/dist/plugins/insights/model.mjs +1 -1
- package/dist/plugins/insights/modelTypes.d.cts +176 -0
- package/dist/plugins/insights/modelTypes.d.mts +176 -0
- package/dist/plugins/insights/overview.cjs +109 -0
- package/dist/plugins/insights/overview.d.cts +15 -0
- package/dist/plugins/insights/overview.d.mts +15 -0
- package/dist/plugins/insights/overview.mjs +107 -0
- package/dist/{insights → plugins/insights}/provider.cjs +33 -14
- package/dist/{insights → plugins/insights}/provider.d.cts +2 -2
- package/dist/{insights → plugins/insights}/provider.d.mts +2 -2
- package/dist/{insights → plugins/insights}/provider.mjs +30 -11
- package/dist/{insights → plugins/insights}/queryInput.cjs +2 -2
- package/dist/{insights → plugins/insights}/queryInput.mjs +2 -2
- package/dist/plugins/insights/reads.cjs +298 -88
- package/dist/plugins/insights/reads.d.cts +61 -0
- package/dist/plugins/insights/reads.d.mts +61 -0
- package/dist/plugins/insights/reads.mjs +298 -90
- package/dist/plugins/insights/recordEvent.cjs +223 -39
- package/dist/plugins/insights/recordEvent.d.cts +9 -4
- package/dist/plugins/insights/recordEvent.d.mts +9 -4
- package/dist/plugins/insights/recordEvent.mjs +221 -37
- package/dist/{insights → plugins/insights}/routes.cjs +3 -30
- package/dist/{insights → plugins/insights}/routes.mjs +4 -28
- package/dist/plugins/insights/schema.cjs +182 -40
- package/dist/plugins/insights/schema.d.cts +446 -6
- package/dist/plugins/insights/schema.d.mts +446 -6
- package/dist/plugins/insights/schema.mjs +180 -41
- package/dist/plugins/insights/testing/eventRow.d.mts +64 -0
- package/dist/plugins/insights/testing/expectInsightsIndex.mjs +18 -0
- package/dist/plugins/insights/testing/fixtures.d.mts +8 -0
- package/dist/plugins/insights/testing/fixtures.mjs +25 -0
- package/dist/plugins/insights/testing/index.d.mts +24 -0
- package/dist/plugins/insights/testing/index.mjs +25 -0
- package/dist/plugins/insights/testing/insightsModelTests.mjs +714 -0
- package/dist/plugins/insights/testing/modelTypes.d.mts +176 -0
- package/dist/plugins/insights/testing/setupInsightsHttpTestSuite.d.mts +11 -0
- package/dist/plugins/insights/testing/setupInsightsHttpTestSuite.mjs +107 -0
- package/dist/plugins/insights/testing/setupInsightsModelTestSuite.d.mts +11 -0
- package/dist/plugins/insights/testing/setupInsightsModelTestSuite.mjs +31 -0
- package/dist/plugins/insights/testing/types.d.mts +26 -0
- package/dist/{insights → plugins/insights}/types.d.cts +3 -2
- package/dist/{insights → plugins/insights}/types.d.mts +3 -2
- package/package.json +14 -7
- package/src/adapters/drizzle.conformance.integration.spec.ts +2 -2
- package/src/adapters/drizzle.readBudgets.integration.spec.ts +6 -4
- package/src/adapters/drizzle.spec.ts +15 -7
- package/src/adapters/drizzle.ts +6 -6
- package/src/adapters/kysely.conformance.integration.spec.ts +2 -2
- package/src/adapters/kysely.readBudgets.integration.spec.ts +4 -2
- package/src/adapters/kysely.spec.ts +13 -9
- package/src/adapters/kysely.ts +2 -2
- package/src/adapters/mongodb.integration.spec.ts +98 -7
- package/src/adapters/mongodb.ts +2 -2
- package/src/adapters/mongodbAdapter.ts +14 -0
- package/src/adapters/prisma.conformance.integration.spec.ts +2 -2
- package/src/adapters/prisma.integration.spec.ts +16 -8
- package/src/adapters/prisma.readBudgets.integration.spec.ts +5 -2
- package/src/adapters/prisma.spec.ts +17 -9
- package/src/adapters/prisma.ts +6 -6
- package/src/adapters/prismaTestClients.ts +8 -1
- package/src/assembly/assemblePlugins.ts +73 -40
- package/src/assembly/assembly.spec.ts +63 -11
- package/src/assembly/assembly.types.spec.ts +50 -2
- package/src/assembly/clientPlugins.ts +113 -0
- package/src/assembly/configError.ts +4 -0
- package/src/assembly/databasePlugins.ts +11 -5
- package/src/assembly/pluginCli.spec.ts +254 -0
- package/src/assembly/pluginCli.ts +248 -0
- package/src/assembly/{builtInRoutes.spec.ts → pluginRoutes.spec.ts} +10 -37
- package/src/createHotUpdaterCore.ts +21 -17
- package/src/database/aggregateBatching.spec.ts +577 -0
- package/src/database/aggregateBatching.ts +803 -0
- package/src/{insights/errors.spec.ts → database/busy.spec.ts} +2 -5
- package/src/{insights/errors.ts → database/busy.ts} +1 -13
- package/src/database/database.ts +39 -8
- package/src/database/definitions.ts +4 -0
- package/src/database/engineAggregates.spec.ts +4 -7
- package/src/database/engineAggregates.ts +5 -9
- package/src/database/engineReads.ts +7 -5
- package/src/database/engineTransaction.ts +1 -7
- package/src/database/fence.spec.ts +5 -5
- package/src/database/fence.ts +4 -0
- package/src/database/index.ts +13 -7
- package/src/database/kv/kvAdapter.batching.integration.spec.ts +15 -0
- package/src/database/kv/kvAdapter.conformance.integration.spec.ts +2 -0
- package/src/database/kv/kvAdapter.spec.ts +128 -1
- package/src/database/kv/kvAdapter.ts +30 -1
- package/src/database/kv/kvTestStore.ts +28 -1
- package/src/database/resolveSchema.ts +4 -1
- package/src/database/retention.spec.ts +314 -0
- package/src/database/retention.ts +129 -0
- package/src/database/schema.ts +44 -0
- package/src/database/sql/sqlAdapter.integration.spec.ts +4 -7
- package/src/database/sql/sqlAdapter.readBudgets.integration.spec.ts +18 -4
- package/src/database/sql/sqlAdapter.spec.ts +91 -3
- package/src/database/sql/sqlAdapter.ts +20 -0
- package/src/database/sql/sqlSchema.ts +81 -0
- package/src/databaseTestSuite.spec.ts +9 -4
- package/src/db/coreDatabase.ts +153 -0
- package/src/db/engineSql.spec.ts +8 -7
- package/src/db/index.ts +19 -1
- package/src/db/pluginTables.spec.ts +57 -27
- package/src/db/types.ts +3 -3
- package/src/handler-standalone.integration.spec.ts +2 -3
- package/src/handler.ts +1 -32
- package/src/handlerReleaseCatalogRoutes.ts +26 -2
- package/src/index.ts +0 -10
- package/src/{apiKeys.integration.spec.ts → plugins/api-keys/apiKeys.integration.spec.ts} +4 -4
- package/src/{apiKeys.spec.ts → plugins/api-keys/apiKeys.spec.ts} +3 -3
- package/src/{apiKeys.ts → plugins/api-keys/apiKeys.ts} +1 -1
- package/src/plugins/api-keys/apiKeysPlugin.spec.ts +11 -15
- package/src/plugins/api-keys/cli.spec.ts +187 -0
- package/src/plugins/api-keys/cli.ts +140 -0
- package/src/plugins/api-keys/index.ts +48 -41
- package/src/plugins/api-keys/model.ts +21 -2
- package/src/plugins/definePlugin.ts +144 -2
- package/src/plugins/index.ts +20 -2
- package/src/plugins/insights/contract.spec.ts +285 -0
- package/src/plugins/insights/contract.ts +372 -0
- package/src/{insights → plugins/insights}/domain.ts +73 -15
- package/src/plugins/insights/errors.ts +11 -0
- package/src/{insights → plugins/insights}/eventInput.ts +189 -29
- package/src/plugins/insights/eventRow.ts +209 -0
- package/src/plugins/insights/index.ts +181 -45
- package/src/{insights → plugins/insights}/insights.integration.spec.ts +330 -34
- package/src/plugins/insights/insightsRollout.integration.spec.ts +1 -2
- package/src/plugins/insights/model.spec.ts +3 -5
- package/src/plugins/insights/model.ts +2 -3
- package/src/plugins/insights/modelTypes.ts +197 -0
- package/src/plugins/insights/overview.spec.ts +64 -0
- package/src/plugins/insights/overview.ts +214 -0
- package/src/{insights → plugins/insights}/provider.spec.ts +21 -10
- package/src/{insights → plugins/insights}/provider.ts +58 -21
- package/src/{insights → plugins/insights}/queryInput.ts +2 -2
- package/src/plugins/insights/reads.spec.ts +340 -52
- package/src/plugins/insights/reads.ts +453 -123
- package/src/plugins/insights/recordEvent.spec.ts +474 -20
- package/src/plugins/insights/recordEvent.ts +301 -63
- package/src/plugins/insights/retention.spec.ts +115 -0
- package/src/{insights → plugins/insights}/routes.ts +1 -31
- package/src/plugins/insights/schema.ts +356 -176
- package/src/plugins/insights/testing/expectInsightsIndex.spec.ts +42 -0
- package/src/plugins/insights/testing/expectInsightsIndex.ts +20 -0
- package/src/plugins/insights/testing/fixtures.ts +30 -0
- package/src/plugins/insights/testing/index.ts +45 -0
- package/src/plugins/insights/testing/insightsModelTests.ts +860 -0
- package/src/plugins/insights/testing/setupInsightsHttpTestSuite.ts +152 -0
- package/src/plugins/insights/testing/setupInsightsModelTestSuite.ts +36 -0
- package/src/plugins/insights/testing/types.ts +30 -0
- package/src/{insights → plugins/insights}/types.ts +1 -1
- package/src/readBudgets.testFixtures.ts +2 -2
- package/src/releaseCatalogRoutes.integration.spec.ts +7 -0
- package/src/retention.spec.ts +73 -0
- package/src/runtime.spec.ts +11 -12
- package/src/runtime.testFixtures.ts +7 -2
- package/src/testUtilsMutation.integration.spec.ts +2 -1
- package/src/testUtilsPackage.integration.spec.ts +7 -3
- package/dist/db/builtInDatabase.cjs +0 -104
- package/dist/db/builtInDatabase.d.cts +0 -38
- package/dist/db/builtInDatabase.d.mts +0 -38
- package/dist/db/builtInDatabase.mjs +0 -97
- package/dist/plugins/builtIn.cjs +0 -7
- package/dist/plugins/builtIn.mjs +0 -6
- package/src/db/builtInDatabase.ts +0 -149
- package/src/plugins/builtIn.ts +0 -5
|
@@ -80,6 +80,13 @@ const sqlTableShapes = (dialect, tables, tablePrefix = "") => tables.map((table)
|
|
|
80
80
|
columns: index.unique ? index.eq : columns
|
|
81
81
|
}];
|
|
82
82
|
});
|
|
83
|
+
const retention = table.retention && retentionOrder(table);
|
|
84
|
+
if (retention && !retention.indexed) indexes.push({
|
|
85
|
+
kind: "index",
|
|
86
|
+
name: shortSqlName(`${name}__retention`),
|
|
87
|
+
unique: false,
|
|
88
|
+
columns: retention.columns
|
|
89
|
+
});
|
|
83
90
|
return {
|
|
84
91
|
name,
|
|
85
92
|
columns: table.columns.map((column) => ({
|
|
@@ -107,9 +114,58 @@ const createTableStatements = (dialect, tables, tablePrefix = "") => {
|
|
|
107
114
|
};
|
|
108
115
|
return sqlTableShapes(dialect, tables, tablePrefix).flatMap(render);
|
|
109
116
|
};
|
|
117
|
+
/**
|
|
118
|
+
* The order a prune walks a table's expired rows in, which ends with the
|
|
119
|
+
* key so it is total: the columns of the first index that leads with the
|
|
120
|
+
* retention column, or the key when it does, or else the column and the
|
|
121
|
+
* key, which then need an index of their own (`indexed` false).
|
|
122
|
+
*/
|
|
123
|
+
const retentionOrder = (table) => {
|
|
124
|
+
const { column } = table.retention;
|
|
125
|
+
for (const index of table.indexes) {
|
|
126
|
+
const columns = [...index.eq, ...(0, _hot_updater_plugin_core_internal.indexOrderColumns)(table, index)];
|
|
127
|
+
if (!index.unique && !isMultiIndex(table, index) && columns[0] === column) return {
|
|
128
|
+
columns,
|
|
129
|
+
indexed: true
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (table.key[0] === column) return {
|
|
133
|
+
columns: table.key,
|
|
134
|
+
indexed: true
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
columns: [column, ...table.key.filter((field) => field !== column)],
|
|
138
|
+
indexed: false
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* The statements that delete up to `limit` expired rows of a table with
|
|
143
|
+
* retention, oldest first in {@link retentionOrder}: its multi-valued index
|
|
144
|
+
* entries, then the rows, which a concurrent write that moved the retention
|
|
145
|
+
* column past `before` keeps. `before` renders the bound each time it
|
|
146
|
+
* appears. MySQL deletes with ORDER BY and LIMIT. Elsewhere the cutoff is
|
|
147
|
+
* the last of the `limit` oldest expired rows in that order, a row value
|
|
148
|
+
* the index ranges over, and the shapes pass Supabase's apply RPC: no IN, no
|
|
149
|
+
* AS, aliases `i` and `b`.
|
|
150
|
+
*/
|
|
151
|
+
const pruneStatements = (dialect, table, tablePrefix, limit) => {
|
|
152
|
+
const quote = (name) => quoteSql(dialect, name);
|
|
153
|
+
const name = quote(`${tablePrefix}${table.name}`);
|
|
154
|
+
const at = quote(table.retention.column);
|
|
155
|
+
const order = retentionOrder(table).columns.map(quote);
|
|
156
|
+
const list = (alias, direction = "") => order.map((column) => `${alias}.${column}${direction}`).join(", ");
|
|
157
|
+
const oldest = (before) => `SELECT ${list("i")} FROM ${name} i WHERE i.${at} <= ${before()} ORDER BY ${list("i", " ASC")} LIMIT ${limit}`;
|
|
158
|
+
const doomed = (alias, before) => `${alias}.${at} <= ${before()} AND (${list(alias)}) <= (SELECT ${list("b")} FROM (${oldest(before)}) b ORDER BY ${list("b", " DESC")} LIMIT 1)`;
|
|
159
|
+
const entries = table.indexes.filter((index) => isMultiIndex(table, index)).map((index) => quote(`${tablePrefix}${table.name}__${index.name}`));
|
|
160
|
+
const keyOf = (left, right) => table.key.map((column) => `${left}.${quote(column)} = ${right}.${quote(column)}`).join(" AND ");
|
|
161
|
+
if (dialect === "mysql") return [...entries.map((index) => (before) => `DELETE e FROM ${index} e JOIN (${oldest(before)}) d ON ${keyOf("e", "d")}`), (before) => `DELETE FROM ${name} WHERE ${at} <= ${before()} ORDER BY ${order.join(", ")} LIMIT ${limit}`];
|
|
162
|
+
return [...entries.map((index) => (before) => `DELETE FROM ${index} WHERE EXISTS (SELECT * FROM ${name} b WHERE ${keyOf("b", index)} AND ${doomed("b", before)})`), (before) => `DELETE FROM ${name} WHERE ${doomed(name, before)}`];
|
|
163
|
+
};
|
|
110
164
|
//#endregion
|
|
111
165
|
exports.createTableStatements = createTableStatements;
|
|
112
166
|
exports.isMultiIndex = isMultiIndex;
|
|
167
|
+
exports.pruneStatements = pruneStatements;
|
|
113
168
|
exports.quoteSql = quoteSql;
|
|
169
|
+
exports.retentionOrder = retentionOrder;
|
|
114
170
|
exports.shortSqlName = shortSqlName;
|
|
115
171
|
exports.sqlTableShapes = sqlTableShapes;
|
|
@@ -80,6 +80,13 @@ const sqlTableShapes = (dialect, tables, tablePrefix = "") => tables.map((table)
|
|
|
80
80
|
columns: index.unique ? index.eq : columns
|
|
81
81
|
}];
|
|
82
82
|
});
|
|
83
|
+
const retention = table.retention && retentionOrder(table);
|
|
84
|
+
if (retention && !retention.indexed) indexes.push({
|
|
85
|
+
kind: "index",
|
|
86
|
+
name: shortSqlName(`${name}__retention`),
|
|
87
|
+
unique: false,
|
|
88
|
+
columns: retention.columns
|
|
89
|
+
});
|
|
83
90
|
return {
|
|
84
91
|
name,
|
|
85
92
|
columns: table.columns.map((column) => ({
|
|
@@ -107,5 +114,52 @@ const createTableStatements = (dialect, tables, tablePrefix = "") => {
|
|
|
107
114
|
};
|
|
108
115
|
return sqlTableShapes(dialect, tables, tablePrefix).flatMap(render);
|
|
109
116
|
};
|
|
117
|
+
/**
|
|
118
|
+
* The order a prune walks a table's expired rows in, which ends with the
|
|
119
|
+
* key so it is total: the columns of the first index that leads with the
|
|
120
|
+
* retention column, or the key when it does, or else the column and the
|
|
121
|
+
* key, which then need an index of their own (`indexed` false).
|
|
122
|
+
*/
|
|
123
|
+
const retentionOrder = (table) => {
|
|
124
|
+
const { column } = table.retention;
|
|
125
|
+
for (const index of table.indexes) {
|
|
126
|
+
const columns = [...index.eq, ...indexOrderColumns(table, index)];
|
|
127
|
+
if (!index.unique && !isMultiIndex(table, index) && columns[0] === column) return {
|
|
128
|
+
columns,
|
|
129
|
+
indexed: true
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (table.key[0] === column) return {
|
|
133
|
+
columns: table.key,
|
|
134
|
+
indexed: true
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
columns: [column, ...table.key.filter((field) => field !== column)],
|
|
138
|
+
indexed: false
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* The statements that delete up to `limit` expired rows of a table with
|
|
143
|
+
* retention, oldest first in {@link retentionOrder}: its multi-valued index
|
|
144
|
+
* entries, then the rows, which a concurrent write that moved the retention
|
|
145
|
+
* column past `before` keeps. `before` renders the bound each time it
|
|
146
|
+
* appears. MySQL deletes with ORDER BY and LIMIT. Elsewhere the cutoff is
|
|
147
|
+
* the last of the `limit` oldest expired rows in that order, a row value
|
|
148
|
+
* the index ranges over, and the shapes pass Supabase's apply RPC: no IN, no
|
|
149
|
+
* AS, aliases `i` and `b`.
|
|
150
|
+
*/
|
|
151
|
+
const pruneStatements = (dialect, table, tablePrefix, limit) => {
|
|
152
|
+
const quote = (name) => quoteSql(dialect, name);
|
|
153
|
+
const name = quote(`${tablePrefix}${table.name}`);
|
|
154
|
+
const at = quote(table.retention.column);
|
|
155
|
+
const order = retentionOrder(table).columns.map(quote);
|
|
156
|
+
const list = (alias, direction = "") => order.map((column) => `${alias}.${column}${direction}`).join(", ");
|
|
157
|
+
const oldest = (before) => `SELECT ${list("i")} FROM ${name} i WHERE i.${at} <= ${before()} ORDER BY ${list("i", " ASC")} LIMIT ${limit}`;
|
|
158
|
+
const doomed = (alias, before) => `${alias}.${at} <= ${before()} AND (${list(alias)}) <= (SELECT ${list("b")} FROM (${oldest(before)}) b ORDER BY ${list("b", " DESC")} LIMIT 1)`;
|
|
159
|
+
const entries = table.indexes.filter((index) => isMultiIndex(table, index)).map((index) => quote(`${tablePrefix}${table.name}__${index.name}`));
|
|
160
|
+
const keyOf = (left, right) => table.key.map((column) => `${left}.${quote(column)} = ${right}.${quote(column)}`).join(" AND ");
|
|
161
|
+
if (dialect === "mysql") return [...entries.map((index) => (before) => `DELETE e FROM ${index} e JOIN (${oldest(before)}) d ON ${keyOf("e", "d")}`), (before) => `DELETE FROM ${name} WHERE ${at} <= ${before()} ORDER BY ${order.join(", ")} LIMIT ${limit}`];
|
|
162
|
+
return [...entries.map((index) => (before) => `DELETE FROM ${index} WHERE EXISTS (SELECT * FROM ${name} b WHERE ${keyOf("b", index)} AND ${doomed("b", before)})`), (before) => `DELETE FROM ${name} WHERE ${doomed(name, before)}`];
|
|
163
|
+
};
|
|
110
164
|
//#endregion
|
|
111
|
-
export { createTableStatements, isMultiIndex, quoteSql, shortSqlName, sqlTableShapes };
|
|
165
|
+
export { createTableStatements, isMultiIndex, pruneStatements, quoteSql, retentionOrder, shortSqlName, sqlTableShapes };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const require_resolveSchema = require("../database/resolveSchema.cjs");
|
|
2
|
+
const require_schema = require("../core/schema.cjs");
|
|
3
|
+
const require_fence = require("../database/fence.cjs");
|
|
4
|
+
const require_schemaSettings = require("./schemaSettings.cjs");
|
|
5
|
+
const require_engineMigrator = require("./engineMigrator.cjs");
|
|
6
|
+
//#region src/db/coreDatabase.ts
|
|
7
|
+
/** Core's tables: the tables every provider's tooling creates. */
|
|
8
|
+
const coreSchema = require_resolveSchema.resolveSchema([require_schema.coreModule]);
|
|
9
|
+
/** The settings rows a provider's database is fenced by. */
|
|
10
|
+
const coreSettings = {
|
|
11
|
+
[require_fence.ENGINE_SCHEMA_KEY]: "1",
|
|
12
|
+
"schema.core": require_schema.HOT_UPDATER_SCHEMA_VERSION
|
|
13
|
+
};
|
|
14
|
+
/** What `hot-updater db` creates for a server without plugins. */
|
|
15
|
+
const coreTarget = {
|
|
16
|
+
schema: coreSchema,
|
|
17
|
+
settings: coreSettings
|
|
18
|
+
};
|
|
19
|
+
/** Each plugin's `schema.<id>` settings row. */
|
|
20
|
+
const pluginSettings = (plugins) => Object.fromEntries(plugins.map(({ id, schemaVersion }) => [`schema.${id}`, schemaVersion]));
|
|
21
|
+
/** A plugin's schema as the engine resolves it: prefixed by its id unless it keeps its names. */
|
|
22
|
+
const pluginModule = ({ id, schema, namespace }) => ({
|
|
23
|
+
id,
|
|
24
|
+
schema,
|
|
25
|
+
...namespace === false ? {} : { namespace: id }
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* What `hot-updater db` creates for a server's plugins: core's tables, then
|
|
29
|
+
* each plugin's tables with its `schema.<id>` settings row.
|
|
30
|
+
*/
|
|
31
|
+
const toolingTargetOf = (plugins) => plugins.length === 0 ? coreTarget : {
|
|
32
|
+
schema: require_resolveSchema.resolveSchema([require_schema.coreModule, ...plugins.map(pluginModule)]),
|
|
33
|
+
settings: {
|
|
34
|
+
...coreSettings,
|
|
35
|
+
...pluginSettings(plugins)
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Creates core's tables and those of `plugins`, then writes their settings
|
|
40
|
+
* rows: what a provider's setup runs for the plugins its server runs.
|
|
41
|
+
*/
|
|
42
|
+
const migrateCoreSchema = (adapter, name, plugins = []) => {
|
|
43
|
+
const { schema, settings } = toolingTargetOf(plugins);
|
|
44
|
+
return require_schemaSettings.migrateSchema(adapter, name, schema.tables, settings);
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* A provider's database on the storage engine: its adapter behind the schema
|
|
48
|
+
* fence, which checks core's settings rows before the first read or write
|
|
49
|
+
* and names `hot-updater db migrate` when they are missing or stale. When the
|
|
50
|
+
* adapter creates its own tables, `hot-updater db migrate` creates core's
|
|
51
|
+
* tables and the server's plugin tables, then writes their settings rows.
|
|
52
|
+
*/
|
|
53
|
+
const createEngineDatabase = ({ name, adapter, onCachedRoutesChange, aggregateBatching }) => {
|
|
54
|
+
const fenced = require_fence.withSchemaFence(adapter, name, coreSettings);
|
|
55
|
+
const createMigrator = ({ schema, settings } = coreTarget) => require_engineMigrator.createEngineMigrator({
|
|
56
|
+
adapterName: name,
|
|
57
|
+
adapter,
|
|
58
|
+
schema,
|
|
59
|
+
settings,
|
|
60
|
+
readSettings: async () => {
|
|
61
|
+
const rows = await require_fence.readSettings(adapter, Object.keys(settings)).catch((error) => {
|
|
62
|
+
if (require_fence.isMissingSchemaError(error)) return [];
|
|
63
|
+
throw error;
|
|
64
|
+
});
|
|
65
|
+
return new Map(rows.flatMap((row) => row === null ? [] : [[String(row.key), row.value]]));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
name,
|
|
70
|
+
adapter: fenced,
|
|
71
|
+
...onCachedRoutesChange === void 0 ? {} : { onCachedRoutesChange },
|
|
72
|
+
...aggregateBatching ? { aggregateBatching } : {},
|
|
73
|
+
...adapter.dispose === void 0 ? {} : { dispose: () => adapter.dispose() },
|
|
74
|
+
...adapter.migrations === void 0 ? {} : { createMigrator }
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
//#endregion
|
|
78
|
+
exports.coreSchema = coreSchema;
|
|
79
|
+
exports.coreSettings = coreSettings;
|
|
80
|
+
exports.coreTarget = coreTarget;
|
|
81
|
+
exports.createEngineDatabase = createEngineDatabase;
|
|
82
|
+
exports.migrateCoreSchema = migrateCoreSchema;
|
|
83
|
+
exports.pluginModule = pluginModule;
|
|
84
|
+
exports.pluginSettings = pluginSettings;
|
|
85
|
+
exports.toolingTargetOf = toolingTargetOf;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SchemaSettings } from "../database/fence.cjs";
|
|
2
|
+
import { ModelShape } from "../database/definitions.cjs";
|
|
3
|
+
import { ResolvedSchema } from "../database/resolveSchema.cjs";
|
|
4
|
+
import { ToolingDatabase, ToolingTarget } from "./types.cjs";
|
|
5
|
+
import "../database/index.cjs";
|
|
6
|
+
import { AggregateBatching } from "@hot-updater/plugin-core";
|
|
7
|
+
import { DatabaseAdapter } from "@hot-updater/plugin-core/internal";
|
|
8
|
+
//#region src/db/coreDatabase.d.ts
|
|
9
|
+
/** Core's tables: the tables every provider's tooling creates. */
|
|
10
|
+
declare const coreSchema: ResolvedSchema;
|
|
11
|
+
/** The settings rows a provider's database is fenced by. */
|
|
12
|
+
declare const coreSettings: SchemaSettings;
|
|
13
|
+
/** What `hot-updater db` creates for a server without plugins. */
|
|
14
|
+
declare const coreTarget: ToolingTarget;
|
|
15
|
+
/** A plugin as the tooling reads it: its id, its tables, and their version. */
|
|
16
|
+
interface PluginTables {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly schemaVersion: string;
|
|
19
|
+
readonly schema: Readonly<Record<string, ModelShape>>;
|
|
20
|
+
/** `false` keeps the declared table names instead of prefixing them with the id. */
|
|
21
|
+
readonly namespace?: false;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* What `hot-updater db` creates for a server's plugins: core's tables, then
|
|
25
|
+
* each plugin's tables with its `schema.<id>` settings row.
|
|
26
|
+
*/
|
|
27
|
+
declare const toolingTargetOf: (plugins: readonly PluginTables[]) => ToolingTarget;
|
|
28
|
+
/**
|
|
29
|
+
* Creates core's tables and those of `plugins`, then writes their settings
|
|
30
|
+
* rows: what a provider's setup runs for the plugins its server runs.
|
|
31
|
+
*/
|
|
32
|
+
declare const migrateCoreSchema: (adapter: DatabaseAdapter, name: string, plugins?: readonly PluginTables[]) => Promise<void>;
|
|
33
|
+
interface EngineDatabaseOptions {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly adapter: DatabaseAdapter;
|
|
36
|
+
/**
|
|
37
|
+
* Purges a CDN's copies of the cacheable client routes. Core calls it after
|
|
38
|
+
* a committed write that changes what those routes answer, since only core
|
|
39
|
+
* knows which of its tables they read.
|
|
40
|
+
*/
|
|
41
|
+
readonly onCachedRoutesChange?: () => Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Batches aggregates declared `batched`, for stores that bill each write;
|
|
44
|
+
* `false` or absent commits them with each transaction.
|
|
45
|
+
*/
|
|
46
|
+
readonly aggregateBatching?: AggregateBatching | false;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A provider's database on the storage engine: its adapter behind the schema
|
|
50
|
+
* fence, which checks core's settings rows before the first read or write
|
|
51
|
+
* and names `hot-updater db migrate` when they are missing or stale. When the
|
|
52
|
+
* adapter creates its own tables, `hot-updater db migrate` creates core's
|
|
53
|
+
* tables and the server's plugin tables, then writes their settings rows.
|
|
54
|
+
*/
|
|
55
|
+
declare const createEngineDatabase: ({ name, adapter, onCachedRoutesChange, aggregateBatching }: EngineDatabaseOptions) => ToolingDatabase;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { EngineDatabaseOptions, PluginTables, coreSchema, coreSettings, coreTarget, createEngineDatabase, migrateCoreSchema, toolingTargetOf };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SchemaSettings } from "../database/fence.mjs";
|
|
2
|
+
import { ModelShape } from "../database/definitions.mjs";
|
|
3
|
+
import { ResolvedSchema } from "../database/resolveSchema.mjs";
|
|
4
|
+
import { ToolingDatabase, ToolingTarget } from "./types.mjs";
|
|
5
|
+
import "../database/index.mjs";
|
|
6
|
+
import { AggregateBatching } from "@hot-updater/plugin-core";
|
|
7
|
+
import { DatabaseAdapter } from "@hot-updater/plugin-core/internal";
|
|
8
|
+
//#region src/db/coreDatabase.d.ts
|
|
9
|
+
/** Core's tables: the tables every provider's tooling creates. */
|
|
10
|
+
declare const coreSchema: ResolvedSchema;
|
|
11
|
+
/** The settings rows a provider's database is fenced by. */
|
|
12
|
+
declare const coreSettings: SchemaSettings;
|
|
13
|
+
/** What `hot-updater db` creates for a server without plugins. */
|
|
14
|
+
declare const coreTarget: ToolingTarget;
|
|
15
|
+
/** A plugin as the tooling reads it: its id, its tables, and their version. */
|
|
16
|
+
interface PluginTables {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly schemaVersion: string;
|
|
19
|
+
readonly schema: Readonly<Record<string, ModelShape>>;
|
|
20
|
+
/** `false` keeps the declared table names instead of prefixing them with the id. */
|
|
21
|
+
readonly namespace?: false;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* What `hot-updater db` creates for a server's plugins: core's tables, then
|
|
25
|
+
* each plugin's tables with its `schema.<id>` settings row.
|
|
26
|
+
*/
|
|
27
|
+
declare const toolingTargetOf: (plugins: readonly PluginTables[]) => ToolingTarget;
|
|
28
|
+
/**
|
|
29
|
+
* Creates core's tables and those of `plugins`, then writes their settings
|
|
30
|
+
* rows: what a provider's setup runs for the plugins its server runs.
|
|
31
|
+
*/
|
|
32
|
+
declare const migrateCoreSchema: (adapter: DatabaseAdapter, name: string, plugins?: readonly PluginTables[]) => Promise<void>;
|
|
33
|
+
interface EngineDatabaseOptions {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly adapter: DatabaseAdapter;
|
|
36
|
+
/**
|
|
37
|
+
* Purges a CDN's copies of the cacheable client routes. Core calls it after
|
|
38
|
+
* a committed write that changes what those routes answer, since only core
|
|
39
|
+
* knows which of its tables they read.
|
|
40
|
+
*/
|
|
41
|
+
readonly onCachedRoutesChange?: () => Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Batches aggregates declared `batched`, for stores that bill each write;
|
|
44
|
+
* `false` or absent commits them with each transaction.
|
|
45
|
+
*/
|
|
46
|
+
readonly aggregateBatching?: AggregateBatching | false;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A provider's database on the storage engine: its adapter behind the schema
|
|
50
|
+
* fence, which checks core's settings rows before the first read or write
|
|
51
|
+
* and names `hot-updater db migrate` when they are missing or stale. When the
|
|
52
|
+
* adapter creates its own tables, `hot-updater db migrate` creates core's
|
|
53
|
+
* tables and the server's plugin tables, then writes their settings rows.
|
|
54
|
+
*/
|
|
55
|
+
declare const createEngineDatabase: ({ name, adapter, onCachedRoutesChange, aggregateBatching }: EngineDatabaseOptions) => ToolingDatabase;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { EngineDatabaseOptions, PluginTables, coreSchema, coreSettings, coreTarget, createEngineDatabase, migrateCoreSchema, toolingTargetOf };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { resolveSchema } from "../database/resolveSchema.mjs";
|
|
2
|
+
import { HOT_UPDATER_SCHEMA_VERSION, coreModule } from "../core/schema.mjs";
|
|
3
|
+
import { ENGINE_SCHEMA_KEY, isMissingSchemaError, readSettings, withSchemaFence } from "../database/fence.mjs";
|
|
4
|
+
import { migrateSchema } from "./schemaSettings.mjs";
|
|
5
|
+
import { createEngineMigrator } from "./engineMigrator.mjs";
|
|
6
|
+
//#region src/db/coreDatabase.ts
|
|
7
|
+
/** Core's tables: the tables every provider's tooling creates. */
|
|
8
|
+
const coreSchema = resolveSchema([coreModule]);
|
|
9
|
+
/** The settings rows a provider's database is fenced by. */
|
|
10
|
+
const coreSettings = {
|
|
11
|
+
[ENGINE_SCHEMA_KEY]: "1",
|
|
12
|
+
"schema.core": HOT_UPDATER_SCHEMA_VERSION
|
|
13
|
+
};
|
|
14
|
+
/** What `hot-updater db` creates for a server without plugins. */
|
|
15
|
+
const coreTarget = {
|
|
16
|
+
schema: coreSchema,
|
|
17
|
+
settings: coreSettings
|
|
18
|
+
};
|
|
19
|
+
/** Each plugin's `schema.<id>` settings row. */
|
|
20
|
+
const pluginSettings = (plugins) => Object.fromEntries(plugins.map(({ id, schemaVersion }) => [`schema.${id}`, schemaVersion]));
|
|
21
|
+
/** A plugin's schema as the engine resolves it: prefixed by its id unless it keeps its names. */
|
|
22
|
+
const pluginModule = ({ id, schema, namespace }) => ({
|
|
23
|
+
id,
|
|
24
|
+
schema,
|
|
25
|
+
...namespace === false ? {} : { namespace: id }
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* What `hot-updater db` creates for a server's plugins: core's tables, then
|
|
29
|
+
* each plugin's tables with its `schema.<id>` settings row.
|
|
30
|
+
*/
|
|
31
|
+
const toolingTargetOf = (plugins) => plugins.length === 0 ? coreTarget : {
|
|
32
|
+
schema: resolveSchema([coreModule, ...plugins.map(pluginModule)]),
|
|
33
|
+
settings: {
|
|
34
|
+
...coreSettings,
|
|
35
|
+
...pluginSettings(plugins)
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Creates core's tables and those of `plugins`, then writes their settings
|
|
40
|
+
* rows: what a provider's setup runs for the plugins its server runs.
|
|
41
|
+
*/
|
|
42
|
+
const migrateCoreSchema = (adapter, name, plugins = []) => {
|
|
43
|
+
const { schema, settings } = toolingTargetOf(plugins);
|
|
44
|
+
return migrateSchema(adapter, name, schema.tables, settings);
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* A provider's database on the storage engine: its adapter behind the schema
|
|
48
|
+
* fence, which checks core's settings rows before the first read or write
|
|
49
|
+
* and names `hot-updater db migrate` when they are missing or stale. When the
|
|
50
|
+
* adapter creates its own tables, `hot-updater db migrate` creates core's
|
|
51
|
+
* tables and the server's plugin tables, then writes their settings rows.
|
|
52
|
+
*/
|
|
53
|
+
const createEngineDatabase = ({ name, adapter, onCachedRoutesChange, aggregateBatching }) => {
|
|
54
|
+
const fenced = withSchemaFence(adapter, name, coreSettings);
|
|
55
|
+
const createMigrator = ({ schema, settings } = coreTarget) => createEngineMigrator({
|
|
56
|
+
adapterName: name,
|
|
57
|
+
adapter,
|
|
58
|
+
schema,
|
|
59
|
+
settings,
|
|
60
|
+
readSettings: async () => {
|
|
61
|
+
const rows = await readSettings(adapter, Object.keys(settings)).catch((error) => {
|
|
62
|
+
if (isMissingSchemaError(error)) return [];
|
|
63
|
+
throw error;
|
|
64
|
+
});
|
|
65
|
+
return new Map(rows.flatMap((row) => row === null ? [] : [[String(row.key), row.value]]));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
name,
|
|
70
|
+
adapter: fenced,
|
|
71
|
+
...onCachedRoutesChange === void 0 ? {} : { onCachedRoutesChange },
|
|
72
|
+
...aggregateBatching ? { aggregateBatching } : {},
|
|
73
|
+
...adapter.dispose === void 0 ? {} : { dispose: () => adapter.dispose() },
|
|
74
|
+
...adapter.migrations === void 0 ? {} : { createMigrator }
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
//#endregion
|
|
78
|
+
export { coreSchema, coreSettings, coreTarget, createEngineDatabase, migrateCoreSchema, pluginModule, pluginSettings, toolingTargetOf };
|
package/dist/db/index.cjs
CHANGED
|
@@ -3,18 +3,22 @@ const require_baseCandidates = require("../core/baseCandidates.cjs");
|
|
|
3
3
|
const require_api = require("../core/api.cjs");
|
|
4
4
|
const require_fence = require("../database/fence.cjs");
|
|
5
5
|
const require_engineSql = require("./engineSql.cjs");
|
|
6
|
+
const require_clientPlugins = require("../assembly/clientPlugins.cjs");
|
|
6
7
|
const require_version = require("../version.cjs");
|
|
7
8
|
const require_createHotUpdaterCore = require("../createHotUpdaterCore.cjs");
|
|
8
9
|
const require_databasePlugins = require("../assembly/databasePlugins.cjs");
|
|
10
|
+
const require_pluginCli = require("../assembly/pluginCli.cjs");
|
|
9
11
|
//#region src/db/index.ts
|
|
10
12
|
const getDBMetadata = (hotUpdater) => {
|
|
11
13
|
const metadata = require_createHotUpdaterCore.getHotUpdaterCoreMetadata(hotUpdater);
|
|
12
14
|
if (!metadata) throw new Error("Database tooling requires a hotUpdater instance created by @hot-updater/server.");
|
|
13
15
|
return metadata;
|
|
14
16
|
};
|
|
17
|
+
/** A server's plugins as configured, whose commands the CLI adds. */
|
|
18
|
+
const serverPluginsOf = (hotUpdater) => getDBMetadata(hotUpdater).plugins;
|
|
15
19
|
/** Whether `hot-updater db generate` writes schema files for a server's database. */
|
|
16
20
|
const generatesSchema = (hotUpdater) => getDBMetadata(hotUpdater).database.generateSchema !== void 0;
|
|
17
|
-
/** The migrator for a server's database:
|
|
21
|
+
/** The migrator for a server's database: core's tables and its plugins' tables. */
|
|
18
22
|
function createMigrator(hotUpdater) {
|
|
19
23
|
const { database, target } = getDBMetadata(hotUpdater);
|
|
20
24
|
if (database.createMigrator === void 0) throw new Error(database.generateSchema === void 0 ? `The ${database.name} database has no migrator; its provider applies the schema.` : `The ${database.name} database applies its schema from migration files: run \`hot-updater db generate\`, then apply the file with the provider's tooling.`);
|
|
@@ -29,12 +33,18 @@ function generateSchema(hotUpdater, ...args) {
|
|
|
29
33
|
//#endregion
|
|
30
34
|
exports.HOT_UPDATER_SERVER_VERSION = require_version.HOT_UPDATER_SERVER_VERSION;
|
|
31
35
|
exports.HotUpdaterSchemaMigrationRequiredError = require_fence.HotUpdaterSchemaMigrationRequiredError;
|
|
36
|
+
exports.clientAuthOf = require_pluginCli.clientAuthOf;
|
|
37
|
+
exports.clientPluginsOf = require_clientPlugins.clientPluginsOf;
|
|
32
38
|
exports.createDatabaseCoreApi = require_api.createDatabaseCoreApi;
|
|
33
39
|
exports.createDatabasePluginApis = require_databasePlugins.createDatabasePluginApis;
|
|
34
40
|
exports.createMeasuredDatabase = require_databasePlugins.createMeasuredDatabase;
|
|
35
41
|
exports.createMigrator = createMigrator;
|
|
42
|
+
exports.generateClientCredential = require_pluginCli.generateClientCredential;
|
|
36
43
|
exports.generateEngineSql = require_engineSql.generateEngineSql;
|
|
37
44
|
exports.generateSchema = generateSchema;
|
|
38
45
|
exports.generatesSchema = generatesSchema;
|
|
46
|
+
exports.pluginCommandsOf = require_pluginCli.pluginCommandsOf;
|
|
47
|
+
exports.provisionClientCredential = require_pluginCli.provisionClientCredential;
|
|
48
|
+
exports.serverPluginsOf = serverPluginsOf;
|
|
39
49
|
exports.settingsStatements = require_engineSql.settingsStatements;
|
|
40
50
|
exports.targetBaseCandidateKey = require_baseCandidates.targetBaseCandidateKey;
|
package/dist/db/index.d.cts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { HotUpdaterSchemaMigrationRequiredError } from "../database/fence.cjs";
|
|
2
2
|
import { DatabaseTooling, Migrator, SchemaGenerator, ToolingDatabase, ToolingTarget } from "./types.cjs";
|
|
3
|
+
import { AnyHotUpdaterPlugin } from "../plugins/definePlugin.cjs";
|
|
3
4
|
import { CoreApi, createDatabaseCoreApi } from "../core/api.cjs";
|
|
4
5
|
import { MeasuredDatabase, MeasuredDatabaseOptions, createDatabasePluginApis, createMeasuredDatabase } from "../assembly/databasePlugins.cjs";
|
|
6
|
+
import { ClientPluginSpec, clientPluginsOf } from "../assembly/clientPlugins.cjs";
|
|
7
|
+
import { ClientAuthSpec, ClientCredentialSpec, PluginCommandEntry, ProvisionedClientCredential, clientAuthOf, generateClientCredential, pluginCommandsOf, provisionClientCredential } from "../assembly/pluginCli.cjs";
|
|
5
8
|
import { targetBaseCandidateKey } from "../core/baseCandidates.cjs";
|
|
6
9
|
import { EngineSqlOptions, generateEngineSql, settingsStatements } from "./engineSql.cjs";
|
|
7
10
|
import { HOT_UPDATER_SERVER_VERSION } from "../version.cjs";
|
|
@@ -9,10 +12,12 @@ import { HOT_UPDATER_SERVER_VERSION } from "../version.cjs";
|
|
|
9
12
|
type HotUpdaterDBTarget = {
|
|
10
13
|
readonly adapterName: string;
|
|
11
14
|
};
|
|
15
|
+
/** A server's plugins as configured, whose commands the CLI adds. */
|
|
16
|
+
declare const serverPluginsOf: (hotUpdater: HotUpdaterDBTarget) => readonly AnyHotUpdaterPlugin[];
|
|
12
17
|
/** Whether `hot-updater db generate` writes schema files for a server's database. */
|
|
13
18
|
declare const generatesSchema: (hotUpdater: HotUpdaterDBTarget) => boolean;
|
|
14
|
-
/** The migrator for a server's database:
|
|
19
|
+
/** The migrator for a server's database: core's tables and its plugins' tables. */
|
|
15
20
|
declare function createMigrator(hotUpdater: HotUpdaterDBTarget): Migrator;
|
|
16
21
|
declare function generateSchema(hotUpdater: HotUpdaterDBTarget, ...args: Parameters<SchemaGenerator>): ReturnType<SchemaGenerator>;
|
|
17
22
|
//#endregion
|
|
18
|
-
export { type CoreApi, type DatabaseTooling, type EngineSqlOptions, HOT_UPDATER_SERVER_VERSION, HotUpdaterDBTarget, HotUpdaterSchemaMigrationRequiredError, type MeasuredDatabase, type MeasuredDatabaseOptions, type Migrator, type SchemaGenerator, type ToolingDatabase, type ToolingTarget, createDatabaseCoreApi, createDatabasePluginApis, createMeasuredDatabase, createMigrator, generateEngineSql, generateSchema, generatesSchema, settingsStatements, targetBaseCandidateKey };
|
|
23
|
+
export { type ClientAuthSpec, type ClientCredentialSpec, type ClientPluginSpec, type CoreApi, type DatabaseTooling, type EngineSqlOptions, HOT_UPDATER_SERVER_VERSION, HotUpdaterDBTarget, HotUpdaterSchemaMigrationRequiredError, type MeasuredDatabase, type MeasuredDatabaseOptions, type Migrator, type PluginCommandEntry, type ProvisionedClientCredential, type SchemaGenerator, type ToolingDatabase, type ToolingTarget, clientAuthOf, clientPluginsOf, createDatabaseCoreApi, createDatabasePluginApis, createMeasuredDatabase, createMigrator, generateClientCredential, generateEngineSql, generateSchema, generatesSchema, pluginCommandsOf, provisionClientCredential, serverPluginsOf, settingsStatements, targetBaseCandidateKey };
|
package/dist/db/index.d.mts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { HotUpdaterSchemaMigrationRequiredError } from "../database/fence.mjs";
|
|
2
2
|
import { DatabaseTooling, Migrator, SchemaGenerator, ToolingDatabase, ToolingTarget } from "./types.mjs";
|
|
3
|
+
import { AnyHotUpdaterPlugin } from "../plugins/definePlugin.mjs";
|
|
3
4
|
import { CoreApi, createDatabaseCoreApi } from "../core/api.mjs";
|
|
4
5
|
import { MeasuredDatabase, MeasuredDatabaseOptions, createDatabasePluginApis, createMeasuredDatabase } from "../assembly/databasePlugins.mjs";
|
|
6
|
+
import { ClientPluginSpec, clientPluginsOf } from "../assembly/clientPlugins.mjs";
|
|
7
|
+
import { ClientAuthSpec, ClientCredentialSpec, PluginCommandEntry, ProvisionedClientCredential, clientAuthOf, generateClientCredential, pluginCommandsOf, provisionClientCredential } from "../assembly/pluginCli.mjs";
|
|
5
8
|
import { targetBaseCandidateKey } from "../core/baseCandidates.mjs";
|
|
6
9
|
import { EngineSqlOptions, generateEngineSql, settingsStatements } from "./engineSql.mjs";
|
|
7
10
|
import { HOT_UPDATER_SERVER_VERSION } from "../version.mjs";
|
|
@@ -9,10 +12,12 @@ import { HOT_UPDATER_SERVER_VERSION } from "../version.mjs";
|
|
|
9
12
|
type HotUpdaterDBTarget = {
|
|
10
13
|
readonly adapterName: string;
|
|
11
14
|
};
|
|
15
|
+
/** A server's plugins as configured, whose commands the CLI adds. */
|
|
16
|
+
declare const serverPluginsOf: (hotUpdater: HotUpdaterDBTarget) => readonly AnyHotUpdaterPlugin[];
|
|
12
17
|
/** Whether `hot-updater db generate` writes schema files for a server's database. */
|
|
13
18
|
declare const generatesSchema: (hotUpdater: HotUpdaterDBTarget) => boolean;
|
|
14
|
-
/** The migrator for a server's database:
|
|
19
|
+
/** The migrator for a server's database: core's tables and its plugins' tables. */
|
|
15
20
|
declare function createMigrator(hotUpdater: HotUpdaterDBTarget): Migrator;
|
|
16
21
|
declare function generateSchema(hotUpdater: HotUpdaterDBTarget, ...args: Parameters<SchemaGenerator>): ReturnType<SchemaGenerator>;
|
|
17
22
|
//#endregion
|
|
18
|
-
export { type CoreApi, type DatabaseTooling, type EngineSqlOptions, HOT_UPDATER_SERVER_VERSION, HotUpdaterDBTarget, HotUpdaterSchemaMigrationRequiredError, type MeasuredDatabase, type MeasuredDatabaseOptions, type Migrator, type SchemaGenerator, type ToolingDatabase, type ToolingTarget, createDatabaseCoreApi, createDatabasePluginApis, createMeasuredDatabase, createMigrator, generateEngineSql, generateSchema, generatesSchema, settingsStatements, targetBaseCandidateKey };
|
|
23
|
+
export { type ClientAuthSpec, type ClientCredentialSpec, type ClientPluginSpec, type CoreApi, type DatabaseTooling, type EngineSqlOptions, HOT_UPDATER_SERVER_VERSION, HotUpdaterDBTarget, HotUpdaterSchemaMigrationRequiredError, type MeasuredDatabase, type MeasuredDatabaseOptions, type Migrator, type PluginCommandEntry, type ProvisionedClientCredential, type SchemaGenerator, type ToolingDatabase, type ToolingTarget, clientAuthOf, clientPluginsOf, createDatabaseCoreApi, createDatabasePluginApis, createMeasuredDatabase, createMigrator, generateClientCredential, generateEngineSql, generateSchema, generatesSchema, pluginCommandsOf, provisionClientCredential, serverPluginsOf, settingsStatements, targetBaseCandidateKey };
|
package/dist/db/index.mjs
CHANGED
|
@@ -2,18 +2,22 @@ import { targetBaseCandidateKey } from "../core/baseCandidates.mjs";
|
|
|
2
2
|
import { createDatabaseCoreApi } from "../core/api.mjs";
|
|
3
3
|
import { HotUpdaterSchemaMigrationRequiredError } from "../database/fence.mjs";
|
|
4
4
|
import { generateEngineSql, settingsStatements } from "./engineSql.mjs";
|
|
5
|
+
import { clientPluginsOf } from "../assembly/clientPlugins.mjs";
|
|
5
6
|
import { HOT_UPDATER_SERVER_VERSION } from "../version.mjs";
|
|
6
7
|
import { getHotUpdaterCoreMetadata } from "../createHotUpdaterCore.mjs";
|
|
7
8
|
import { createDatabasePluginApis, createMeasuredDatabase } from "../assembly/databasePlugins.mjs";
|
|
9
|
+
import { clientAuthOf, generateClientCredential, pluginCommandsOf, provisionClientCredential } from "../assembly/pluginCli.mjs";
|
|
8
10
|
//#region src/db/index.ts
|
|
9
11
|
const getDBMetadata = (hotUpdater) => {
|
|
10
12
|
const metadata = getHotUpdaterCoreMetadata(hotUpdater);
|
|
11
13
|
if (!metadata) throw new Error("Database tooling requires a hotUpdater instance created by @hot-updater/server.");
|
|
12
14
|
return metadata;
|
|
13
15
|
};
|
|
16
|
+
/** A server's plugins as configured, whose commands the CLI adds. */
|
|
17
|
+
const serverPluginsOf = (hotUpdater) => getDBMetadata(hotUpdater).plugins;
|
|
14
18
|
/** Whether `hot-updater db generate` writes schema files for a server's database. */
|
|
15
19
|
const generatesSchema = (hotUpdater) => getDBMetadata(hotUpdater).database.generateSchema !== void 0;
|
|
16
|
-
/** The migrator for a server's database:
|
|
20
|
+
/** The migrator for a server's database: core's tables and its plugins' tables. */
|
|
17
21
|
function createMigrator(hotUpdater) {
|
|
18
22
|
const { database, target } = getDBMetadata(hotUpdater);
|
|
19
23
|
if (database.createMigrator === void 0) throw new Error(database.generateSchema === void 0 ? `The ${database.name} database has no migrator; its provider applies the schema.` : `The ${database.name} database applies its schema from migration files: run \`hot-updater db generate\`, then apply the file with the provider's tooling.`);
|
|
@@ -26,4 +30,4 @@ function generateSchema(hotUpdater, ...args) {
|
|
|
26
30
|
return database.generateSchema(version, name, target);
|
|
27
31
|
}
|
|
28
32
|
//#endregion
|
|
29
|
-
export { HOT_UPDATER_SERVER_VERSION, HotUpdaterSchemaMigrationRequiredError, createDatabaseCoreApi, createDatabasePluginApis, createMeasuredDatabase, createMigrator, generateEngineSql, generateSchema, generatesSchema, settingsStatements, targetBaseCandidateKey };
|
|
33
|
+
export { HOT_UPDATER_SERVER_VERSION, HotUpdaterSchemaMigrationRequiredError, clientAuthOf, clientPluginsOf, createDatabaseCoreApi, createDatabasePluginApis, createMeasuredDatabase, createMigrator, generateClientCredential, generateEngineSql, generateSchema, generatesSchema, pluginCommandsOf, provisionClientCredential, serverPluginsOf, settingsStatements, targetBaseCandidateKey };
|
package/dist/db/types.d.cts
CHANGED
|
@@ -52,7 +52,7 @@ interface Migrator {
|
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* The tables `db migrate` and `db generate` create and the settings rows they
|
|
55
|
-
* write:
|
|
55
|
+
* write: core's, and those of each plugin the server runs.
|
|
56
56
|
*/
|
|
57
57
|
interface ToolingTarget {
|
|
58
58
|
readonly schema: ResolvedSchema;
|
|
@@ -64,8 +64,8 @@ type SchemaGenerator = (version: string | "latest", name?: string, target?: Tool
|
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
66
|
* What `hot-updater db generate` and `db migrate` run for a provider's
|
|
67
|
-
* database, beside the database itself. Without a target they cover
|
|
68
|
-
*
|
|
67
|
+
* database, beside the database itself. Without a target they cover core's
|
|
68
|
+
* tables.
|
|
69
69
|
*/
|
|
70
70
|
interface DatabaseTooling {
|
|
71
71
|
readonly provider?: ORMProvider;
|
package/dist/db/types.d.mts
CHANGED
|
@@ -52,7 +52,7 @@ interface Migrator {
|
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* The tables `db migrate` and `db generate` create and the settings rows they
|
|
55
|
-
* write:
|
|
55
|
+
* write: core's, and those of each plugin the server runs.
|
|
56
56
|
*/
|
|
57
57
|
interface ToolingTarget {
|
|
58
58
|
readonly schema: ResolvedSchema;
|
|
@@ -64,8 +64,8 @@ type SchemaGenerator = (version: string | "latest", name?: string, target?: Tool
|
|
|
64
64
|
};
|
|
65
65
|
/**
|
|
66
66
|
* What `hot-updater db generate` and `db migrate` run for a provider's
|
|
67
|
-
* database, beside the database itself. Without a target they cover
|
|
68
|
-
*
|
|
67
|
+
* database, beside the database itself. Without a target they cover core's
|
|
68
|
+
* tables.
|
|
69
69
|
*/
|
|
70
70
|
interface DatabaseTooling {
|
|
71
71
|
readonly provider?: ORMProvider;
|
package/dist/handler.cjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const require_fence = require("./database/fence.cjs");
|
|
2
|
-
const
|
|
3
|
-
const require_assemblePlugins = require("./assembly/assemblePlugins.cjs");
|
|
2
|
+
const require_configError = require("./assembly/configError.cjs");
|
|
4
3
|
const require_handlerErrors = require("./handlerErrors.cjs");
|
|
5
4
|
const require_handlerAdminRoutes = require("./handlerAdminRoutes.cjs");
|
|
6
5
|
const require_handlerReleaseCatalogRoutes = require("./handlerReleaseCatalogRoutes.cjs");
|
|
@@ -85,8 +84,6 @@ function createHotUpdaterHandlers({ api, clientPolicy, downloadStorageObject, en
|
|
|
85
84
|
...require_handlerVersionRoutes.createVersionRouteHandlers(plugins),
|
|
86
85
|
...require_handlerReleaseCatalogRoutes.createReleaseCatalogRouteHandlers(),
|
|
87
86
|
...require_handlerAdminRoutes.createAdminRouteHandlers(),
|
|
88
|
-
...Object.fromEntries(require_routes.INSIGHTS_ROUTES.map(({ handler }) => [handler, require_routes.insightsDisabled])),
|
|
89
|
-
appendBundleEvent: require_routes.createDroppedEventHandler(),
|
|
90
87
|
...downloadStorageObject === void 0 ? {} : { downloadStorageObject: createDownloadStorageRouteHandler(downloadStorageObject) }
|
|
91
88
|
};
|
|
92
89
|
const routes = [];
|
|
@@ -94,7 +91,7 @@ function createHotUpdaterHandlers({ api, clientPolicy, downloadStorageObject, en
|
|
|
94
91
|
const mount = (router, admin) => (method, path, handler) => {
|
|
95
92
|
const shape = `${admin ? "admin" : "client"} ${method} ${path.replaceAll(/:[^/]+/gu, ":")}`;
|
|
96
93
|
const taken = shapes.get(shape);
|
|
97
|
-
if (taken !== void 0) throw new
|
|
94
|
+
if (taken !== void 0) throw new require_configError.HotUpdaterConfigError(`${handler} (${method} ${path}) collides with ${taken} on handlers.${admin ? "admin" : "client"}.`);
|
|
98
95
|
shapes.set(shape, handler);
|
|
99
96
|
require_internalRouter.addRoute(router, method, path, handler);
|
|
100
97
|
routes.push({
|
|
@@ -103,13 +100,6 @@ function createHotUpdaterHandlers({ api, clientPolicy, downloadStorageObject, en
|
|
|
103
100
|
access: admin ? "admin" : PUBLIC_CLIENT_ROUTES.has(handler) ? "public" : "client"
|
|
104
101
|
});
|
|
105
102
|
};
|
|
106
|
-
/** The Insights routes no plugin endpoint serves, which answer that Insights is off. */
|
|
107
|
-
const mountInsights = (access, add) => {
|
|
108
|
-
for (const route of require_routes.INSIGHTS_ROUTES) {
|
|
109
|
-
const served = endpoints.some((endpoint) => endpoint.access === route.access && endpoint.method === route.method && endpoint.path === route.path);
|
|
110
|
-
if (route.access === access && !served) add(route.method, route.path, route.handler);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
103
|
const clientRouter = require_internalRouter.createRouter();
|
|
114
104
|
const addClientRoute = mount(clientRouter, false);
|
|
115
105
|
addClientRoute("GET", "/version", "version");
|
|
@@ -117,12 +107,10 @@ function createHotUpdaterHandlers({ api, clientPolicy, downloadStorageObject, en
|
|
|
117
107
|
addClientRoute("GET", "/release-catalogs/app-version/:platform/:channelKey/:appVersion", "appVersionReleaseCatalog");
|
|
118
108
|
addClientRoute("GET", "/release-catalogs/fingerprint/:platform/:channelKey/:fingerprintHash", "fingerprintReleaseCatalog");
|
|
119
109
|
addClientRoute("GET", "/artifacts/v1/:targetBundleId/from/:currentBundleId", "artifactV1");
|
|
120
|
-
mountInsights("client", addClientRoute);
|
|
121
110
|
const adminRouter = require_internalRouter.createRouter();
|
|
122
111
|
const addAdminRoute = mount(adminRouter, true);
|
|
123
112
|
addAdminRoute("GET", "/version", "adminVersion");
|
|
124
113
|
for (const route of require_handlerAdminRoutes.ADMIN_ROUTES) addAdminRoute(route.method, route.path, route.handler);
|
|
125
|
-
mountInsights("admin", addAdminRoute);
|
|
126
114
|
for (const endpoint of endpoints) {
|
|
127
115
|
const name = `plugin ${endpoint.plugin}: ${endpoint.method} ${endpoint.path}`;
|
|
128
116
|
routeHandlers[name] = (params, request) => endpoint.handler(request, params);
|