@hot-updater/plugin-core 0.36.6 → 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/assetStorageLayout.cjs +36 -18
  2. package/dist/assetStorageLayout.d.cts +21 -6
  3. package/dist/assetStorageLayout.d.mts +21 -6
  4. package/dist/assetStorageLayout.mjs +36 -18
  5. package/dist/bundleStorageLayout.cjs +2 -3
  6. package/dist/bundleStorageLayout.mjs +2 -3
  7. package/dist/contentAddressedAssets.cjs +5 -0
  8. package/dist/contentAddressedAssets.d.cts +2 -1
  9. package/dist/contentAddressedAssets.d.mts +2 -1
  10. package/dist/contentAddressedAssets.mjs +5 -1
  11. package/dist/createDatabasePlugin.cjs +775 -284
  12. package/dist/createDatabasePlugin.d.cts +20 -64
  13. package/dist/createDatabasePlugin.d.mts +20 -64
  14. package/dist/createDatabasePlugin.mjs +773 -284
  15. package/dist/createStorageKeyBuilder.cjs +9 -2
  16. package/dist/createStorageKeyBuilder.mjs +9 -2
  17. package/dist/createStoragePlugin.cjs +6 -145
  18. package/dist/createStoragePlugin.d.cts +7 -52
  19. package/dist/createStoragePlugin.d.mts +7 -52
  20. package/dist/createStoragePlugin.mjs +5 -143
  21. package/dist/databaseClient.cjs +112 -0
  22. package/dist/databaseClient.d.cts +33 -0
  23. package/dist/databaseClient.d.mts +33 -0
  24. package/dist/databaseClient.mjs +110 -0
  25. package/dist/databaseClientReads.cjs +113 -0
  26. package/dist/databaseClientReads.mjs +112 -0
  27. package/dist/databaseClientUpdates.cjs +39 -0
  28. package/dist/databaseClientUpdates.d.cts +11 -0
  29. package/dist/databaseClientUpdates.d.mts +11 -0
  30. package/dist/databaseClientUpdates.mjs +36 -0
  31. package/dist/databaseJsonValue.cjs +37 -0
  32. package/dist/databaseJsonValue.d.cts +5 -0
  33. package/dist/databaseJsonValue.d.mts +5 -0
  34. package/dist/databaseJsonValue.mjs +37 -0
  35. package/dist/databaseMetadata.cjs +13 -0
  36. package/dist/databaseMetadata.mjs +12 -0
  37. package/dist/databasePluginCrud.cjs +86 -0
  38. package/dist/databasePluginCrud.d.cts +1 -0
  39. package/dist/databasePluginCrud.d.mts +1 -0
  40. package/dist/databasePluginCrud.mjs +86 -0
  41. package/dist/databasePluginCrudValidation.d.cts +1 -0
  42. package/dist/databasePluginCrudValidation.d.mts +1 -0
  43. package/dist/databasePluginCrudValidationErrors.cjs +10 -0
  44. package/dist/databasePluginCrudValidationErrors.d.cts +9 -0
  45. package/dist/databasePluginCrudValidationErrors.d.mts +9 -0
  46. package/dist/databasePluginCrudValidationErrors.mjs +10 -0
  47. package/dist/databasePluginCrudValidationFields.cjs +291 -0
  48. package/dist/databasePluginCrudValidationFields.d.cts +1 -0
  49. package/dist/databasePluginCrudValidationFields.d.mts +1 -0
  50. package/dist/databasePluginCrudValidationFields.mjs +281 -0
  51. package/dist/databasePluginCrudValidationMutations.cjs +88 -0
  52. package/dist/databasePluginCrudValidationMutations.d.cts +1 -0
  53. package/dist/databasePluginCrudValidationMutations.d.mts +1 -0
  54. package/dist/databasePluginCrudValidationMutations.mjs +82 -0
  55. package/dist/databasePluginCrudValidationQueries.cjs +103 -0
  56. package/dist/databasePluginCrudValidationQueries.d.cts +1 -0
  57. package/dist/databasePluginCrudValidationQueries.d.mts +1 -0
  58. package/dist/databasePluginCrudValidationQueries.mjs +97 -0
  59. package/dist/databasePluginCrudValidationRows.cjs +55 -0
  60. package/dist/databasePluginCrudValidationRows.d.cts +1 -0
  61. package/dist/databasePluginCrudValidationRows.d.mts +1 -0
  62. package/dist/databasePluginCrudValidationRows.mjs +53 -0
  63. package/dist/databasePluginTransaction.cjs +7 -0
  64. package/dist/databasePluginTransaction.mjs +7 -0
  65. package/dist/databaseRows.cjs +149 -0
  66. package/dist/databaseRows.d.cts +34 -0
  67. package/dist/databaseRows.d.mts +34 -0
  68. package/dist/databaseRows.mjs +141 -0
  69. package/dist/index.cjs +76 -24
  70. package/dist/index.d.cts +22 -12
  71. package/dist/index.d.mts +22 -12
  72. package/dist/index.mjs +21 -14
  73. package/dist/internal.cjs +6 -0
  74. package/dist/internal.d.cts +9 -0
  75. package/dist/internal.d.mts +9 -0
  76. package/dist/internal.mjs +3 -0
  77. package/dist/node_modules/.pnpm/verkit@0.3.2/node_modules/verkit/dist/index.cjs +345 -0
  78. package/dist/node_modules/.pnpm/verkit@0.3.2/node_modules/verkit/dist/index.mjs +341 -0
  79. package/dist/paginateBundles.d.cts +6 -4
  80. package/dist/paginateBundles.d.mts +6 -4
  81. package/dist/parseStorageUri.cjs +46 -30
  82. package/dist/parseStorageUri.d.cts +20 -17
  83. package/dist/parseStorageUri.d.mts +20 -17
  84. package/dist/parseStorageUri.mjs +46 -30
  85. package/dist/queryBundles.cjs +1 -7
  86. package/dist/queryBundles.d.cts +3 -1
  87. package/dist/queryBundles.d.mts +3 -1
  88. package/dist/queryBundles.mjs +1 -7
  89. package/dist/releaseCatalogCompiler.cjs +391 -0
  90. package/dist/releaseCatalogCompiler.d.cts +55 -0
  91. package/dist/releaseCatalogCompiler.d.mts +55 -0
  92. package/dist/releaseCatalogCompiler.mjs +386 -0
  93. package/dist/releaseCatalogMutation.cjs +303 -0
  94. package/dist/releaseCatalogMutation.d.cts +86 -0
  95. package/dist/releaseCatalogMutation.d.mts +86 -0
  96. package/dist/releaseCatalogMutation.mjs +297 -0
  97. package/dist/releaseManagement.cjs +231 -0
  98. package/dist/releaseManagement.d.cts +48 -0
  99. package/dist/releaseManagement.d.mts +48 -0
  100. package/dist/releaseManagement.mjs +224 -0
  101. package/dist/remoteBundleSigning.cjs +296 -0
  102. package/dist/remoteBundleSigning.d.cts +43 -0
  103. package/dist/remoteBundleSigning.d.mts +43 -0
  104. package/dist/remoteBundleSigning.mjs +291 -0
  105. package/dist/requestBundleCache.cjs +22 -0
  106. package/dist/requestBundleCache.d.cts +9 -0
  107. package/dist/requestBundleCache.d.mts +9 -0
  108. package/dist/requestBundleCache.mjs +22 -0
  109. package/dist/semverSatisfies.cjs +3 -4
  110. package/dist/semverSatisfies.mjs +1 -1
  111. package/dist/storageDownloadPath.cjs +48 -0
  112. package/dist/storageDownloadPath.d.cts +15 -0
  113. package/dist/storageDownloadPath.d.mts +15 -0
  114. package/dist/storageDownloadPath.mjs +46 -0
  115. package/dist/types/database.d.cts +4 -0
  116. package/dist/types/database.d.mts +4 -0
  117. package/dist/types/databaseFields.cjs +92 -0
  118. package/dist/types/databaseFields.d.cts +12 -0
  119. package/dist/types/databaseFields.d.mts +12 -0
  120. package/dist/types/databaseFields.mjs +92 -0
  121. package/dist/types/databaseOperations.d.cts +173 -0
  122. package/dist/types/databaseOperations.d.mts +173 -0
  123. package/dist/types/databasePlugin.d.cts +240 -0
  124. package/dist/types/databasePlugin.d.mts +240 -0
  125. package/dist/types/databaseQuery.d.cts +47 -0
  126. package/dist/types/databaseQuery.d.mts +47 -0
  127. package/dist/types/databaseRows.d.cts +120 -0
  128. package/dist/types/databaseRows.d.mts +120 -0
  129. package/dist/types/index.d.cts +120 -162
  130. package/dist/types/index.d.mts +120 -162
  131. package/dist/types/internal.d.cts +7 -0
  132. package/dist/types/internal.d.mts +7 -0
  133. package/dist/types/public.d.cts +3 -0
  134. package/dist/types/public.d.mts +3 -0
  135. package/dist/uuidv7.cjs +9 -0
  136. package/dist/uuidv7.d.cts +4 -1
  137. package/dist/uuidv7.d.mts +4 -1
  138. package/dist/uuidv7.mjs +8 -1
  139. package/package.json +10 -5
  140. package/dist/bundleUnitOfWork.cjs +0 -158
  141. package/dist/bundleUnitOfWork.mjs +0 -158
  142. package/dist/bundleUnitOfWorkStore.cjs +0 -15
  143. package/dist/bundleUnitOfWorkStore.mjs +0 -15
  144. package/dist/createBlobDatabasePlugin.cjs +0 -382
  145. package/dist/createBlobDatabasePlugin.d.cts +0 -29
  146. package/dist/createBlobDatabasePlugin.d.mts +0 -29
  147. package/dist/createBlobDatabasePlugin.mjs +0 -381
  148. package/dist/legacyAssetStorageLayout.cjs +0 -12
  149. package/dist/legacyAssetStorageLayout.mjs +0 -12
  150. package/dist/requestUpdateBundleState.cjs +0 -26
  151. package/dist/requestUpdateBundleState.d.cts +0 -12
  152. package/dist/requestUpdateBundleState.d.mts +0 -12
  153. package/dist/requestUpdateBundleState.mjs +0 -24
  154. package/dist/resolveUpdateInfoFromBundles.cjs +0 -14
  155. package/dist/resolveUpdateInfoFromBundles.d.cts +0 -16
  156. package/dist/resolveUpdateInfoFromBundles.d.mts +0 -16
  157. package/dist/resolveUpdateInfoFromBundles.mjs +0 -13
  158. package/dist/storageProfile.cjs +0 -15
  159. package/dist/storageProfile.d.cts +0 -9
  160. package/dist/storageProfile.d.mts +0 -9
  161. package/dist/storageProfile.mjs +0 -12
