@hot-updater/plugin-core 0.30.12 → 0.31.1

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.
@@ -2,7 +2,7 @@ require("./_virtual/_rolldown/runtime.cjs");
2
2
  const require_calculatePagination = require("./calculatePagination.cjs");
3
3
  let es_toolkit = require("es-toolkit");
4
4
  //#region src/createDatabasePlugin.ts
5
- const REPLACE_ON_UPDATE_KEYS = ["targetCohorts"];
5
+ const REPLACE_ON_UPDATE_KEYS = ["patches", "targetCohorts"];
6
6
  const DEFAULT_DESC_ORDER = {
7
7
  field: "id",
8
8
  direction: "desc"
@@ -1,7 +1,7 @@
1
1
  import { calculatePagination } from "./calculatePagination.mjs";
2
2
  import { mergeWith } from "es-toolkit";
3
3
  //#region src/createDatabasePlugin.ts
4
- const REPLACE_ON_UPDATE_KEYS = ["targetCohorts"];
4
+ const REPLACE_ON_UPDATE_KEYS = ["patches", "targetCohorts"];
5
5
  const DEFAULT_DESC_ORDER = {
6
6
  field: "id",
7
7
  direction: "desc"
@@ -1,55 +1,126 @@
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) profiles.node = {
42
+ async delete(storageUri) {
43
+ return requireNodeProfile().delete(storageUri);
44
+ },
45
+ async downloadFile(storageUri, filePath) {
46
+ return requireNodeProfile().downloadFile(storageUri, filePath);
47
+ },
48
+ async upload(key, filePath) {
49
+ return requireNodeProfile().upload(key, filePath);
50
+ }
51
+ };
52
+ else if (profileShape?.node !== false) Object.defineProperty(profiles, "node", {
53
+ enumerable: true,
54
+ get: getNodeProfile
55
+ });
56
+ if (profileShape?.runtime) profiles.runtime = {
57
+ async getDownloadUrl(storageUri, context) {
58
+ return requireRuntimeProfile().getDownloadUrl(storageUri, context);
59
+ },
60
+ async readText(storageUri, context) {
61
+ return requireRuntimeProfile().readText(storageUri, context);
62
+ }
63
+ };
64
+ else if (profileShape?.runtime !== false) Object.defineProperty(profiles, "runtime", {
65
+ enumerable: true,
66
+ get: getRuntimeProfile
67
+ });
68
+ return {
69
+ name,
70
+ supportedProtocol,
71
+ profiles
72
+ };
73
+ };
74
+ /**
75
+ * Creates a deploy/CLI/console storage plugin.
76
+ */
77
+ const createNodeStoragePlugin = (options) => {
78
+ return (config, hooks) => {
79
+ return () => createProfiledStoragePlugin({
80
+ createProfiles: () => ({ node: options.factory(config) }),
81
+ name: options.name,
82
+ profileShape: {
83
+ node: true,
84
+ runtime: false
85
+ },
86
+ supportedProtocol: options.supportedProtocol
87
+ }, hooks);
88
+ };
89
+ };
90
+ /**
91
+ * Creates an update-check runtime storage plugin.
92
+ */
93
+ const createRuntimeStoragePlugin = (options) => {
94
+ return (config, hooks) => {
95
+ return () => createProfiledStoragePlugin({
96
+ createProfiles: () => ({ runtime: options.factory(config) }),
97
+ name: options.name,
98
+ profileShape: {
99
+ node: false,
100
+ runtime: true
101
+ },
102
+ supportedProtocol: options.supportedProtocol
103
+ }, hooks);
104
+ };
105
+ };
2
106
  /**
3
- * Creates a storage plugin with lazy initialization and automatic hook execution.
4
- *
5
- * This factory function abstracts the double currying pattern used by all storage plugins,
6
- * ensuring consistent lazy initialization behavior across different storage providers.
7
- * Hooks are automatically executed at appropriate times without requiring manual invocation.
8
- *
9
- * @param options - Configuration options for the storage plugin
10
- * @returns A double-curried function that lazily initializes the storage plugin
11
- *
12
- * @example
13
- * ```typescript
14
- * export const s3Storage = createStoragePlugin<S3StorageConfig>({
15
- * name: "s3Storage",
16
- * supportedProtocol: "s3",
17
- * factory: (config) => {
18
- * const client = new S3Client(config);
19
- * return {
20
- * async upload(key, filePath) { ... },
21
- * async delete(storageUri) { ... },
22
- * async getDownloadUrl(storageUri, context) { ... }
23
- * };
24
- * }
25
- * });
26
- * ```
107
+ * Creates a storage plugin that can be used by both Node tooling and update
108
+ * check runtimes.
27
109
  */
