@hot-updater/server 1.0.0-rc.16 → 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 -3
- package/dist/db/index.d.cts +7 -3
- package/dist/db/index.d.mts +7 -3
- package/dist/db/index.mjs +6 -3
- package/dist/db/types.d.cts +3 -3
- package/dist/db/types.d.mts +3 -3
- package/dist/diff.cjs +3 -0
- package/dist/diff.d.cts +2 -0
- package/dist/diff.d.mts +2 -0
- package/dist/diff.mjs +2 -0
- 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 +18 -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 -2
- package/src/db/pluginTables.spec.ts +57 -27
- package/src/db/types.ts +3 -3
- package/src/diff.ts +6 -0
- 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
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { HotUpdaterConfigError } from "./configError.mjs";
|
|
2
|
+
import { clientPluginsOf } from "./clientPlugins.mjs";
|
|
3
|
+
import { assemblePlugins } from "./assemblePlugins.mjs";
|
|
4
|
+
import { createDatabasePluginApis } from "./databasePlugins.mjs";
|
|
5
|
+
import { createMemoryAdapter } from "@hot-updater/plugin-core/internal";
|
|
6
|
+
//#region src/assembly/pluginCli.ts
|
|
7
|
+
const COMMAND_NAME = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/u;
|
|
8
|
+
const ARGUMENT_NAME = /^[A-Za-z][A-Za-z0-9]*$/u;
|
|
9
|
+
const RESERVED_ARGUMENT = "configPath";
|
|
10
|
+
const fail = (message) => {
|
|
11
|
+
throw new HotUpdaterConfigError(message);
|
|
12
|
+
};
|
|
13
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
|
+
const pluginsOf = (value) => Array.isArray(value) ? value.filter(isRecord) : fail("plugins must be an array of plugins.");
|
|
15
|
+
const checkCommand = (plugin, value, path) => {
|
|
16
|
+
const at = `Plugin "${plugin}" command "${[...path, isRecord(value) ? String(value.name) : "?"].join(" ")}"`;
|
|
17
|
+
if (!isRecord(value) || typeof value.name !== "string" || !COMMAND_NAME.test(value.name) || typeof value.description !== "string") return fail(`${at} needs a name of lowercase words joined by hyphens and a description.`);
|
|
18
|
+
const command = value;
|
|
19
|
+
if (typeof command.run === "function" === (command.commands !== void 0)) fail(`${at} needs either subcommands or run, not both.`);
|
|
20
|
+
const names = /* @__PURE__ */ new Set();
|
|
21
|
+
for (const argument of command.arguments ?? []) {
|
|
22
|
+
if (!isRecord(argument) || typeof argument.name !== "string" || !ARGUMENT_NAME.test(argument.name) || argument.name === RESERVED_ARGUMENT || names.has(argument.name) || typeof argument.description !== "string") fail(`${at} has an argument that needs a unique camelCase name other than "${RESERVED_ARGUMENT}" and a description.`);
|
|
23
|
+
names.add(argument.name);
|
|
24
|
+
}
|
|
25
|
+
for (const option of command.options ?? []) if (!isRecord(option) || typeof option.flags !== "string" || !option.flags.includes("--") || typeof option.description !== "string") fail(`${at} has an option that needs --flags and a description.`);
|
|
26
|
+
if (command.commands !== void 0) {
|
|
27
|
+
if (!Array.isArray(command.commands) || command.commands.length === 0) fail(`${at} needs at least one subcommand.`);
|
|
28
|
+
const subcommands = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const subcommand of command.commands) {
|
|
30
|
+
const checked = checkCommand(plugin, subcommand, [...path, command.name]);
|
|
31
|
+
if (subcommands.has(checked.name)) fail(`${at} has two subcommands named "${checked.name}".`);
|
|
32
|
+
subcommands.add(checked.name);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return command;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The top-level commands the plugins add, each checked. Two plugins may not
|
|
39
|
+
* add the same command.
|
|
40
|
+
*/
|
|
41
|
+
const pluginCommandsOf = (plugins) => {
|
|
42
|
+
const entries = [];
|
|
43
|
+
for (const plugin of pluginsOf(plugins)) {
|
|
44
|
+
const commands = plugin.cli?.commands;
|
|
45
|
+
if (commands === void 0) continue;
|
|
46
|
+
const id = String(plugin.id);
|
|
47
|
+
if (!Array.isArray(commands)) fail(`Plugin "${id}" cli.commands must be an array.`);
|
|
48
|
+
for (const value of commands) {
|
|
49
|
+
const command = checkCommand(id, value, []);
|
|
50
|
+
const taken = entries.find((entry) => entry.command.name === command.name);
|
|
51
|
+
if (taken !== void 0) fail(`Plugins "${taken.plugin}" and "${id}" both add the command "${command.name}"; keep one.`);
|
|
52
|
+
entries.push({
|
|
53
|
+
plugin: id,
|
|
54
|
+
command
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return entries;
|
|
59
|
+
};
|
|
60
|
+
/** The clientAuth plugin's credential contribution, checked. */
|
|
61
|
+
const credentialOf = (plugins) => {
|
|
62
|
+
const plugin = pluginsOf(plugins).find(({ provides }) => provides?.clientAuth === true);
|
|
63
|
+
if (plugin === void 0) return void 0;
|
|
64
|
+
const id = String(plugin.id);
|
|
65
|
+
const credential = plugin.cli?.clientCredential;
|
|
66
|
+
if (!isRecord(credential) || typeof credential.label !== "string" || typeof credential.header !== "string" || typeof credential.env !== "string" || typeof credential.generate !== "function" || typeof credential.provision !== "function") return fail(`Plugin "${id}" provides clientAuth but no cli.clientCredential with a label, header, env, generate, and provision, so init cannot give an app its credential.`);
|
|
67
|
+
return {
|
|
68
|
+
plugin: id,
|
|
69
|
+
credential
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The client-route policy the plugins set: the plugin that provides
|
|
74
|
+
* clientAuth, the headers its decision reads, and the credential an app
|
|
75
|
+
* sends. Undefined when client routes are public. The plugins initialize on
|
|
76
|
+
* a throwaway in-memory database, since `varyHeaders` live on the instance.
|
|
77
|
+
*/
|
|
78
|
+
const clientAuthOf = (plugins) => {
|
|
79
|
+
const found = credentialOf(plugins);
|
|
80
|
+
if (found === void 0) return void 0;
|
|
81
|
+
const { clientAuth } = assemblePlugins(plugins, createMemoryAdapter());
|
|
82
|
+
const { label, header, env } = found.credential;
|
|
83
|
+
return {
|
|
84
|
+
plugin: found.plugin,
|
|
85
|
+
varyHeaders: (clientAuth?.varyHeaders ?? []).map((name) => name.toLowerCase()),
|
|
86
|
+
credential: {
|
|
87
|
+
label,
|
|
88
|
+
header: header.toLowerCase(),
|
|
89
|
+
env
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* A new client credential, made without a database, so tooling can save it
|
|
95
|
+
* before it registers it. Undefined when client routes are public.
|
|
96
|
+
*/
|
|
97
|
+
const generateClientCredential = (plugins) => credentialOf(plugins)?.credential.generate();
|
|
98
|
+
/**
|
|
99
|
+
* Provisions the credential an app sends to client routes, through the
|
|
100
|
+
* plugin that provides clientAuth, on the tables the server reads: a
|
|
101
|
+
* credential saved in `env` is registered again rather than replaced.
|
|
102
|
+
* Undefined when client routes are public.
|
|
103
|
+
*/
|
|
104
|
+
const provisionClientCredential = async (database, plugins, input) => {
|
|
105
|
+
const found = credentialOf(plugins);
|
|
106
|
+
if (found === void 0) return void 0;
|
|
107
|
+
const { label, header, env, provision } = found.credential;
|
|
108
|
+
const existing = input.env[env]?.trim();
|
|
109
|
+
const value = await provision(createDatabasePluginApis(database, plugins)[found.plugin], {
|
|
110
|
+
...existing ? { existing } : {},
|
|
111
|
+
name: input.name
|
|
112
|
+
});
|
|
113
|
+
return {
|
|
114
|
+
label,
|
|
115
|
+
header: header.toLowerCase(),
|
|
116
|
+
env,
|
|
117
|
+
value
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
//#endregion
|
|
121
|
+
export { clientAuthOf, clientPluginsOf, generateClientCredential, pluginCommandsOf, provisionClientCredential };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_coreDatabase = require("./db/coreDatabase.cjs");
|
|
2
|
+
const require_configError = require("./assembly/configError.cjs");
|
|
2
3
|
const require_assemblePlugins = require("./assembly/assemblePlugins.cjs");
|
|
3
4
|
const require_handler = require("./handler.cjs");
|
|
4
5
|
const require_storageAccess = require("./storageAccess.cjs");
|
|
@@ -15,21 +16,15 @@ const isAdapter = (value) => isRecord(value) && [
|
|
|
15
16
|
const databaseOf = (value) => {
|
|
16
17
|
if (isRecord(value) && typeof value.name === "string") {
|
|
17
18
|
if (isAdapter(value.adapter)) return value;
|
|
18
|
-
if ("core" in value && "fetchAdmin" in value) throw new
|
|
19
|
+
if ("core" in value && "fetchAdmin" in value) throw new require_configError.HotUpdaterConfigError("standaloneRepository reaches a server's admin API from the CLI and console. createHotUpdater needs the server's own database, such as kyselyAdapter(...).");
|
|
19
20
|
}
|
|
20
|
-
throw new
|
|
21
|
+
throw new require_configError.HotUpdaterConfigError("database must be a Hot Updater 1.0 database, such as kyselyAdapter(...) or postgres(...). Upgrade the provider package that created it.");
|
|
21
22
|
};
|
|
22
|
-
/**
|
|
23
|
-
const KEEP_INSIGHTS = "To keep Insights, which the release candidates ran by default, add insights() from @hot-updater/server/plugins/insights to plugins.";
|
|
24
|
-
/** `"public"`, or nothing; a `clientAccess` object names what replaced it. */
|
|
23
|
+
/** `"public"`, or nothing; a `clientAccess` object says what replaced it. */
|
|
25
24
|
const isPublic = (value) => {
|
|
26
25
|
if (value === void 0) return false;
|
|
27
26
|
if (value === "public") return true;
|
|
28
|
-
|
|
29
|
-
const type = value.type;
|
|
30
|
-
throw new require_assemblePlugins.HotUpdaterConfigError(type === "api-key" ? `clientAccess: { type: "api-key" } was removed in 1.0. Remove it and add apiKeys(${value.headerName === void 0 ? "" : `{ headerName: ${JSON.stringify(value.headerName)} }`}) from @hot-updater/server/plugins/api-keys to plugins, which protects client routes the same way. ${KEEP_INSIGHTS}` : `clientAccess objects were removed in 1.0. Use clientAccess: "public", or add apiKeys() from @hot-updater/server/plugins/api-keys to plugins. ${KEEP_INSIGHTS}`);
|
|
31
|
-
}
|
|
32
|
-
throw new require_assemblePlugins.HotUpdaterConfigError("clientAccess must be \"public\"; to protect client routes, add apiKeys() from @hot-updater/server/plugins/api-keys to plugins.");
|
|
27
|
+
throw new require_configError.HotUpdaterConfigError(isRecord(value) ? "clientAccess objects were removed in 1.0. Set clientAccess: \"public\", or add a plugin that provides clientAuth to plugins." : "clientAccess must be \"public\"; to protect client routes, add a plugin that provides clientAuth to plugins.");
|
|
33
28
|
};
|
|
34
29
|
const hotUpdaterCoreMetadata = Symbol.for("@hot-updater/server/core-metadata");
|
|
35
30
|
function getHotUpdaterCoreMetadata(hotUpdater) {
|
|
@@ -49,11 +44,12 @@ function createHotUpdater(options) {
|
|
|
49
44
|
readStorageText,
|
|
50
45
|
resolveFileUrl
|
|
51
46
|
},
|
|
52
|
-
...database.onCachedRoutesChange === void 0 ? {} : { onCachedRoutesChange: () => database.onCachedRoutesChange() }
|
|
47
|
+
...database.onCachedRoutesChange === void 0 ? {} : { onCachedRoutesChange: () => database.onCachedRoutesChange() },
|
|
48
|
+
...database.aggregateBatching === void 0 ? {} : { batching: database.aggregateBatching }
|
|
53
49
|
});
|
|
54
50
|
const clientAuth = plugins.clientAuth;
|
|
55
|
-
if (clientAuth !== void 0 && publicClients) throw new
|
|
56
|
-
if (clientAuth === void 0 && !publicClients) throw new
|
|
51
|
+
if (clientAuth !== void 0 && publicClients) throw new require_configError.HotUpdaterConfigError(`Plugin "${clientAuth.plugin}" provides clientAuth, so remove clientAccess.`);
|
|
52
|
+
if (clientAuth === void 0 && !publicClients) throw new require_configError.HotUpdaterConfigError("Set clientAccess to \"public\", or add a plugin that provides clientAuth.");
|
|
57
53
|
const clientPolicy = clientAuth === void 0 ? void 0 : {
|
|
58
54
|
varyHeaders: clientAuth.varyHeaders.map((header) => header.toLowerCase()),
|
|
59
55
|
authenticate: (request) => clientAuth.authenticate(request.headers)
|
|
@@ -69,13 +65,15 @@ function createHotUpdater(options) {
|
|
|
69
65
|
adapterName: database.name,
|
|
70
66
|
handlers,
|
|
71
67
|
core: plugins.core,
|
|
72
|
-
api: plugins.api
|
|
68
|
+
api: plugins.api,
|
|
69
|
+
flush: plugins.flush
|
|
73
70
|
};
|
|
74
71
|
Object.defineProperty(api, hotUpdaterCoreMetadata, {
|
|
75
72
|
enumerable: false,
|
|
76
73
|
value: {
|
|
77
74
|
database,
|
|
78
|
-
target:
|
|
75
|
+
target: require_coreDatabase.toolingTargetOf(options.plugins ?? []),
|
|
76
|
+
plugins: options.plugins ?? []
|
|
79
77
|
}
|
|
80
78
|
});
|
|
81
79
|
return api;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolingDatabase } from "./db/types.cjs";
|
|
2
|
-
import { CoreApi } from "./core/api.cjs";
|
|
3
2
|
import { AnyHotUpdaterPlugin, PluginApis } from "./plugins/definePlugin.cjs";
|
|
3
|
+
import { CoreApi } from "./core/api.cjs";
|
|
4
4
|
import { HotUpdaterHandlers } from "./handlerTypes.cjs";
|
|
5
5
|
import "./handler.cjs";
|
|
6
6
|
import { StoragePlugin } from "@hot-updater/plugin-core";
|
|
@@ -13,9 +13,16 @@ type RuntimeHotUpdaterAPI<TPlugins extends readonly AnyHotUpdaterPlugin[] = read
|
|
|
13
13
|
readonly api: PluginApis<TPlugins>;
|
|
14
14
|
/** The database's name, which `hot-updater db` commands read. */
|
|
15
15
|
readonly adapterName: string;
|
|
16
|
+
/**
|
|
17
|
+
* Applies aggregate changes the database batches that are still pending:
|
|
18
|
+
* this process's buffer, and the log rows no compaction has merged yet.
|
|
19
|
+
* A long-lived server with `aggregateBatching: { mode: "memory" }` calls
|
|
20
|
+
* it before it exits.
|
|
21
|
+
*/
|
|
22
|
+
readonly flush: () => Promise<void>;
|
|
16
23
|
};
|
|
17
24
|
type HotUpdaterAPI = RuntimeHotUpdaterAPI;
|
|
18
|
-
declare const REMOVED_CLIENT_ACCESS = "clientAccess objects were removed in 1.0: set clientAccess: \"public\", or add
|
|
25
|
+
declare const REMOVED_CLIENT_ACCESS = "clientAccess objects were removed in 1.0: set clientAccess: \"public\", or add a plugin that provides clientAuth";
|
|
19
26
|
/**
|
|
20
27
|
* A `clientAccess` object from before 1.0. Its `type` names the fix, so
|
|
21
28
|
* TypeScript reports it where the object is written.
|
|
@@ -57,7 +64,7 @@ type CreateHotUpdaterOptions<TPlugins extends readonly AnyHotUpdaterPlugin[] = r
|
|
|
57
64
|
readonly database: ToolingDatabase;
|
|
58
65
|
/** Storage implementations used to read provider-specific storage URIs. */
|
|
59
66
|
readonly storage?: readonly StoragePlugin[];
|
|
60
|
-
/**
|
|
67
|
+
/** The plugins the server runs; at most one provides clientAuth. Defaults to none. */
|
|
61
68
|
readonly plugins?: TPlugins;
|
|
62
69
|
} & ClientAccessRule<TPlugins>;
|
|
63
70
|
declare function createHotUpdater<const TPlugins extends readonly AnyHotUpdaterPlugin[] = readonly []>(options: CreateHotUpdaterOptions<TPlugins>): RuntimeHotUpdaterAPI<NoInfer<TPlugins>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ToolingDatabase } from "./db/types.mjs";
|
|
2
|
-
import { CoreApi } from "./core/api.mjs";
|
|
3
2
|
import { AnyHotUpdaterPlugin, PluginApis } from "./plugins/definePlugin.mjs";
|
|
3
|
+
import { CoreApi } from "./core/api.mjs";
|
|
4
4
|
import { HotUpdaterHandlers } from "./handlerTypes.mjs";
|
|
5
5
|
import "./handler.mjs";
|
|
6
6
|
import { StoragePlugin } from "@hot-updater/plugin-core";
|
|
@@ -13,9 +13,16 @@ type RuntimeHotUpdaterAPI<TPlugins extends readonly AnyHotUpdaterPlugin[] = read
|
|
|
13
13
|
readonly api: PluginApis<TPlugins>;
|
|
14
14
|
/** The database's name, which `hot-updater db` commands read. */
|
|
15
15
|
readonly adapterName: string;
|
|
16
|
+
/**
|
|
17
|
+
* Applies aggregate changes the database batches that are still pending:
|
|
18
|
+
* this process's buffer, and the log rows no compaction has merged yet.
|
|
19
|
+
* A long-lived server with `aggregateBatching: { mode: "memory" }` calls
|
|
20
|
+
* it before it exits.
|
|
21
|
+
*/
|
|
22
|
+
readonly flush: () => Promise<void>;
|
|
16
23
|
};
|
|
17
24
|
type HotUpdaterAPI = RuntimeHotUpdaterAPI;
|
|
18
|
-
declare const REMOVED_CLIENT_ACCESS = "clientAccess objects were removed in 1.0: set clientAccess: \"public\", or add
|
|
25
|
+
declare const REMOVED_CLIENT_ACCESS = "clientAccess objects were removed in 1.0: set clientAccess: \"public\", or add a plugin that provides clientAuth";
|
|
19
26
|
/**
|
|
20
27
|
* A `clientAccess` object from before 1.0. Its `type` names the fix, so
|
|
21
28
|
* TypeScript reports it where the object is written.
|
|
@@ -57,7 +64,7 @@ type CreateHotUpdaterOptions<TPlugins extends readonly AnyHotUpdaterPlugin[] = r
|
|
|
57
64
|
readonly database: ToolingDatabase;
|
|
58
65
|
/** Storage implementations used to read provider-specific storage URIs. */
|
|
59
66
|
readonly storage?: readonly StoragePlugin[];
|
|
60
|
-
/**
|
|
67
|
+
/** The plugins the server runs; at most one provides clientAuth. Defaults to none. */
|
|
61
68
|
readonly plugins?: TPlugins;
|
|
62
69
|
} & ClientAccessRule<TPlugins>;
|
|
63
70
|
declare function createHotUpdater<const TPlugins extends readonly AnyHotUpdaterPlugin[] = readonly []>(options: CreateHotUpdaterOptions<TPlugins>): RuntimeHotUpdaterAPI<NoInfer<TPlugins>>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { toolingTargetOf } from "./db/
|
|
2
|
-
import { HotUpdaterConfigError
|
|
1
|
+
import { toolingTargetOf } from "./db/coreDatabase.mjs";
|
|
2
|
+
import { HotUpdaterConfigError } from "./assembly/configError.mjs";
|
|
3
|
+
import { assemblePlugins } from "./assembly/assemblePlugins.mjs";
|
|
3
4
|
import { createHotUpdaterHandlers } from "./handler.mjs";
|
|
4
5
|
import { createStorageAccess } from "./storageAccess.mjs";
|
|
5
6
|
import { assertStorageOperations } from "@hot-updater/plugin-core";
|
|
@@ -19,17 +20,11 @@ const databaseOf = (value) => {
|
|
|
19
20
|
}
|
|
20
21
|
throw new HotUpdaterConfigError("database must be a Hot Updater 1.0 database, such as kyselyAdapter(...) or postgres(...). Upgrade the provider package that created it.");
|
|
21
22
|
};
|
|
22
|
-
/**
|
|
23
|
-
const KEEP_INSIGHTS = "To keep Insights, which the release candidates ran by default, add insights() from @hot-updater/server/plugins/insights to plugins.";
|
|
24
|
-
/** `"public"`, or nothing; a `clientAccess` object names what replaced it. */
|
|
23
|
+
/** `"public"`, or nothing; a `clientAccess` object says what replaced it. */
|
|
25
24
|
const isPublic = (value) => {
|
|
26
25
|
if (value === void 0) return false;
|
|
27
26
|
if (value === "public") return true;
|
|
28
|
-
|
|
29
|
-
const type = value.type;
|
|
30
|
-
throw new HotUpdaterConfigError(type === "api-key" ? `clientAccess: { type: "api-key" } was removed in 1.0. Remove it and add apiKeys(${value.headerName === void 0 ? "" : `{ headerName: ${JSON.stringify(value.headerName)} }`}) from @hot-updater/server/plugins/api-keys to plugins, which protects client routes the same way. ${KEEP_INSIGHTS}` : `clientAccess objects were removed in 1.0. Use clientAccess: "public", or add apiKeys() from @hot-updater/server/plugins/api-keys to plugins. ${KEEP_INSIGHTS}`);
|
|
31
|
-
}
|
|
32
|
-
throw new HotUpdaterConfigError("clientAccess must be \"public\"; to protect client routes, add apiKeys() from @hot-updater/server/plugins/api-keys to plugins.");
|
|
27
|
+
throw new HotUpdaterConfigError(isRecord(value) ? "clientAccess objects were removed in 1.0. Set clientAccess: \"public\", or add a plugin that provides clientAuth to plugins." : "clientAccess must be \"public\"; to protect client routes, add a plugin that provides clientAuth to plugins.");
|
|
33
28
|
};
|
|
34
29
|
const hotUpdaterCoreMetadata = Symbol.for("@hot-updater/server/core-metadata");
|
|
35
30
|
function getHotUpdaterCoreMetadata(hotUpdater) {
|
|
@@ -49,7 +44,8 @@ function createHotUpdater(options) {
|
|
|
49
44
|
readStorageText,
|
|
50
45
|
resolveFileUrl
|
|
51
46
|
},
|
|
52
|
-
...database.onCachedRoutesChange === void 0 ? {} : { onCachedRoutesChange: () => database.onCachedRoutesChange() }
|
|
47
|
+
...database.onCachedRoutesChange === void 0 ? {} : { onCachedRoutesChange: () => database.onCachedRoutesChange() },
|
|
48
|
+
...database.aggregateBatching === void 0 ? {} : { batching: database.aggregateBatching }
|
|
53
49
|
});
|
|
54
50
|
const clientAuth = plugins.clientAuth;
|
|
55
51
|
if (clientAuth !== void 0 && publicClients) throw new HotUpdaterConfigError(`Plugin "${clientAuth.plugin}" provides clientAuth, so remove clientAccess.`);
|
|
@@ -69,13 +65,15 @@ function createHotUpdater(options) {
|
|
|
69
65
|
adapterName: database.name,
|
|
70
66
|
handlers,
|
|
71
67
|
core: plugins.core,
|
|
72
|
-
api: plugins.api
|
|
68
|
+
api: plugins.api,
|
|
69
|
+
flush: plugins.flush
|
|
73
70
|
};
|
|
74
71
|
Object.defineProperty(api, hotUpdaterCoreMetadata, {
|
|
75
72
|
enumerable: false,
|
|
76
73
|
value: {
|
|
77
74
|
database,
|
|
78
|
-
target: toolingTargetOf(options.plugins ?? [])
|
|
75
|
+
target: toolingTargetOf(options.plugins ?? []),
|
|
76
|
+
plugins: options.plugins ?? []
|
|
79
77
|
}
|
|
80
78
|
});
|
|
81
79
|
return api;
|