@@ -1,6 +1,13 @@
1
1
  //#region src/createStorageKeyBuilder.ts
2
- const createStorageKeyBuilder = (basePath) => (...args) => {
3
- return [basePath || "", ...args].filter(Boolean).join("/");
2
+ const normalizeStorageKeyParts = (values) => {
3
+ if (values.some((value) => value.includes("\\"))) throw new Error("Storage keys must use '/' as the hierarchy separator.");
4
+ const segments = values.flatMap((value) => value.split("/").filter(Boolean));
5
+ if (segments.some((segment) => segment === "." || segment === "..")) throw new Error("Storage key segments must not be '.' or '..'.");
6
+ return segments;
7
+ };
8
+ const createStorageKeyBuilder = (basePath) => {
9
+ const baseSegments = normalizeStorageKeyParts([basePath ?? ""]);
10
+ return (...args) => [...baseSegments, ...normalizeStorageKeyParts(args)].join("/");
4
11
  };
5
12
  //#endregion
6
13
  exports.createStorageKeyBuilder = createStorageKeyBuilder;
@@ -1,6 +1,13 @@
1
1
  //#region src/createStorageKeyBuilder.ts
2
- const createStorageKeyBuilder = (basePath) => (...args) => {
3
- return [basePath || "", ...args].filter(Boolean).join("/");
2
+ const normalizeStorageKeyParts = (values) => {
3
+ if (values.some((value) => value.includes("\\"))) throw new Error("Storage keys must use '/' as the hierarchy separator.");
4
+ const segments = values.flatMap((value) => value.split("/").filter(Boolean));
5
+ if (segments.some((segment) => segment === "." || segment === "..")) throw new Error("Storage key segments must not be '.' or '..'.");
6
+ return segments;
7
+ };
8
+ const createStorageKeyBuilder = (basePath) => {
9
+ const baseSegments = normalizeStorageKeyParts([basePath ?? ""]);
10
+ return (...args) => [...baseSegments, ...normalizeStorageKeyParts(args)].join("/");
4
11
  };
5
12
  //#endregion
6
13
  export { createStorageKeyBuilder };
@@ -1,147 +1,8 @@
1
1
  //#region src/createStoragePlugin.ts
2
- const wrapNodeProfile = (node, hooks) => ({
3
- ...node,
4
- async upload(key, filePath) {
5
- const result = await node.upload(key, filePath);
6
- await hooks?.onStorageUploaded?.();
7
- return result;
8
- }
9
- });
10
- const createProfiledStoragePlugin = ({ createProfiles, name, profileShape, supportedProtocol }, hooks) => {
11
- let cachedProfiles = null;
12
- let cachedNodeProfile;
13
- let cachedRuntimeProfile;
14
- const getProfiles = () => {
15
- cachedProfiles ??= createProfiles();
16
- return cachedProfiles;
17
- };
18
- const getNodeProfile = () => {
19
- const node = getProfiles().node;
20
- if (!node) return;
21
- cachedNodeProfile ??= wrapNodeProfile(node, hooks);
22
- return cachedNodeProfile;
23
- };
24
- const requireNodeProfile = () => {
25
- const node = getNodeProfile();
26
- if (!node) throw new Error(`${name} does not implement the node storage profile for protocol "${supportedProtocol}".`);
27
- return node;
28
- };
29
- const getRuntimeProfile = () => {
30
- const runtime = getProfiles().runtime;
31
- if (!runtime) return;
32
- cachedRuntimeProfile ??= runtime;
33
- return cachedRuntimeProfile;
34
- };
35
- const requireRuntimeProfile = () => {
36
- const runtime = getRuntimeProfile();
37
- if (!runtime) throw new Error(`${name} does not implement the runtime storage profile for protocol "${supportedProtocol}".`);
38
- return runtime;
39
- };
40
- const profiles = {};
41
- if (profileShape?.node) {
42
- const nodeProfile = {
43
- async delete(storageUri) {
44
- return requireNodeProfile().delete(storageUri);
45
- },
46
- async downloadFile(storageUri, filePath) {
47
- return requireNodeProfile().downloadFile(storageUri, filePath);
48
- },
49
- async exists(storageUri) {
50
- return requireNodeProfile().exists(storageUri);
51
- },
52
- async upload(key, filePath) {
53
- return requireNodeProfile().upload(key, filePath);
54
- }
55
- };
56
- Object.defineProperties(nodeProfile, {
57
- deleteObjects: {
58
- enumerable: true,
59
- get: () => {
60
- const deleteObjects = requireNodeProfile().deleteObjects;
61
- return deleteObjects ? (keys) => deleteObjects(keys) : void 0;
62
- }
63
- },
64
- listObjects: {
65
- enumerable: true,
66
- get: () => {
67
- const listObjects = requireNodeProfile().listObjects;
68
- return listObjects ? (prefix) => listObjects(prefix) : void 0;
69
- }
70
- }
71
- });
72
- profiles.node = nodeProfile;
73
- } else if (profileShape?.node !== false) Object.defineProperty(profiles, "node", {
74
- enumerable: true,
75
- get: getNodeProfile
76
- });
77
- if (profileShape?.runtime) profiles.runtime = {
78
- async getDownloadUrl(storageUri, context) {
79
- return requireRuntimeProfile().getDownloadUrl(storageUri, context);
80
- },
81
- async readText(storageUri, context) {
82
- return requireRuntimeProfile().readText(storageUri, context);
83
- }
84
- };
85
- else if (profileShape?.runtime !== false) Object.defineProperty(profiles, "runtime", {
86
- enumerable: true,
87
- get: getRuntimeProfile
88
- });
89
- return {
90
- name,
91
- supportedProtocol,
92
- profiles
93
- };
94
- };
95
- /**
96
- * Creates a deploy/CLI/console storage plugin.
97
- */
98
- const createNodeStoragePlugin = (options) => {
99
- return (config, hooks) => {
100
- return () => createProfiledStoragePlugin({
101
- createProfiles: () => ({ node: options.factory(config) }),
102
- name: options.name,
103
- profileShape: {
104
- node: true,
105
- runtime: false
106
- },
107
- supportedProtocol: options.supportedProtocol
108
- }, hooks);
109
- };
110
- };
111
- /**
112
- * Creates an update-check runtime storage plugin.
113
- */
114
- const createRuntimeStoragePlugin = (options) => {
115
- return (config, hooks) => {
116
- return () => createProfiledStoragePlugin({
117
- createProfiles: () => ({ runtime: options.factory(config) }),
118
- name: options.name,
119
- profileShape: {
120
- node: false,
121
- runtime: true
122
- },
123
- supportedProtocol: options.supportedProtocol
124
- }, hooks);
125
- };
126
- };
127
- /**
128
- * Creates a storage plugin that can be used by both Node tooling and update
129
- * check runtimes.
130
- */
131
- const createUniversalStoragePlugin = (options) => {
132
- return (config, hooks) => {
133
- return () => createProfiledStoragePlugin({
134
- createProfiles: () => options.factory(config),
135
- name: options.name,
136
- profileShape: {
137
- node: true,
138
- runtime: true
139
- },
140
- supportedProtocol: options.supportedProtocol
141
- }, hooks);
142
- };
143
- };
2
+ const createStoragePlugin = (options) => ({ ...options });
3
+ function assertStorageOperations(plugin, operations) {
4
+ for (const operation of operations) if (typeof plugin[operation] !== "function") throw new Error(`Storage plugin "${plugin.name}" does not implement ${operation}.`);
5
+ }
144
6
  //#endregion
145
- exports.createNodeStoragePlugin = createNodeStoragePlugin;
146
- exports.createRuntimeStoragePlugin = createRuntimeStoragePlugin;
147
- exports.createUniversalStoragePlugin = createUniversalStoragePlugin;
7
+ exports.assertStorageOperations = assertStorageOperations;
8
+ exports.createStoragePlugin = createStoragePlugin;
@@ -1,55 +1,10 @@
1
- import { NodeStoragePlugin, NodeStorageProfile, RuntimeStoragePlugin, RuntimeStorageProfile, StoragePluginHooks, StoragePluginProfiles, UniversalStoragePlugin } from "./types/index.cjs";
1
+ import { StoragePlugin } from "./types/index.cjs";
2
2
 
3
3
  //#region src/createStoragePlugin.d.ts
4
- type StorageProfileFactory<TConfig, TProfiles> = (config: TConfig) => TProfiles;
5
- interface BaseStoragePluginOptions<TConfig, TContext = unknown, TProfiles extends StoragePluginProfiles<TContext> = StoragePluginProfiles<TContext>> {
6
- /**
7
- * The name of the storage plugin (e.g., "s3Storage", "r2Storage").
8
- */
9
- name: string;
10
- /**
11
- * The protocol that this storage plugin supports (e.g., "s3", "r2", "gs").
12
- *
13
- * This value is stored in the database and is used by the server to
14
- * understand how to fetch assets.
15
- */
16
- supportedProtocol: string;
17
- /**
18
- * Function that creates the storage plugin profiles.
19
- */
20
- factory: StorageProfileFactory<TConfig, TProfiles>;
21
- }
22
- type CreateNodeStoragePluginOptions<TConfig> = Omit<BaseStoragePluginOptions<TConfig, unknown, {
23
- node: NodeStorageProfile;
24
- }>, "factory"> & {
25
- factory: StorageProfileFactory<TConfig, NodeStorageProfile>;
26
- };
27
- type CreateRuntimeStoragePluginOptions<TConfig, TContext = unknown> = Omit<BaseStoragePluginOptions<TConfig, TContext, {
28
- runtime: RuntimeStorageProfile<TContext>;
29
- }>, "factory"> & {
30
- factory: StorageProfileFactory<TConfig, RuntimeStorageProfile<TContext>>;
31
- };
32
- type CreateUniversalStoragePluginOptions<TConfig, TContext = unknown> = Omit<BaseStoragePluginOptions<TConfig, TContext, {
33
- node: NodeStorageProfile;
34
- runtime: RuntimeStorageProfile<TContext>;
35
- }>, "factory"> & {
36
- factory: StorageProfileFactory<TConfig, {
37
- node: NodeStorageProfile;
38
- runtime: RuntimeStorageProfile<TContext>;
39
- }>;
40
- };
41
- /**
42
- * Creates a deploy/CLI/console storage plugin.
43
- */
44
- declare const createNodeStoragePlugin: <TConfig>(options: CreateNodeStoragePluginOptions<TConfig>) => (config: TConfig, hooks?: StoragePluginHooks) => () => NodeStoragePlugin;
45
- /**
46
- * Creates an update-check runtime storage plugin.
47
- */
48
- declare const createRuntimeStoragePlugin: <TConfig, TContext = unknown>(options: CreateRuntimeStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => RuntimeStoragePlugin<TContext>;
49
- /**
50
- * Creates a storage plugin that can be used by both Node tooling and update
51
- * check runtimes.
52
- */
53
- declare const createUniversalStoragePlugin: <TConfig, TContext = unknown>(options: CreateUniversalStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => UniversalStoragePlugin<TContext>;
4
+ type CreateStoragePluginOptions = StoragePlugin;
5
+ type StorageOperation = Exclude<keyof StoragePlugin, "name" | "protocol">;
6
+ type StoragePluginWith<TOperation extends StorageOperation> = StoragePlugin & Required<Pick<StoragePlugin, TOperation>>;
7
+ declare const createStoragePlugin: <const TOptions extends CreateStoragePluginOptions>(options: TOptions) => TOptions;
8
+ declare function assertStorageOperations<const TOperations extends readonly StorageOperation[]>(plugin: StoragePlugin, operations: TOperations): asserts plugin is StoragePluginWith<TOperations[number]>;
54
9
  //#endregion
55
- export { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin };
10
+ export { CreateStoragePluginOptions, StorageOperation, StoragePluginWith, assertStorageOperations, createStoragePlugin };
@@ -1,55 +1,10 @@
1
- import { NodeStoragePlugin, NodeStorageProfile, RuntimeStoragePlugin, RuntimeStorageProfile, StoragePluginHooks, StoragePluginProfiles, UniversalStoragePlugin } from "./types/index.mjs";
1
+ import { StoragePlugin } from "./types/index.mjs";
2
2
 
3
3
  //#region src/createStoragePlugin.d.ts
4
- type StorageProfileFactory<TConfig, TProfiles> = (config: TConfig) => TProfiles;
5
- interface BaseStoragePluginOptions<TConfig, TContext = unknown, TProfiles extends StoragePluginProfiles<TContext> = StoragePluginProfiles<TContext>> {
6
- /**
7
- * The name of the storage plugin (e.g., "s3Storage", "r2Storage").
8
- */
9
- name: string;
10
- /**
11
- * The protocol that this storage plugin supports (e.g., "s3", "r2", "gs").
12
- *
13
- * This value is stored in the database and is used by the server to
14
- * understand how to fetch assets.
15
- */
16
- supportedProtocol: string;
17
- /**
18
- * Function that creates the storage plugin profiles.
19
- */
20
- factory: StorageProfileFactory<TConfig, TProfiles>;
21
- }
22
- type CreateNodeStoragePluginOptions<TConfig> = Omit<BaseStoragePluginOptions<TConfig, unknown, {
23
- node: NodeStorageProfile;
24
- }>, "factory"> & {
25
- factory: StorageProfileFactory<TConfig, NodeStorageProfile>;
26
- };
27
- type CreateRuntimeStoragePluginOptions<TConfig, TContext = unknown> = Omit<BaseStoragePluginOptions<TConfig, TContext, {
28
- runtime: RuntimeStorageProfile<TContext>;
29
- }>, "factory"> & {
30
- factory: StorageProfileFactory<TConfig, RuntimeStorageProfile<TContext>>;
31
- };
32
- type CreateUniversalStoragePluginOptions<TConfig, TContext = unknown> = Omit<BaseStoragePluginOptions<TConfig, TContext, {
33
- node: NodeStorageProfile;
34
- runtime: RuntimeStorageProfile<TContext>;
35
- }>, "factory"> & {
36
- factory: StorageProfileFactory<TConfig, {
37
- node: NodeStorageProfile;
38
- runtime: RuntimeStorageProfile<TContext>;
39
- }>;
40
- };
41
- /**
42
- * Creates a deploy/CLI/console storage plugin.
43
- */
44
- declare const createNodeStoragePlugin: <TConfig>(options: CreateNodeStoragePluginOptions<TConfig>) => (config: TConfig, hooks?: StoragePluginHooks) => () => NodeStoragePlugin;
45
- /**
46
- * Creates an update-check runtime storage plugin.
47
- */
48
- declare const createRuntimeStoragePlugin: <TConfig, TContext = unknown>(options: CreateRuntimeStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => RuntimeStoragePlugin<TContext>;
49
- /**
50
- * Creates a storage plugin that can be used by both Node tooling and update
51
- * check runtimes.
52
- */
53
- declare const createUniversalStoragePlugin: <TConfig, TContext = unknown>(options: CreateUniversalStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => UniversalStoragePlugin<TContext>;
4
+ type CreateStoragePluginOptions = StoragePlugin;
5
+ type StorageOperation = Exclude<keyof StoragePlugin, "name" | "protocol">;
6
+ type StoragePluginWith<TOperation extends StorageOperation> = StoragePlugin & Required<Pick<StoragePlugin, TOperation>>;
7
+ declare const createStoragePlugin: <const TOptions extends CreateStoragePluginOptions>(options: TOptions) => TOptions;
8
+ declare function assertStorageOperations<const TOperations extends readonly StorageOperation[]>(plugin: StoragePlugin, operations: TOperations): asserts plugin is StoragePluginWith<TOperations[number]>;
54
9
  //#endregion
55
- export { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin };
10
+ export { CreateStoragePluginOptions, StorageOperation, StoragePluginWith, assertStorageOperations, createStoragePlugin };
@@ -1,145 +1,7 @@
1
1
  //#region src/createStoragePlugin.ts
2
- const wrapNodeProfile = (node, hooks) => ({
3
- ...node,
4
- async upload(key, filePath) {
5
- const result = await node.upload(key, filePath);
6
- await hooks?.onStorageUploaded?.();
7
- return result;
8
- }
9
- });
10
- const createProfiledStoragePlugin = ({ createProfiles, name, profileShape, supportedProtocol }, hooks) => {
11
- let cachedProfiles = null;
12
- let cachedNodeProfile;
13
- let cachedRuntimeProfile;
14
- const getProfiles = () => {
15
- cachedProfiles ??= createProfiles();
16
- return cachedProfiles;
17
- };
18
- const getNodeProfile = () => {
19
- const node = getProfiles().node;
20
- if (!node) return;
21
- cachedNodeProfile ??= wrapNodeProfile(node, hooks);
22
- return cachedNodeProfile;
23
- };
24
- const requireNodeProfile = () => {
25
- const node = getNodeProfile();
26
- if (!node) throw new Error(`${name} does not implement the node storage profile for protocol "${supportedProtocol}".`);
27
- return node;
28
- };
29
- const getRuntimeProfile = () => {
30
- const runtime = getProfiles().runtime;
31
- if (!runtime) return;
32
- cachedRuntimeProfile ??= runtime;
33
- return cachedRuntimeProfile;
34
- };
35
- const requireRuntimeProfile = () => {
36
- const runtime = getRuntimeProfile();
37
- if (!runtime) throw new Error(`${name} does not implement the runtime storage profile for protocol "${supportedProtocol}".`);
38
- return runtime;
39
- };
40
- const profiles = {};
41
- if (profileShape?.node) {
42
- const nodeProfile = {
43
- async delete(storageUri) {
44
- return requireNodeProfile().delete(storageUri);
45
- },
46
- async downloadFile(storageUri, filePath) {
47
- return requireNodeProfile().downloadFile(storageUri, filePath);
48
- },
49
- async exists(storageUri) {
50
- return requireNodeProfile().exists(storageUri);
51
- },
52
- async upload(key, filePath) {
53
- return requireNodeProfile().upload(key, filePath);
54
- }
55
- };
56
- Object.defineProperties(nodeProfile, {
57
- deleteObjects: {
58
- enumerable: true,
59
- get: () => {
60
- const deleteObjects = requireNodeProfile().deleteObjects;
61
- return deleteObjects ? (keys) => deleteObjects(keys) : void 0;
62
- }
63
- },
64
- listObjects: {
65
- enumerable: true,
66
- get: () => {
67
- const listObjects = requireNodeProfile().listObjects;
68
- return listObjects ? (prefix) => listObjects(prefix) : void 0;
69
- }
70
- }
71
- });
72
- profiles.node = nodeProfile;
73
- } else if (profileShape?.node !== false) Object.defineProperty(profiles, "node", {
74
- enumerable: true,
75
- get: getNodeProfile
76
- });
77
- if (profileShape?.runtime) profiles.runtime = {
78
- async getDownloadUrl(storageUri, context) {
79
- return requireRuntimeProfile().getDownloadUrl(storageUri, context);
80
- },
81
- async readText(storageUri, context) {
82
- return requireRuntimeProfile().readText(storageUri, context);
83
- }
84
- };
85
- else if (profileShape?.runtime !== false) Object.defineProperty(profiles, "runtime", {
86
- enumerable: true,
87
- get: getRuntimeProfile
88
- });
89
- return {
90
- name,
91
- supportedProtocol,
92
- profiles
93
- };
94
- };
95
- /**
96
- * Creates a deploy/CLI/console storage plugin.
97
- */
98
- const createNodeStoragePlugin = (options) => {
99
- return (config, hooks) => {
100
- return () => createProfiledStoragePlugin({
101
- createProfiles: () => ({ node: options.factory(config) }),
102
- name: options.name,
103
- profileShape: {
104
- node: true,
105
- runtime: false
106
- },
107
- supportedProtocol: options.supportedProtocol
108
- }, hooks);
109
- };
110
- };
111
- /**
112
- * Creates an update-check runtime storage plugin.
113
- */
114
- const createRuntimeStoragePlugin = (options) => {
115
- return (config, hooks) => {
116
- return () => createProfiledStoragePlugin({
117
- createProfiles: () => ({ runtime: options.factory(config) }),
118
- name: options.name,
119
- profileShape: {
120
- node: false,
121
- runtime: true
122
- },
123
- supportedProtocol: options.supportedProtocol
124
- }, hooks);
125
- };
126
- };
127
- /**
128
- * Creates a storage plugin that can be used by both Node tooling and update
129
- * check runtimes.
130
- */
131
- const createUniversalStoragePlugin = (options) => {
132
- return (config, hooks) => {
133
- return () => createProfiledStoragePlugin({
134
- createProfiles: () => options.factory(config),
135
- name: options.name,
136
- profileShape: {
137
- node: true,
138
- runtime: true
139
- },
140
- supportedProtocol: options.supportedProtocol
141
- }, hooks);
142
- };
143
- };
2
+ const createStoragePlugin = (options) => ({ ...options });
3
+ function assertStorageOperations(plugin, operations) {
4
+ for (const operation of operations) if (typeof plugin[operation] !== "function") throw new Error(`Storage plugin "${plugin.name}" does not implement ${operation}.`);
5
+ }
144
6
  //#endregion
145
- export { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin };
7
+ export { assertStorageOperations, createStoragePlugin };
@@ -0,0 +1,112 @@
1
+ const require_createDatabasePlugin = require("./createDatabasePlugin.cjs");
2
+ const require_databaseRows = require("./databaseRows.cjs");
3
+ const require_databaseClientReads = require("./databaseClientReads.cjs");
4
+ const require_databaseClientUpdates = require("./databaseClientUpdates.cjs");
5
+ //#region src/databaseClient.ts
6
+ var DatabaseBundleNotFoundError = class extends Error {
7
+ name = "DatabaseBundleNotFoundError";
8
+ constructor(bundleId) {
9
+ super(`Bundle "${bundleId}" was not found.`);
10
+ this.bundleId = bundleId;
11
+ }
12
+ };
13
+ var DatabasePatchInsertUnsupportedError = class extends Error {
14
+ name = "DatabasePatchInsertUnsupportedError";
15
+ constructor(bundleId, pluginName) {
16
+ super(`Database plugin "${pluginName}" cannot atomically insert patches for bundle "${bundleId}".`);
17
+ this.bundleId = bundleId;
18
+ this.pluginName = pluginName;
19
+ }
20
+ };
21
+ const insertChanges = (bundle) => [{
22
+ model: "bundles",
23
+ operation: "insert",
24
+ row: require_databaseRows.bundleToRow(bundle)
25
+ }, ...require_databaseRows.bundleToPatchRows(bundle).map((row) => ({
26
+ model: "bundlePatches",
27
+ operation: "insert",
28
+ row
29
+ }))];
30
+ const updateChanges = (bundleId, update) => {
31
+ const rowUpdate = require_databaseClientUpdates.bundleUpdateToRow(update);
32
+ return [{
33
+ model: "bundles",
34
+ operation: "update",
35
+ where: { id: bundleId },
36
+ update: rowUpdate
37
+ }, ...Object.hasOwn(update, "patches") ? [{
38
+ model: "bundlePatches",
39
+ operation: "delete",
40
+ where: { bundleId }
41
+ }, ...require_databaseClientUpdates.bundleUpdateToPatchRows(bundleId, update).map((row) => ({
42
+ model: "bundlePatches",
43
+ operation: "insert",
44
+ row
45
+ }))] : []];
46
+ };
47
+ const deleteChanges = (bundleId) => [{
48
+ model: "bundles",
49
+ operation: "delete",
50
+ where: { id: bundleId }
51
+ }];
52
+ const createDatabaseClient = (plugin) => {
53
+ const getBundleById = async (id) => {
54
+ const row = await plugin.models.bundles.findById(id);
55
+ if (!row) return null;
56
+ return (await require_databaseClientReads.hydrateRows(plugin, [row]))[0] ?? null;
57
+ };
58
+ const insertChannel = (input) => plugin.models.channels.insert(input);
59
+ const createMutationClient = (commit) => ({
60
+ getBundleById,
61
+ getBundles: (options) => require_databaseClientReads.responsePage(plugin, options),
62
+ async getChannels() {
63
+ return (await plugin.models.channels.list({})).channels;
64
+ },
65
+ insertChannel,
66
+ async insertBundle(bundle) {
67
+ try {
68
+ await commit(insertChanges(bundle));
69
+ } catch (error) {
70
+ if (error instanceof require_createDatabasePlugin.DatabaseAtomicCommitUnsupportedError && require_databaseRows.bundleToPatchRows(bundle).length > 0) throw new DatabasePatchInsertUnsupportedError(bundle.id, plugin.name);
71
+ throw error;
72
+ }
73
+ },
74
+ async updateBundleById(bundleId, update) {
75
+ try {
76
+ if (!(await commit(updateChanges(bundleId, update))).committed) throw new DatabaseBundleNotFoundError(bundleId);
77
+ } catch (error) {
78
+ if (error instanceof require_createDatabasePlugin.DatabaseAtomicCommitUnsupportedError && Object.hasOwn(update, "patches")) throw new require_databaseClientUpdates.DatabasePatchUpdateUnsupportedError(bundleId, plugin.name);
79
+ throw error;
80
+ }
81
+ },
82
+ async deleteBundleById(bundleId) {
83
+ const result = await commit(deleteChanges(bundleId));
84
+ if (!result.committed && result.conflict.reason === "referenced") throw new require_createDatabasePlugin.DatabaseRowReferencedError();
85
+ }
86
+ });
87
+ const runMutation = async (operation) => {
88
+ const changes = [];
89
+ const result = await operation(createMutationClient(async (input) => {
90
+ changes.push(...input);
91
+ return { committed: true };
92
+ }));
93
+ if (changes.length === 0) return result;
94
+ const commitResult = await plugin.commit({ changes });
95
+ if (!commitResult.committed) {
96
+ const change = changes[commitResult.conflict.changeIndex];
97
+ if (commitResult.conflict.reason === "referenced" && change?.model === "bundles" && change.operation === "delete") throw new require_createDatabasePlugin.DatabaseRowReferencedError();
98
+ if (change?.model === "bundles" && change.operation === "update") throw new DatabaseBundleNotFoundError(change.where.id);
99
+ throw new Error(`Database plugin "${plugin.name}" rejected a commit.`);
100
+ }
101
+ return result;
102
+ };
103
+ return {
104
+ ...createMutationClient((changes) => plugin.commit({ changes })),
105
+ deleteChannel: (input) => plugin.models.channels.delete(input),
106
+ mutate: runMutation
107
+ };
108
+ };
109
+ //#endregion
110
+ exports.DatabaseBundleNotFoundError = DatabaseBundleNotFoundError;
111
+ exports.DatabasePatchInsertUnsupportedError = DatabasePatchInsertUnsupportedError;
112
+ exports.createDatabaseClient = createDatabaseClient;
@@ -0,0 +1,33 @@
1
+ import { ChannelRow } from "./types/databaseRows.cjs";
2
+ import { BundleRepository, ChannelDeleteInput, ChannelDeleteResult, ChannelInsertInput, ChannelInsertResult } from "./types/databasePlugin.cjs";
3
+ import { DatabaseBundleQueryOptions, PaginatedResult } from "./types/index.cjs";
4
+ import { DatabasePatchUpdateUnsupportedError } from "./databaseClientUpdates.cjs";
5
+ import { Bundle } from "@hot-updater/core";
6
+
7
+ //#region src/databaseClient.d.ts
8
+ interface DatabaseClient {
9
+ getBundleById(id: string): Promise<Bundle | null>;
10
+ getChannels(): Promise<readonly ChannelRow[]>;
11
+ insertChannel(input: ChannelInsertInput): Promise<ChannelInsertResult>;
12
+ deleteChannel(input: ChannelDeleteInput): Promise<ChannelDeleteResult>;
13
+ getBundles(options: DatabaseBundleQueryOptions): Promise<PaginatedResult>;
14
+ insertBundle(bundle: Bundle): Promise<void>;
15
+ updateBundleById(bundleId: string, update: Partial<Bundle>): Promise<void>;
16
+ deleteBundleById(bundleId: string): Promise<void>;
17
+ mutate<TResult>(operation: (client: DatabaseMutationClient) => Promise<TResult>): Promise<TResult>;
18
+ }
19
+ type DatabaseMutationClient = Omit<DatabaseClient, "deleteChannel" | "mutate">;
20
+ declare class DatabaseBundleNotFoundError extends Error {
21
+ readonly bundleId: string;
22
+ readonly name = "DatabaseBundleNotFoundError";
23
+ constructor(bundleId: string);
24
+ }
25
+ declare class DatabasePatchInsertUnsupportedError extends Error {
26
+ readonly bundleId: string;
27
+ readonly pluginName: string;
28
+ readonly name = "DatabasePatchInsertUnsupportedError";
29
+ constructor(bundleId: string, pluginName: string);
30
+ }
31
+ declare const createDatabaseClient: (plugin: BundleRepository) => DatabaseClient;
32
+ //#endregion
33
+ export { DatabaseBundleNotFoundError, DatabaseClient, DatabaseMutationClient, DatabasePatchInsertUnsupportedError, createDatabaseClient };
@@ -0,0 +1,33 @@
1
+ import { ChannelRow } from "./types/databaseRows.mjs";
2
+ import { BundleRepository, ChannelDeleteInput, ChannelDeleteResult, ChannelInsertInput, ChannelInsertResult } from "./types/databasePlugin.mjs";
3
+ import { DatabaseBundleQueryOptions, PaginatedResult } from "./types/index.mjs";
4
+ import { DatabasePatchUpdateUnsupportedError } from "./databaseClientUpdates.mjs";
5
+ import { Bundle } from "@hot-updater/core";
6
+
7
+ //#region src/databaseClient.d.ts
8
+ interface DatabaseClient {
9
+ getBundleById(id: string): Promise<Bundle | null>;
10
+ getChannels(): Promise<readonly ChannelRow[]>;
11
+ insertChannel(input: ChannelInsertInput): Promise<ChannelInsertResult>;
12
+ deleteChannel(input: ChannelDeleteInput): Promise<ChannelDeleteResult>;
13
+ getBundles(options: DatabaseBundleQueryOptions): Promise<PaginatedResult>;
14
+ insertBundle(bundle: Bundle): Promise<void>;
15
+ updateBundleById(bundleId: string, update: Partial<Bundle>): Promise<void>;
16
+ deleteBundleById(bundleId: string): Promise<void>;
17
+ mutate<TResult>(operation: (client: DatabaseMutationClient) => Promise<TResult>): Promise<TResult>;
18
+ }
19
+ type DatabaseMutationClient = Omit<DatabaseClient, "deleteChannel" | "mutate">;
20
+ declare class DatabaseBundleNotFoundError extends Error {
21
+ readonly bundleId: string;
22
+ readonly name = "DatabaseBundleNotFoundError";
23
+ constructor(bundleId: string);
24
+ }
25
+ declare class DatabasePatchInsertUnsupportedError extends Error {
26
+ readonly bundleId: string;
27
+ readonly pluginName: string;
28
+ readonly name = "DatabasePatchInsertUnsupportedError";
29
+ constructor(bundleId: string, pluginName: string);
30
+ }
31
+ declare const createDatabaseClient: (plugin: BundleRepository) => DatabaseClient;
32
+ //#endregion
33
+ export { DatabaseBundleNotFoundError, DatabaseClient, DatabaseMutationClient, DatabasePatchInsertUnsupportedError, createDatabaseClient };