28
- const createStoragePlugin = (options) => {
110
+ const createUniversalStoragePlugin = (options) => {
29
111
  return (config, hooks) => {
30
- return () => {
31
- let cachedMethods = null;
32
- const getMethods = () => {
33
- if (!cachedMethods) cachedMethods = options.factory(config);
34
- return cachedMethods;
35
- };
36
- return {
37
- name: options.name,
38
- supportedProtocol: options.supportedProtocol,
39
- async upload(key, filePath) {
40
- const result = await getMethods().upload(key, filePath);
41
- await hooks?.onStorageUploaded?.();
42
- return result;
43
- },
44
- async delete(storageUri) {
45
- return getMethods().delete(storageUri);
46
- },
47
- async getDownloadUrl(storageUri, context) {
48
- return getMethods().getDownloadUrl(storageUri, context);
49
- }
50
- };
51
- };
112
+ return () => createProfiledStoragePlugin({
113
+ createProfiles: () => options.factory(config),
114
+ name: options.name,
115
+ profileShape: {
116
+ node: true,
117
+ runtime: true
118
+ },
119
+ supportedProtocol: options.supportedProtocol
120
+ }, hooks);
52
121
  };
53
122
  };
54
123
  //#endregion
55
- exports.createStoragePlugin = createStoragePlugin;
124
+ exports.createNodeStoragePlugin = createNodeStoragePlugin;
125
+ exports.createRuntimeStoragePlugin = createRuntimeStoragePlugin;
126
+ exports.createUniversalStoragePlugin = createUniversalStoragePlugin;
@@ -1,62 +1,55 @@
1
- import { StoragePlugin, StoragePluginHooks } from "./types/index.cjs";
1
+ import { NodeStoragePlugin, NodeStorageProfile, RuntimeStoragePlugin, RuntimeStorageProfile, StoragePluginHooks, StoragePluginProfiles, UniversalStoragePlugin } from "./types/index.cjs";
2
2
 
3
3
  //#region src/createStoragePlugin.d.ts
4
- /**
5
- * Storage plugin methods without name and supportedProtocol
6
- */
7
- type StoragePluginMethods<TContext = unknown> = Omit<StoragePlugin<TContext>, "name" | "supportedProtocol">;
8
- /**
9
- * Factory function that creates storage plugin methods
10
- */
11
- type StoragePluginFactory<TConfig, TContext = unknown> = (config: TConfig) => StoragePluginMethods<TContext>;
12
- /**
13
- * Configuration options for creating a storage plugin
14
- */
15
- interface CreateStoragePluginOptions<TConfig, TContext = unknown> {
4
+ type StorageProfileFactory<TConfig, TProfiles> = (config: TConfig) => TProfiles;
5
+ interface BaseStoragePluginOptions<TConfig, TContext = unknown, TProfiles extends StoragePluginProfiles<TContext> = StoragePluginProfiles<TContext>> {
16
6
  /**
17
- * The name of the storage plugin (e.g., "s3Storage", "r2Storage")
7
+ * The name of the storage plugin (e.g., "s3Storage", "r2Storage").
18
8
  */
19
9
  name: string;
20
10
  /**
21
11
  * The protocol that this storage plugin supports (e.g., "s3", "r2", "gs").
22
12
  *
23
- * This value is stored in the database and is used by the server to understand
24
- * how to fetch assets.
25
- * For example, if the protocol is "s3", assets will be stored in the format:
26
- * s3://bucketName/key
13
+ * This value is stored in the database and is used by the server to
14
+ * understand how to fetch assets.
27
15
  */
28
16
  supportedProtocol: string;
29
17
  /**
30
- * Function that creates the storage plugin methods (upload, delete, getDownloadUrl)
18
+ * Function that creates the storage plugin profiles.
31
19
  */
32
- factory: StoragePluginFactory<TConfig, TContext>;
20
+ factory: StorageProfileFactory<TConfig, TProfiles>;
33
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>;
34
49
  /**
35
- * Creates a storage plugin with lazy initialization and automatic hook execution.
36
- *
37
- * This factory function abstracts the double currying pattern used by all storage plugins,
38
- * ensuring consistent lazy initialization behavior across different storage providers.
39
- * Hooks are automatically executed at appropriate times without requiring manual invocation.
40
- *
41
- * @param options - Configuration options for the storage plugin
42
- * @returns A double-curried function that lazily initializes the storage plugin
43
- *
44
- * @example
45
- * ```typescript
46
- * export const s3Storage = createStoragePlugin<S3StorageConfig>({
47
- * name: "s3Storage",
48
- * supportedProtocol: "s3",
49
- * factory: (config) => {
50
- * const client = new S3Client(config);
51
- * return {
52
- * async upload(key, filePath) { ... },
53
- * async delete(storageUri) { ... },
54
- * async getDownloadUrl(storageUri, context) { ... }
55
- * };
56
- * }
57
- * });
58
- * ```
50
+ * Creates a storage plugin that can be used by both Node tooling and update
51
+ * check runtimes.
59
52
  */
60
- declare const createStoragePlugin: <TConfig, TContext = unknown>(options: CreateStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => StoragePlugin<TContext>;
53
+ declare const createUniversalStoragePlugin: <TConfig, TContext = unknown>(options: CreateUniversalStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => UniversalStoragePlugin<TContext>;
61
54
  //#endregion
62
- export { CreateStoragePluginOptions, createStoragePlugin };
55
+ export { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin };
@@ -1,62 +1,55 @@
1
- import { StoragePlugin, StoragePluginHooks } from "./types/index.mjs";
1
+ import { NodeStoragePlugin, NodeStorageProfile, RuntimeStoragePlugin, RuntimeStorageProfile, StoragePluginHooks, StoragePluginProfiles, UniversalStoragePlugin } from "./types/index.mjs";
2
2
 
3
3
  //#region src/createStoragePlugin.d.ts
4
- /**
5
- * Storage plugin methods without name and supportedProtocol
6
- */
7
- type StoragePluginMethods<TContext = unknown> = Omit<StoragePlugin<TContext>, "name" | "supportedProtocol">;
8
- /**
9
- * Factory function that creates storage plugin methods
10
- */
11
- type StoragePluginFactory<TConfig, TContext = unknown> = (config: TConfig) => StoragePluginMethods<TContext>;
12
- /**
13
- * Configuration options for creating a storage plugin
14
- */
15
- interface CreateStoragePluginOptions<TConfig, TContext = unknown> {
4
+ type StorageProfileFactory<TConfig, TProfiles> = (config: TConfig) => TProfiles;
5
+ interface BaseStoragePluginOptions<TConfig, TContext = unknown, TProfiles extends StoragePluginProfiles<TContext> = StoragePluginProfiles<TContext>> {
16
6
  /**
17
- * The name of the storage plugin (e.g., "s3Storage", "r2Storage")
7
+ * The name of the storage plugin (e.g., "s3Storage", "r2Storage").
18
8
  */
19
9
  name: string;
20
10
  /**
21
11
  * The protocol that this storage plugin supports (e.g., "s3", "r2", "gs").
22
12
  *
23
- * This value is stored in the database and is used by the server to understand
24
- * how to fetch assets.
25
- * For example, if the protocol is "s3", assets will be stored in the format:
26
- * s3://bucketName/key
13
+ * This value is stored in the database and is used by the server to
14
+ * understand how to fetch assets.
27
15
  */
28
16
  supportedProtocol: string;
29
17
  /**
30
- * Function that creates the storage plugin methods (upload, delete, getDownloadUrl)
18
+ * Function that creates the storage plugin profiles.
31
19
  */
32
- factory: StoragePluginFactory<TConfig, TContext>;
20
+ factory: StorageProfileFactory<TConfig, TProfiles>;
33
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>;
34
49
  /**
35
- * Creates a storage plugin with lazy initialization and automatic hook execution.
36
- *
37
- * This factory function abstracts the double currying pattern used by all storage plugins,
38
- * ensuring consistent lazy initialization behavior across different storage providers.
39
- * Hooks are automatically executed at appropriate times without requiring manual invocation.
40
- *
41
- * @param options - Configuration options for the storage plugin
42
- * @returns A double-curried function that lazily initializes the storage plugin
43
- *
44
- * @example
45
- * ```typescript
46
- * export const s3Storage = createStoragePlugin<S3StorageConfig>({
47
- * name: "s3Storage",
48
- * supportedProtocol: "s3",
49
- * factory: (config) => {
50
- * const client = new S3Client(config);
51
- * return {
52
- * async upload(key, filePath) { ... },
53
- * async delete(storageUri) { ... },
54
- * async getDownloadUrl(storageUri, context) { ... }
55
- * };
56
- * }
57
- * });
58
- * ```
50
+ * Creates a storage plugin that can be used by both Node tooling and update
51
+ * check runtimes.
59
52
  */
60
- declare const createStoragePlugin: <TConfig, TContext = unknown>(options: CreateStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => StoragePlugin<TContext>;
53
+ declare const createUniversalStoragePlugin: <TConfig, TContext = unknown>(options: CreateUniversalStoragePluginOptions<TConfig, TContext>) => (config: TConfig, hooks?: StoragePluginHooks) => () => UniversalStoragePlugin<TContext>;
61
54
  //#endregion
62
- export { CreateStoragePluginOptions, createStoragePlugin };
55
+ export { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin };
@@ -1,55 +1,124 @@
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) profiles.node = {
42
+ async delete(storageUri) {
43
+ return requireNodeProfile().delete(storageUri);
44
+ },
45
+ async downloadFile(storageUri, filePath) {
46
+ return requireNodeProfile().downloadFile(storageUri, filePath);
47
+ },
48
+ async upload(key, filePath) {
49
+ return requireNodeProfile().upload(key, filePath);
50
+ }
51
+ };
52
+ else if (profileShape?.node !== false) Object.defineProperty(profiles, "node", {
53
+ enumerable: true,
54
+ get: getNodeProfile
55
+ });
56
+ if (profileShape?.runtime) profiles.runtime = {
57
+ async getDownloadUrl(storageUri, context) {
58
+ return requireRuntimeProfile().getDownloadUrl(storageUri, context);
59
+ },
60
+ async readText(storageUri, context) {
61
+ return requireRuntimeProfile().readText(storageUri, context);
62
+ }
63
+ };
64
+ else if (profileShape?.runtime !== false) Object.defineProperty(profiles, "runtime", {
65
+ enumerable: true,
66
+ get: getRuntimeProfile
67
+ });
68
+ return {
69
+ name,
70
+ supportedProtocol,
71
+ profiles
72
+ };
73
+ };
74
+ /**
75
+ * Creates a deploy/CLI/console storage plugin.
76
+ */
77
+ const createNodeStoragePlugin = (options) => {
78
+ return (config, hooks) => {
79
+ return () => createProfiledStoragePlugin({
80
+ createProfiles: () => ({ node: options.factory(config) }),
81
+ name: options.name,
82
+ profileShape: {
83
+ node: true,
84
+ runtime: false
85
+ },
86
+ supportedProtocol: options.supportedProtocol
87
+ }, hooks);
88
+ };
89
+ };
90
+ /**
91
+ * Creates an update-check runtime storage plugin.
92
+ */
93
+ const createRuntimeStoragePlugin = (options) => {
94
+ return (config, hooks) => {
95
+ return () => createProfiledStoragePlugin({
96
+ createProfiles: () => ({ runtime: options.factory(config) }),
97
+ name: options.name,
98
+ profileShape: {
99
+ node: false,
100
+ runtime: true
101
+ },
102
+ supportedProtocol: options.supportedProtocol
103
+ }, hooks);
104
+ };
105
+ };
2
106
  /**
3
- * Creates a storage plugin with lazy initialization and automatic hook execution.
4
- *
5
- * This factory function abstracts the double currying pattern used by all storage plugins,
6
- * ensuring consistent lazy initialization behavior across different storage providers.
7
- * Hooks are automatically executed at appropriate times without requiring manual invocation.
8
- *
9
- * @param options - Configuration options for the storage plugin
10
- * @returns A double-curried function that lazily initializes the storage plugin
11
- *
12
- * @example
13
- * ```typescript
14
- * export const s3Storage = createStoragePlugin<S3StorageConfig>({
15
- * name: "s3Storage",
16
- * supportedProtocol: "s3",
17
- * factory: (config) => {
18
- * const client = new S3Client(config);
19
- * return {
20
- * async upload(key, filePath) { ... },
21
- * async delete(storageUri) { ... },
22
- * async getDownloadUrl(storageUri, context) { ... }
23
- * };
24
- * }
25
- * });
26
- * ```
107
+ * Creates a storage plugin that can be used by both Node tooling and update
108
+ * check runtimes.
27
109
  */
28
- const createStoragePlugin = (options) => {
110
+ const createUniversalStoragePlugin = (options) => {
29
111
  return (config, hooks) => {
30
- return () => {
31
- let cachedMethods = null;
32
- const getMethods = () => {
33
- if (!cachedMethods) cachedMethods = options.factory(config);
34
- return cachedMethods;
35
- };
36
- return {
37
- name: options.name,
38
- supportedProtocol: options.supportedProtocol,
39
- async upload(key, filePath) {
40
- const result = await getMethods().upload(key, filePath);
41
- await hooks?.onStorageUploaded?.();
42
- return result;
43
- },
44
- async delete(storageUri) {
45
- return getMethods().delete(storageUri);
46
- },
47
- async getDownloadUrl(storageUri, context) {
48
- return getMethods().getDownloadUrl(storageUri, context);
49
- }
50
- };
51
- };
112
+ return () => createProfiledStoragePlugin({
113
+ createProfiles: () => options.factory(config),
114
+ name: options.name,
115
+ profileShape: {
116
+ node: true,
117
+ runtime: true
118
+ },
119
+ supportedProtocol: options.supportedProtocol
120
+ }, hooks);
52
121
  };
53
122
  };
54
123
  //#endregion
55
- export { createStoragePlugin };
124
+ export { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin };
package/dist/index.cjs CHANGED
@@ -12,24 +12,31 @@ const require_createStorageKeyBuilder = require("./createStorageKeyBuilder.cjs")
12
12
  const require_createStoragePlugin = require("./createStoragePlugin.cjs");
13
13
  const require_generateMinBundleId = require("./generateMinBundleId.cjs");
14
14
  const require_parseStorageUri = require("./parseStorageUri.cjs");
15
+ const require_storageProfile = require("./storageProfile.cjs");
15
16
  const require_index = require("./types/index.cjs");
16
17
  const require_uuidv7 = require("./uuidv7.cjs");
18
+ exports.assertNodeStoragePlugin = require_storageProfile.assertNodeStoragePlugin;
19
+ exports.assertRuntimeStoragePlugin = require_storageProfile.assertRuntimeStoragePlugin;
17
20
  exports.bundleIdMatchesFilter = require_queryBundles.bundleIdMatchesFilter;
18
21
  exports.bundleMatchesQueryWhere = require_queryBundles.bundleMatchesQueryWhere;
19
22
  exports.calculatePagination = require_calculatePagination.calculatePagination;
20
23
  exports.createBlobDatabasePlugin = require_createBlobDatabasePlugin.createBlobDatabasePlugin;
21
24
  exports.createDatabasePlugin = require_createDatabasePlugin.createDatabasePlugin;
22
25
  exports.createDatabasePluginGetUpdateInfo = require_createDatabasePluginGetUpdateInfo.createDatabasePluginGetUpdateInfo;
26
+ exports.createNodeStoragePlugin = require_createStoragePlugin.createNodeStoragePlugin;
27
+ exports.createRuntimeStoragePlugin = require_createStoragePlugin.createRuntimeStoragePlugin;
23
28
  exports.createStorageKeyBuilder = require_createStorageKeyBuilder.createStorageKeyBuilder;
24
- exports.createStoragePlugin = require_createStoragePlugin.createStoragePlugin;
25
29
  exports.createUUIDv7 = require_uuidv7.createUUIDv7;
26
30
  exports.createUUIDv7WithSameTimestamp = require_uuidv7.createUUIDv7WithSameTimestamp;
31
+ exports.createUniversalStoragePlugin = require_createStoragePlugin.createUniversalStoragePlugin;
27
32
  exports.detectCompressionFormat = require_compressionFormat.detectCompressionFormat;
28
33
  exports.extractTimestampFromUUIDv7 = require_uuidv7.extractTimestampFromUUIDv7;
29
34
  exports.filterCompatibleAppVersions = require_filterCompatibleAppVersions.filterCompatibleAppVersions;
30
35
  exports.generateMinBundleId = require_generateMinBundleId.generateMinBundleId;
31
36
  exports.getCompressionMimeType = require_compressionFormat.getCompressionMimeType;
32
37
  exports.getContentType = require_compressionFormat.getContentType;
38
+ exports.isNodeStoragePlugin = require_storageProfile.isNodeStoragePlugin;
39
+ exports.isRuntimeStoragePlugin = require_storageProfile.isRuntimeStoragePlugin;
33
40
  exports.paginateBundles = require_paginateBundles.paginateBundles;
34
41
  exports.parseStorageUri = require_parseStorageUri.parseStorageUri;
35
42
  exports.semverSatisfies = require_semverSatisfies.semverSatisfies;
package/dist/index.d.cts CHANGED
@@ -1,17 +1,18 @@
1
1
  import { BuiltIns, HasMultipleCallSignatures, Primitive, RequiredDeep } from "./types/utils.cjs";
2
- import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, SigningConfig, StoragePlugin, StoragePluginHooks, StorageResolveContext, UpdateInfo, supportedIosPlatforms } from "./types/index.cjs";
2
+ import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, supportedIosPlatforms } from "./types/index.cjs";
3
3
  import { PaginationOptions, calculatePagination } from "./calculatePagination.cjs";
4
4
  import { CompressionFormat, CompressionFormatInfo, detectCompressionFormat, getCompressionMimeType, getContentType } from "./compressionFormat.cjs";
5
5
  import { BlobDatabasePluginConfig, BlobOperations, createBlobDatabasePlugin } from "./createBlobDatabasePlugin.cjs";
6
6
  import { AbstractDatabasePlugin, CreateDatabasePluginOptions, createDatabasePlugin } from "./createDatabasePlugin.cjs";
7
7
  import { CreateDatabasePluginGetUpdateInfoOptions, createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.cjs";
8
8
  import { createStorageKeyBuilder } from "./createStorageKeyBuilder.cjs";
9
- import { CreateStoragePluginOptions, createStoragePlugin } from "./createStoragePlugin.cjs";
9
+ import { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin } from "./createStoragePlugin.cjs";
10
10
  import { filterCompatibleAppVersions } from "./filterCompatibleAppVersions.cjs";
11
11
  import { generateMinBundleId } from "./generateMinBundleId.cjs";
12
12
  import { ParsedStorageUri, parseStorageUri } from "./parseStorageUri.cjs";
13
13
  import { paginateBundles } from "./paginateBundles.cjs";
14
14
  import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.cjs";
15
15
  import { semverSatisfies } from "./semverSatisfies.cjs";
16
+ import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.cjs";
16
17
  import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.cjs";
17
- export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, CreateStoragePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, SigningConfig, StoragePlugin, StoragePluginHooks, StorageResolveContext, UpdateInfo, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createStorageKeyBuilder, createStoragePlugin, createUUIDv7, createUUIDv7WithSameTimestamp, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, paginateBundles, parseStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
18
+ export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
package/dist/index.d.mts CHANGED
@@ -1,17 +1,18 @@
1
1
  import { BuiltIns, HasMultipleCallSignatures, Primitive, RequiredDeep } from "./types/utils.mjs";
2
- import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, SigningConfig, StoragePlugin, StoragePluginHooks, StorageResolveContext, UpdateInfo, supportedIosPlatforms } from "./types/index.mjs";
2
+ import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, supportedIosPlatforms } from "./types/index.mjs";
3
3
  import { PaginationOptions, calculatePagination } from "./calculatePagination.mjs";
4
4
  import { CompressionFormat, CompressionFormatInfo, detectCompressionFormat, getCompressionMimeType, getContentType } from "./compressionFormat.mjs";
5
5
  import { BlobDatabasePluginConfig, BlobOperations, createBlobDatabasePlugin } from "./createBlobDatabasePlugin.mjs";
6
6
  import { AbstractDatabasePlugin, CreateDatabasePluginOptions, createDatabasePlugin } from "./createDatabasePlugin.mjs";
7
7
  import { CreateDatabasePluginGetUpdateInfoOptions, createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.mjs";
8
8
  import { createStorageKeyBuilder } from "./createStorageKeyBuilder.mjs";
9
- import { CreateStoragePluginOptions, createStoragePlugin } from "./createStoragePlugin.mjs";
9
+ import { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin } from "./createStoragePlugin.mjs";
10
10
  import { filterCompatibleAppVersions } from "./filterCompatibleAppVersions.mjs";
11
11
  import { generateMinBundleId } from "./generateMinBundleId.mjs";
12
12
  import { ParsedStorageUri, parseStorageUri } from "./parseStorageUri.mjs";
13
13
  import { paginateBundles } from "./paginateBundles.mjs";
14
14
  import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.mjs";
15
15
  import { semverSatisfies } from "./semverSatisfies.mjs";
16
+ import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.mjs";
16
17
  import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.mjs";
17
- export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, CreateStoragePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, SigningConfig, StoragePlugin, StoragePluginHooks, StorageResolveContext, UpdateInfo, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createStorageKeyBuilder, createStoragePlugin, createUUIDv7, createUUIDv7WithSameTimestamp, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, paginateBundles, parseStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
18
+ export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
package/dist/index.mjs CHANGED
@@ -8,9 +8,10 @@ import { paginateBundles } from "./paginateBundles.mjs";
8
8
  import { createBlobDatabasePlugin } from "./createBlobDatabasePlugin.mjs";
9
9
  import { createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.mjs";
10
10
  import { createStorageKeyBuilder } from "./createStorageKeyBuilder.mjs";
11
- import { createStoragePlugin } from "./createStoragePlugin.mjs";
11
+ import { createNodeStoragePlugin, createRuntimeStoragePlugin, createUniversalStoragePlugin } from "./createStoragePlugin.mjs";
12
12
  import { generateMinBundleId } from "./generateMinBundleId.mjs";
13
13
  import { parseStorageUri } from "./parseStorageUri.mjs";
14
+ import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.mjs";
14
15
  import { supportedIosPlatforms } from "./types/index.mjs";
15
16
  import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.mjs";
16
- export { bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createStorageKeyBuilder, createStoragePlugin, createUUIDv7, createUUIDv7WithSameTimestamp, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, paginateBundles, parseStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
17
+ export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
@@ -0,0 +1,15 @@
1
+ //#region src/storageProfile.ts
2
+ const createMissingProfileError = (plugin, profile) => /* @__PURE__ */ new Error(`${plugin.name} does not implement the ${profile} storage profile for protocol "${plugin.supportedProtocol}".`);
3
+ const isNodeStoragePlugin = (plugin) => Boolean(plugin.profiles.node);
4
+ const isRuntimeStoragePlugin = (plugin) => Boolean(plugin.profiles.runtime);
5
+ function assertNodeStoragePlugin(plugin) {
6
+ if (!isNodeStoragePlugin(plugin)) throw createMissingProfileError(plugin, "node");
7
+ }
8
+ function assertRuntimeStoragePlugin(plugin) {
9
+ if (!isRuntimeStoragePlugin(plugin)) throw createMissingProfileError(plugin, "runtime");
10
+ }
11
+ //#endregion
12
+ exports.assertNodeStoragePlugin = assertNodeStoragePlugin;
13
+ exports.assertRuntimeStoragePlugin = assertRuntimeStoragePlugin;
14
+ exports.isNodeStoragePlugin = isNodeStoragePlugin;
15
+ exports.isRuntimeStoragePlugin = isRuntimeStoragePlugin;
@@ -0,0 +1,9 @@
1
+ import { NodeStoragePlugin, RuntimeStoragePlugin, StoragePlugin } from "./types/index.cjs";
2
+
3
+ //#region src/storageProfile.d.ts
4
+ declare const isNodeStoragePlugin: <TContext = unknown>(plugin: StoragePlugin<TContext>) => plugin is NodeStoragePlugin<TContext>;
5
+ declare const isRuntimeStoragePlugin: <TContext = unknown>(plugin: StoragePlugin<TContext>) => plugin is RuntimeStoragePlugin<TContext>;
6
+ declare function assertNodeStoragePlugin<TContext = unknown>(plugin: StoragePlugin<TContext>): asserts plugin is NodeStoragePlugin<TContext>;
7
+ declare function assertRuntimeStoragePlugin<TContext = unknown>(plugin: StoragePlugin<TContext>): asserts plugin is RuntimeStoragePlugin<TContext>;
8
+ //#endregion
9
+ export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin };
@@ -0,0 +1,9 @@
1
+ import { NodeStoragePlugin, RuntimeStoragePlugin, StoragePlugin } from "./types/index.mjs";
2
+
3
+ //#region src/storageProfile.d.ts
4
+ declare const isNodeStoragePlugin: <TContext = unknown>(plugin: StoragePlugin<TContext>) => plugin is NodeStoragePlugin<TContext>;
5
+ declare const isRuntimeStoragePlugin: <TContext = unknown>(plugin: StoragePlugin<TContext>) => plugin is RuntimeStoragePlugin<TContext>;
6
+ declare function assertNodeStoragePlugin<TContext = unknown>(plugin: StoragePlugin<TContext>): asserts plugin is NodeStoragePlugin<TContext>;
7
+ declare function assertRuntimeStoragePlugin<TContext = unknown>(plugin: StoragePlugin<TContext>): asserts plugin is RuntimeStoragePlugin<TContext>;
8
+ //#endregion
9
+ export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin };
@@ -0,0 +1,12 @@
1
+ //#region src/storageProfile.ts
2
+ const createMissingProfileError = (plugin, profile) => /* @__PURE__ */ new Error(`${plugin.name} does not implement the ${profile} storage profile for protocol "${plugin.supportedProtocol}".`);
3
+ const isNodeStoragePlugin = (plugin) => Boolean(plugin.profiles.node);
4
+ const isRuntimeStoragePlugin = (plugin) => Boolean(plugin.profiles.runtime);
5
+ function assertNodeStoragePlugin(plugin) {
6
+ if (!isNodeStoragePlugin(plugin)) throw createMissingProfileError(plugin, "node");
7
+ }
8
+ function assertRuntimeStoragePlugin(plugin) {
9
+ if (!isRuntimeStoragePlugin(plugin)) throw createMissingProfileError(plugin, "runtime");
10
+ }
11
+ //#endregion
12
+ export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin };
@@ -269,20 +269,61 @@ interface RequestEnvContext<TEnv = unknown> {
269
269
  }
270
270
  type HotUpdaterContext<TContext = unknown> = TContext;
271
271
  type StorageResolveContext<TContext = unknown> = HotUpdaterContext<TContext>;
272
- interface StoragePlugin<TContext = unknown> {
273
- /**
274
- * Protocol this storage plugin can resolve.
275
- * @example "s3", "r2", "supabase-storage".
276
- */
277
- supportedProtocol: string;
272
+ interface NodeStorageProfile {
278
273
  upload: (key: string, filePath: string) => Promise<{
279
274
  storageUri: string;
280
275
  }>;
281
276
  delete: (storageUri: string) => Promise<void>;
277
+ downloadFile: (storageUri: string, filePath: string) => Promise<void>;
278
+ }
279
+ interface RuntimeStorageProfile<TContext = unknown> {
282
280
  getDownloadUrl: (storageUri: string, context?: StorageResolveContext<TContext>) => Promise<{
283
281
  fileUrl: string;
284
282
  }>;
283
+ readText: (storageUri: string, context?: StorageResolveContext<TContext>) => Promise<string | null>;
284
+ }
285
+ interface StoragePluginProfiles<TContext = unknown> {
286
+ /**
287
+ * Node/deploy/console profile.
288
+ *
289
+ * Use this profile when the caller can materialize storage objects to the
290
+ * local filesystem.
291
+ */
292
+ node?: NodeStorageProfile;
293
+ /**
294
+ * Runtime update-check profile.
295
+ *
296
+ * Use this profile when the caller needs signed/public client URLs and direct
297
+ * server-side reads for small control-plane text objects such as manifests.
298
+ */
299
+ runtime?: RuntimeStorageProfile<TContext>;
300
+ }
301
+ interface StoragePlugin<TContext = unknown> {
302
+ /**
303
+ * Protocol this storage plugin can resolve.
304
+ * @example "s3", "r2", "supabase-storage".
305
+ */
306
+ supportedProtocol: string;
285
307
  name: string;
308
+ profiles: StoragePluginProfiles<TContext>;
309
+ }
310
+ interface NodeStoragePlugin<TContext = unknown> extends StoragePlugin<TContext> {
311
+ profiles: {
312
+ node: NodeStorageProfile;
313
+ runtime?: RuntimeStorageProfile<TContext>;
314
+ };
315
+ }
316
+ interface RuntimeStoragePlugin<TContext = unknown> extends StoragePlugin<TContext> {
317
+ profiles: {
318
+ node?: NodeStorageProfile;
319
+ runtime: RuntimeStorageProfile<TContext>;
320
+ };
321
+ }
322
+ interface UniversalStoragePlugin<TContext = unknown> extends StoragePlugin<TContext> {
323
+ profiles: {
324
+ node: NodeStorageProfile;
325
+ runtime: RuntimeStorageProfile<TContext>;
326
+ };
286
327
  }
287
328
  interface StoragePluginHooks {
288
329
  onStorageUploaded?: () => Promise<void>;
@@ -370,6 +411,30 @@ type ConfigInput = {
370
411
  */
371
412
  debug?: boolean;
372
413
  };
414
+ /**
415
+ * Optional pre-generated patch artifacts for faster OTA delivery.
416
+ *
417
+ * When enabled, `hot-updater deploy` tries to prepare binary patches against
418
+ * up to `maxBaseBundles` recent compatible bundles. Patch generation is an
419
+ * optimization only; archive delivery remains the fallback path.
420
+ *
421
+ * @default { enabled: true, maxBaseBundles: 3 }
422
+ */
423
+ patch?: {
424
+ /**
425
+ * Enable automatic patch generation during deploy.
426
+ *
427
+ * @default true
428
+ */
429
+ enabled?: boolean;
430
+ /**
431
+ * Maximum number of compatible older bundles to prepare patches for.
432
+ * Must be a positive integer.
433
+ *
434
+ * @default 3
435
+ */
436
+ maxBaseBundles?: number;
437
+ };
373
438
  console?: {
374
439
  /**
375
440
  * Git repository URL
@@ -406,7 +471,7 @@ type ConfigInput = {
406
471
  */
407
472
  signing?: SigningConfig;
408
473
  build: (args: BasePluginArgs) => Promise<BuildPlugin> | BuildPlugin;
409
- storage: () => Promise<StoragePlugin> | StoragePlugin;
474
+ storage: () => Promise<NodeStoragePlugin> | NodeStoragePlugin;
410
475
  database: () => Promise<DatabasePlugin> | DatabasePlugin;
411
476
  };
412
477
  interface NativeBuildOptions {
@@ -416,4 +481,4 @@ interface NativeBuildOptions {
416
481
  scheme?: string;
417
482
  }
418
483
  //#endregion
419
- export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, SigningConfig, StoragePlugin, StoragePluginHooks, StorageResolveContext, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
484
+ export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
@@ -269,20 +269,61 @@ interface RequestEnvContext<TEnv = unknown> {
269
269
  }
270
270
  type HotUpdaterContext<TContext = unknown> = TContext;
271
271
  type StorageResolveContext<TContext = unknown> = HotUpdaterContext<TContext>;
272
- interface StoragePlugin<TContext = unknown> {
273
- /**
274
- * Protocol this storage plugin can resolve.
275
- * @example "s3", "r2", "supabase-storage".
276
- */
277
- supportedProtocol: string;
272
+ interface NodeStorageProfile {
278
273
  upload: (key: string, filePath: string) => Promise<{
279
274
  storageUri: string;
280
275
  }>;
281
276
  delete: (storageUri: string) => Promise<void>;
277
+ downloadFile: (storageUri: string, filePath: string) => Promise<void>;
278
+ }
279
+ interface RuntimeStorageProfile<TContext = unknown> {
282
280
  getDownloadUrl: (storageUri: string, context?: StorageResolveContext<TContext>) => Promise<{
283
281
  fileUrl: string;
284
282
  }>;
283
+ readText: (storageUri: string, context?: StorageResolveContext<TContext>) => Promise<string | null>;
284
+ }
285
+ interface StoragePluginProfiles<TContext = unknown> {
286
+ /**
287
+ * Node/deploy/console profile.
288
+ *
289
+ * Use this profile when the caller can materialize storage objects to the
290
+ * local filesystem.
291
+ */
292
+ node?: NodeStorageProfile;
293
+ /**
294
+ * Runtime update-check profile.
295
+ *
296
+ * Use this profile when the caller needs signed/public client URLs and direct
297
+ * server-side reads for small control-plane text objects such as manifests.
298
+ */
299
+ runtime?: RuntimeStorageProfile<TContext>;
300
+ }
301
+ interface StoragePlugin<TContext = unknown> {
302
+ /**
303
+ * Protocol this storage plugin can resolve.
304
+ * @example "s3", "r2", "supabase-storage".
305
+ */
306
+ supportedProtocol: string;
285
307
  name: string;
308
+ profiles: StoragePluginProfiles<TContext>;
309
+ }
310
+ interface NodeStoragePlugin<TContext = unknown> extends StoragePlugin<TContext> {
311
+ profiles: {
312
+ node: NodeStorageProfile;
313
+ runtime?: RuntimeStorageProfile<TContext>;
314
+ };
315
+ }
316
+ interface RuntimeStoragePlugin<TContext = unknown> extends StoragePlugin<TContext> {
317
+ profiles: {
318
+ node?: NodeStorageProfile;
319
+ runtime: RuntimeStorageProfile<TContext>;
320
+ };
321
+ }
322
+ interface UniversalStoragePlugin<TContext = unknown> extends StoragePlugin<TContext> {
323
+ profiles: {
324
+ node: NodeStorageProfile;
325
+ runtime: RuntimeStorageProfile<TContext>;
326
+ };
286
327
  }
287
328
  interface StoragePluginHooks {
288
329
  onStorageUploaded?: () => Promise<void>;
@@ -370,6 +411,30 @@ type ConfigInput = {
370
411
  */
371
412
  debug?: boolean;
372
413
  };
414
+ /**
415
+ * Optional pre-generated patch artifacts for faster OTA delivery.
416
+ *
417
+ * When enabled, `hot-updater deploy` tries to prepare binary patches against
418
+ * up to `maxBaseBundles` recent compatible bundles. Patch generation is an
419
+ * optimization only; archive delivery remains the fallback path.
420
+ *
421
+ * @default { enabled: true, maxBaseBundles: 3 }
422
+ */
423
+ patch?: {
424
+ /**
425
+ * Enable automatic patch generation during deploy.
426
+ *
427
+ * @default true
428
+ */
429
+ enabled?: boolean;
430
+ /**
431
+ * Maximum number of compatible older bundles to prepare patches for.
432
+ * Must be a positive integer.
433
+ *
434
+ * @default 3
435
+ */
436
+ maxBaseBundles?: number;
437
+ };
373
438
  console?: {
374
439
  /**
375
440
  * Git repository URL
@@ -406,7 +471,7 @@ type ConfigInput = {
406
471
  */
407
472
  signing?: SigningConfig;
408
473
  build: (args: BasePluginArgs) => Promise<BuildPlugin> | BuildPlugin;
409
- storage: () => Promise<StoragePlugin> | StoragePlugin;
474
+ storage: () => Promise<NodeStoragePlugin> | NodeStoragePlugin;
410
475
  database: () => Promise<DatabasePlugin> | DatabasePlugin;
411
476
  };
412
477
  interface NativeBuildOptions {
@@ -416,4 +481,4 @@ interface NativeBuildOptions {
416
481
  scheme?: string;
417
482
  }
418
483
  //#endregion
419
- export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, SigningConfig, StoragePlugin, StoragePluginHooks, StorageResolveContext, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
484
+ export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/plugin-core",
3
- "version": "0.30.12",
3
+ "version": "0.31.1",
4
4
  "type": "module",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "sideEffects": false,
@@ -42,14 +42,14 @@
42
42
  "es-toolkit": "^1.32.0",
43
43
  "mime": "^4.0.4",
44
44
  "semver": "^7.7.2",
45
- "@hot-updater/core": "0.30.12",
46
- "@hot-updater/js": "0.30.12"
45
+ "@hot-updater/core": "0.31.1",
46
+ "@hot-updater/js": "0.31.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^20",
50
50
  "@types/semver": "^7.5.8",
51
51
  "typescript": "6.0.2",
52
- "@hot-updater/test-utils": "0.30.12"
52
+ "@hot-updater/test-utils": "0.31.1"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsdown",