@hot-updater/core 0.27.1 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/hotUpdateDirUtil.cjs +26 -0
- package/dist/hotUpdateDirUtil.d.cts +25 -0
- package/dist/hotUpdateDirUtil.d.mts +25 -0
- package/dist/{index.js → hotUpdateDirUtil.mjs} +2 -8
- package/dist/index.cjs +20 -54
- package/dist/index.d.cts +5 -198
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +4 -0
- package/dist/react-native.cjs +18 -0
- package/dist/react-native.d.cts +4 -0
- package/dist/react-native.d.mts +4 -0
- package/dist/react-native.mjs +3 -0
- package/dist/rollout.cjs +132 -0
- package/dist/rollout.d.cts +17 -0
- package/dist/rollout.d.mts +17 -0
- package/dist/rollout.mjs +118 -0
- package/dist/types.cjs +0 -0
- package/dist/{index.d.ts → types.d.cts} +39 -30
- package/dist/types.d.mts +207 -0
- package/dist/types.mjs +1 -0
- package/dist/uuid.cjs +5 -0
- package/dist/uuid.d.cts +4 -0
- package/dist/uuid.d.mts +4 -0
- package/dist/uuid.mjs +4 -0
- package/package.json +24 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
node_path = require_runtime.__toESM(node_path);
|
|
5
|
+
//#region src/hotUpdateDirUtil.ts
|
|
6
|
+
const HOT_UPDATE_DIR_NAME = ".hot-updater";
|
|
7
|
+
const HOT_UPDATE_OUTPUT_DIR_NAME = "output";
|
|
8
|
+
const HOT_UPDATE_LOG_DIR_NAME = "log";
|
|
9
|
+
const HotUpdateDirUtil = {
|
|
10
|
+
dirName: HOT_UPDATE_DIR_NAME,
|
|
11
|
+
outputDirName: HOT_UPDATE_OUTPUT_DIR_NAME,
|
|
12
|
+
logDirName: HOT_UPDATE_LOG_DIR_NAME,
|
|
13
|
+
outputGitignorePath: `${HOT_UPDATE_DIR_NAME}/${HOT_UPDATE_OUTPUT_DIR_NAME}`,
|
|
14
|
+
logGitignorePath: `${HOT_UPDATE_DIR_NAME}/${HOT_UPDATE_LOG_DIR_NAME}`,
|
|
15
|
+
getDirPath: ({ cwd }) => {
|
|
16
|
+
return node_path.default.join(cwd, HOT_UPDATE_DIR_NAME);
|
|
17
|
+
},
|
|
18
|
+
getDefaultOutputPath: ({ cwd }) => {
|
|
19
|
+
return node_path.default.join(cwd, HOT_UPDATE_DIR_NAME, HOT_UPDATE_OUTPUT_DIR_NAME);
|
|
20
|
+
},
|
|
21
|
+
getLogDirPath: ({ cwd }) => {
|
|
22
|
+
return node_path.default.join(cwd, HOT_UPDATE_DIR_NAME, HOT_UPDATE_LOG_DIR_NAME);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
exports.HotUpdateDirUtil = HotUpdateDirUtil;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/hotUpdateDirUtil.d.ts
|
|
2
|
+
declare const HotUpdateDirUtil: {
|
|
3
|
+
readonly dirName: ".hot-updater";
|
|
4
|
+
readonly outputDirName: "output";
|
|
5
|
+
readonly logDirName: "log";
|
|
6
|
+
readonly outputGitignorePath: ".hot-updater/output";
|
|
7
|
+
readonly logGitignorePath: ".hot-updater/log";
|
|
8
|
+
readonly getDirPath: ({
|
|
9
|
+
cwd
|
|
10
|
+
}: {
|
|
11
|
+
cwd: string;
|
|
12
|
+
}) => string;
|
|
13
|
+
readonly getDefaultOutputPath: ({
|
|
14
|
+
cwd
|
|
15
|
+
}: {
|
|
16
|
+
cwd: string;
|
|
17
|
+
}) => string;
|
|
18
|
+
readonly getLogDirPath: ({
|
|
19
|
+
cwd
|
|
20
|
+
}: {
|
|
21
|
+
cwd: string;
|
|
22
|
+
}) => string;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { HotUpdateDirUtil };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/hotUpdateDirUtil.d.ts
|
|
2
|
+
declare const HotUpdateDirUtil: {
|
|
3
|
+
readonly dirName: ".hot-updater";
|
|
4
|
+
readonly outputDirName: "output";
|
|
5
|
+
readonly logDirName: "log";
|
|
6
|
+
readonly outputGitignorePath: ".hot-updater/output";
|
|
7
|
+
readonly logGitignorePath: ".hot-updater/log";
|
|
8
|
+
readonly getDirPath: ({
|
|
9
|
+
cwd
|
|
10
|
+
}: {
|
|
11
|
+
cwd: string;
|
|
12
|
+
}) => string;
|
|
13
|
+
readonly getDefaultOutputPath: ({
|
|
14
|
+
cwd
|
|
15
|
+
}: {
|
|
16
|
+
cwd: string;
|
|
17
|
+
}) => string;
|
|
18
|
+
readonly getLogDirPath: ({
|
|
19
|
+
cwd
|
|
20
|
+
}: {
|
|
21
|
+
cwd: string;
|
|
22
|
+
}) => string;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { HotUpdateDirUtil };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
|
|
1
|
+
import path from "node:path";
|
|
3
2
|
//#region src/hotUpdateDirUtil.ts
|
|
4
3
|
const HOT_UPDATE_DIR_NAME = ".hot-updater";
|
|
5
4
|
const HOT_UPDATE_OUTPUT_DIR_NAME = "output";
|
|
@@ -20,10 +19,5 @@ const HotUpdateDirUtil = {
|
|
|
20
19
|
return path.join(cwd, HOT_UPDATE_DIR_NAME, HOT_UPDATE_LOG_DIR_NAME);
|
|
21
20
|
}
|
|
22
21
|
};
|
|
23
|
-
|
|
24
22
|
//#endregion
|
|
25
|
-
|
|
26
|
-
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
27
|
-
|
|
28
|
-
//#endregion
|
|
29
|
-
export { HotUpdateDirUtil, NIL_UUID };
|
|
23
|
+
export { HotUpdateDirUtil };
|
package/dist/index.cjs
CHANGED
|
@@ -1,54 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
let path = require("path");
|
|
25
|
-
path = __toESM(path);
|
|
26
|
-
|
|
27
|
-
//#region src/hotUpdateDirUtil.ts
|
|
28
|
-
const HOT_UPDATE_DIR_NAME = ".hot-updater";
|
|
29
|
-
const HOT_UPDATE_OUTPUT_DIR_NAME = "output";
|
|
30
|
-
const HOT_UPDATE_LOG_DIR_NAME = "log";
|
|
31
|
-
const HotUpdateDirUtil = {
|
|
32
|
-
dirName: HOT_UPDATE_DIR_NAME,
|
|
33
|
-
outputDirName: HOT_UPDATE_OUTPUT_DIR_NAME,
|
|
34
|
-
logDirName: HOT_UPDATE_LOG_DIR_NAME,
|
|
35
|
-
outputGitignorePath: `${HOT_UPDATE_DIR_NAME}/${HOT_UPDATE_OUTPUT_DIR_NAME}`,
|
|
36
|
-
logGitignorePath: `${HOT_UPDATE_DIR_NAME}/${HOT_UPDATE_LOG_DIR_NAME}`,
|
|
37
|
-
getDirPath: ({ cwd }) => {
|
|
38
|
-
return path.default.join(cwd, HOT_UPDATE_DIR_NAME);
|
|
39
|
-
},
|
|
40
|
-
getDefaultOutputPath: ({ cwd }) => {
|
|
41
|
-
return path.default.join(cwd, HOT_UPDATE_DIR_NAME, HOT_UPDATE_OUTPUT_DIR_NAME);
|
|
42
|
-
},
|
|
43
|
-
getLogDirPath: ({ cwd }) => {
|
|
44
|
-
return path.default.join(cwd, HOT_UPDATE_DIR_NAME, HOT_UPDATE_LOG_DIR_NAME);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
//#endregion
|
|
49
|
-
//#region src/uuid.ts
|
|
50
|
-
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
51
|
-
|
|
52
|
-
//#endregion
|
|
53
|
-
exports.HotUpdateDirUtil = HotUpdateDirUtil;
|
|
54
|
-
exports.NIL_UUID = NIL_UUID;
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_hotUpdateDirUtil = require("./hotUpdateDirUtil.cjs");
|
|
3
|
+
const require_rollout = require("./rollout.cjs");
|
|
4
|
+
const require_uuid = require("./uuid.cjs");
|
|
5
|
+
exports.DEFAULT_ROLLOUT_COHORT_COUNT = require_rollout.DEFAULT_ROLLOUT_COHORT_COUNT;
|
|
6
|
+
exports.HotUpdateDirUtil = require_hotUpdateDirUtil.HotUpdateDirUtil;
|
|
7
|
+
exports.INVALID_COHORT_ERROR_MESSAGE = require_rollout.INVALID_COHORT_ERROR_MESSAGE;
|
|
8
|
+
exports.MAX_COHORT_LENGTH = require_rollout.MAX_COHORT_LENGTH;
|
|
9
|
+
exports.NIL_UUID = require_uuid.NIL_UUID;
|
|
10
|
+
exports.NUMERIC_COHORT_SIZE = require_rollout.NUMERIC_COHORT_SIZE;
|
|
11
|
+
exports.getDefaultNumericCohort = require_rollout.getDefaultNumericCohort;
|
|
12
|
+
exports.getNumericCohortRolloutPosition = require_rollout.getNumericCohortRolloutPosition;
|
|
13
|
+
exports.getNumericCohortValue = require_rollout.getNumericCohortValue;
|
|
14
|
+
exports.getRolledOutNumericCohorts = require_rollout.getRolledOutNumericCohorts;
|
|
15
|
+
exports.isCohortEligibleForUpdate = require_rollout.isCohortEligibleForUpdate;
|
|
16
|
+
exports.isCustomCohort = require_rollout.isCustomCohort;
|
|
17
|
+
exports.isNumericCohort = require_rollout.isNumericCohort;
|
|
18
|
+
exports.isValidCohort = require_rollout.isValidCohort;
|
|
19
|
+
exports.normalizeCohortValue = require_rollout.normalizeCohortValue;
|
|
20
|
+
exports.normalizeRolloutCohortCount = require_rollout.normalizeRolloutCohortCount;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,198 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly outputGitignorePath: ".hot-updater/output";
|
|
7
|
-
readonly logGitignorePath: ".hot-updater/log";
|
|
8
|
-
readonly getDirPath: ({
|
|
9
|
-
cwd
|
|
10
|
-
}: {
|
|
11
|
-
cwd: string;
|
|
12
|
-
}) => string;
|
|
13
|
-
readonly getDefaultOutputPath: ({
|
|
14
|
-
cwd
|
|
15
|
-
}: {
|
|
16
|
-
cwd: string;
|
|
17
|
-
}) => string;
|
|
18
|
-
readonly getLogDirPath: ({
|
|
19
|
-
cwd
|
|
20
|
-
}: {
|
|
21
|
-
cwd: string;
|
|
22
|
-
}) => string;
|
|
23
|
-
};
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region src/types.d.ts
|
|
26
|
-
type Platform = "ios" | "android";
|
|
27
|
-
type BundleMetadata = {
|
|
28
|
-
app_version?: string;
|
|
29
|
-
};
|
|
30
|
-
interface Bundle {
|
|
31
|
-
/**
|
|
32
|
-
* The unique identifier for the bundle. uuidv7
|
|
33
|
-
*/
|
|
34
|
-
id: string;
|
|
35
|
-
/**
|
|
36
|
-
* The platform the bundle is for.
|
|
37
|
-
*/
|
|
38
|
-
platform: Platform;
|
|
39
|
-
/**
|
|
40
|
-
* Whether the bundle should force an update.
|
|
41
|
-
*/
|
|
42
|
-
shouldForceUpdate: boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Whether the bundle is enabled.
|
|
45
|
-
*/
|
|
46
|
-
enabled: boolean;
|
|
47
|
-
/**
|
|
48
|
-
* The hash of the bundle.
|
|
49
|
-
*/
|
|
50
|
-
fileHash: string;
|
|
51
|
-
/**
|
|
52
|
-
* The storage key of the bundle.
|
|
53
|
-
* @example "s3://my-bucket/my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
54
|
-
* @example "r2://my-bucket/my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
55
|
-
* @example "firebase-storage://my-bucket/my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
56
|
-
* @example "storage://my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
57
|
-
*/
|
|
58
|
-
storageUri: string;
|
|
59
|
-
/**
|
|
60
|
-
* The git commit hash of the bundle.
|
|
61
|
-
*/
|
|
62
|
-
gitCommitHash: string | null;
|
|
63
|
-
/**
|
|
64
|
-
* The message of the bundle.
|
|
65
|
-
*/
|
|
66
|
-
message: string | null;
|
|
67
|
-
/**
|
|
68
|
-
* The name of the channel where the bundle is deployed.
|
|
69
|
-
*
|
|
70
|
-
* Examples:
|
|
71
|
-
* - production: Production channel for end users
|
|
72
|
-
* - development: Development channel for testing
|
|
73
|
-
* - staging: Staging channel for quality assurance before production
|
|
74
|
-
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
75
|
-
*
|
|
76
|
-
* Different channel values can be used based on each app's requirements.
|
|
77
|
-
*/
|
|
78
|
-
channel: string;
|
|
79
|
-
/**
|
|
80
|
-
* The target app version of the bundle.
|
|
81
|
-
*/
|
|
82
|
-
targetAppVersion: string | null;
|
|
83
|
-
/**
|
|
84
|
-
* The fingerprint hash of the bundle.
|
|
85
|
-
*/
|
|
86
|
-
fingerprintHash: string | null;
|
|
87
|
-
/**
|
|
88
|
-
* The metadata of the bundle.
|
|
89
|
-
*/
|
|
90
|
-
metadata?: BundleMetadata;
|
|
91
|
-
}
|
|
92
|
-
type SnakeCase<S extends string> = S extends `${infer T}${infer U}` ? `${T extends Capitalize<T> ? "_" : ""}${Lowercase<T>}${SnakeCase<U>}` : S;
|
|
93
|
-
type SnakeKeyObject<T$1> = T$1 extends Record<string, any> ? { [K in keyof T$1 as SnakeCase<Extract<K, string>>]: T$1[K] extends object ? SnakeKeyObject<T$1[K]> : T$1[K] } : T$1;
|
|
94
|
-
type SnakeCaseBundle = SnakeKeyObject<Bundle>;
|
|
95
|
-
type UpdateStatus = "ROLLBACK" | "UPDATE";
|
|
96
|
-
/**
|
|
97
|
-
* The update info for the database layer.
|
|
98
|
-
* This is the update info that is used by the database.
|
|
99
|
-
*/
|
|
100
|
-
interface UpdateInfo {
|
|
101
|
-
id: string;
|
|
102
|
-
shouldForceUpdate: boolean;
|
|
103
|
-
message: string | null;
|
|
104
|
-
status: UpdateStatus;
|
|
105
|
-
storageUri: string | null;
|
|
106
|
-
fileHash: string | null;
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* The update info for the app layer.
|
|
110
|
-
* This is the update info that is used by the app.
|
|
111
|
-
*/
|
|
112
|
-
interface AppUpdateInfo extends Omit<UpdateInfo, "storageUri"> {
|
|
113
|
-
fileUrl: string | null;
|
|
114
|
-
/**
|
|
115
|
-
* SHA256 hash of the bundle file, optionally with embedded signature.
|
|
116
|
-
* Format when signed: "sig:<base64_signature>"
|
|
117
|
-
* Format when unsigned: "<hex_hash>" (64-character lowercase hex)
|
|
118
|
-
* The client parses this to extract signature for native verification.
|
|
119
|
-
*/
|
|
120
|
-
fileHash: string | null;
|
|
121
|
-
}
|
|
122
|
-
type UpdateStrategy = "fingerprint" | "appVersion";
|
|
123
|
-
type FingerprintGetBundlesArgs = {
|
|
124
|
-
_updateStrategy: "fingerprint";
|
|
125
|
-
platform: Platform;
|
|
126
|
-
/**
|
|
127
|
-
* The current bundle id of the app.
|
|
128
|
-
*/
|
|
129
|
-
bundleId: string;
|
|
130
|
-
/**
|
|
131
|
-
* Minimum bundle id that should be used.
|
|
132
|
-
* This value is generated at build time via getMinBundleId().
|
|
133
|
-
*
|
|
134
|
-
* @default "00000000-0000-0000-0000-000000000000"
|
|
135
|
-
*/
|
|
136
|
-
minBundleId?: string;
|
|
137
|
-
/**
|
|
138
|
-
* The name of the channel where the bundle is deployed.
|
|
139
|
-
*
|
|
140
|
-
* @default "production"
|
|
141
|
-
*
|
|
142
|
-
* Examples:
|
|
143
|
-
* - production: Production channel for end users
|
|
144
|
-
* - development: Development channel for testing
|
|
145
|
-
* - staging: Staging channel for quality assurance before production
|
|
146
|
-
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
147
|
-
*/
|
|
148
|
-
channel?: string;
|
|
149
|
-
/**
|
|
150
|
-
* The fingerprint hash of the bundle.
|
|
151
|
-
*/
|
|
152
|
-
fingerprintHash: string;
|
|
153
|
-
};
|
|
154
|
-
type AppVersionGetBundlesArgs = {
|
|
155
|
-
_updateStrategy: "appVersion";
|
|
156
|
-
platform: Platform;
|
|
157
|
-
/**
|
|
158
|
-
* The current bundle id of the app.
|
|
159
|
-
*/
|
|
160
|
-
bundleId: string;
|
|
161
|
-
/**
|
|
162
|
-
* Minimum bundle id that should be used.
|
|
163
|
-
* This value is generated at build time via getMinBundleId().
|
|
164
|
-
*
|
|
165
|
-
* @default "00000000-0000-0000-0000-000000000000"
|
|
166
|
-
*/
|
|
167
|
-
minBundleId?: string;
|
|
168
|
-
/**
|
|
169
|
-
* The name of the channel where the bundle is deployed.
|
|
170
|
-
*
|
|
171
|
-
* @default "production"
|
|
172
|
-
*
|
|
173
|
-
* Examples:
|
|
174
|
-
* - production: Production channel for end users
|
|
175
|
-
* - development: Development channel for testing
|
|
176
|
-
* - staging: Staging channel for quality assurance before production
|
|
177
|
-
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
178
|
-
*/
|
|
179
|
-
channel?: string;
|
|
180
|
-
/**
|
|
181
|
-
* The current app version.
|
|
182
|
-
*/
|
|
183
|
-
appVersion: string;
|
|
184
|
-
};
|
|
185
|
-
type GetBundlesArgs = FingerprintGetBundlesArgs | AppVersionGetBundlesArgs;
|
|
186
|
-
type UpdateBundleParams = {
|
|
187
|
-
platform: Platform;
|
|
188
|
-
bundleId: string;
|
|
189
|
-
minBundleId: string;
|
|
190
|
-
channel: string;
|
|
191
|
-
appVersion: string;
|
|
192
|
-
fingerprintHash: string | null;
|
|
193
|
-
};
|
|
194
|
-
//#endregion
|
|
195
|
-
//#region src/uuid.d.ts
|
|
196
|
-
declare const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
197
|
-
//#endregion
|
|
198
|
-
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdateDirUtil, NIL_UUID, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy };
|
|
1
|
+
import { HotUpdateDirUtil } from "./hotUpdateDirUtil.cjs";
|
|
2
|
+
import { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount } from "./rollout.cjs";
|
|
3
|
+
import { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy } from "./types.cjs";
|
|
4
|
+
import { NIL_UUID } from "./uuid.cjs";
|
|
5
|
+
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, DEFAULT_ROLLOUT_COHORT_COUNT, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdateDirUtil, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NIL_UUID, NUMERIC_COHORT_SIZE, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { HotUpdateDirUtil } from "./hotUpdateDirUtil.mjs";
|
|
2
|
+
import { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount } from "./rollout.mjs";
|
|
3
|
+
import { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy } from "./types.mjs";
|
|
4
|
+
import { NIL_UUID } from "./uuid.mjs";
|
|
5
|
+
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, DEFAULT_ROLLOUT_COHORT_COUNT, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdateDirUtil, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NIL_UUID, NUMERIC_COHORT_SIZE, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { HotUpdateDirUtil } from "./hotUpdateDirUtil.mjs";
|
|
2
|
+
import { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount } from "./rollout.mjs";
|
|
3
|
+
import { NIL_UUID } from "./uuid.mjs";
|
|
4
|
+
export { DEFAULT_ROLLOUT_COHORT_COUNT, HotUpdateDirUtil, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NIL_UUID, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rollout = require("./rollout.cjs");
|
|
3
|
+
const require_uuid = require("./uuid.cjs");
|
|
4
|
+
exports.DEFAULT_ROLLOUT_COHORT_COUNT = require_rollout.DEFAULT_ROLLOUT_COHORT_COUNT;
|
|
5
|
+
exports.INVALID_COHORT_ERROR_MESSAGE = require_rollout.INVALID_COHORT_ERROR_MESSAGE;
|
|
6
|
+
exports.MAX_COHORT_LENGTH = require_rollout.MAX_COHORT_LENGTH;
|
|
7
|
+
exports.NIL_UUID = require_uuid.NIL_UUID;
|
|
8
|
+
exports.NUMERIC_COHORT_SIZE = require_rollout.NUMERIC_COHORT_SIZE;
|
|
9
|
+
exports.getDefaultNumericCohort = require_rollout.getDefaultNumericCohort;
|
|
10
|
+
exports.getNumericCohortRolloutPosition = require_rollout.getNumericCohortRolloutPosition;
|
|
11
|
+
exports.getNumericCohortValue = require_rollout.getNumericCohortValue;
|
|
12
|
+
exports.getRolledOutNumericCohorts = require_rollout.getRolledOutNumericCohorts;
|
|
13
|
+
exports.isCohortEligibleForUpdate = require_rollout.isCohortEligibleForUpdate;
|
|
14
|
+
exports.isCustomCohort = require_rollout.isCustomCohort;
|
|
15
|
+
exports.isNumericCohort = require_rollout.isNumericCohort;
|
|
16
|
+
exports.isValidCohort = require_rollout.isValidCohort;
|
|
17
|
+
exports.normalizeCohortValue = require_rollout.normalizeCohortValue;
|
|
18
|
+
exports.normalizeRolloutCohortCount = require_rollout.normalizeRolloutCohortCount;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount } from "./rollout.cjs";
|
|
2
|
+
import { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy } from "./types.cjs";
|
|
3
|
+
import { NIL_UUID } from "./uuid.cjs";
|
|
4
|
+
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, DEFAULT_ROLLOUT_COHORT_COUNT, FingerprintGetBundlesArgs, GetBundlesArgs, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NIL_UUID, NUMERIC_COHORT_SIZE, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount } from "./rollout.mjs";
|
|
2
|
+
import { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy } from "./types.mjs";
|
|
3
|
+
import { NIL_UUID } from "./uuid.mjs";
|
|
4
|
+
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, DEFAULT_ROLLOUT_COHORT_COUNT, FingerprintGetBundlesArgs, GetBundlesArgs, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NIL_UUID, NUMERIC_COHORT_SIZE, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount } from "./rollout.mjs";
|
|
2
|
+
import { NIL_UUID } from "./uuid.mjs";
|
|
3
|
+
export { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NIL_UUID, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
package/dist/rollout.cjs
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/rollout.ts
|
|
3
|
+
const NUMERIC_COHORT_SIZE = 1e3;
|
|
4
|
+
const DEFAULT_ROLLOUT_COHORT_COUNT = NUMERIC_COHORT_SIZE;
|
|
5
|
+
const MAX_COHORT_LENGTH = 64;
|
|
6
|
+
const INVALID_COHORT_ERROR_MESSAGE = `Invalid cohort. Use 1-1000 or a lowercase slug without spaces, up to 64 characters.`;
|
|
7
|
+
const CUSTOM_COHORT_PATTERN = /^[a-z0-9-]+$/;
|
|
8
|
+
function parseNumericCohortValue(cohort) {
|
|
9
|
+
if (!/^\d+$/.test(cohort)) return null;
|
|
10
|
+
const parsed = Number.parseInt(cohort, 10);
|
|
11
|
+
if (Number.isNaN(parsed) || parsed < 1 || parsed > 1e3) return null;
|
|
12
|
+
return parsed;
|
|
13
|
+
}
|
|
14
|
+
function positiveMod(value, modulus) {
|
|
15
|
+
return (value % modulus + modulus) % modulus;
|
|
16
|
+
}
|
|
17
|
+
function hashString(value) {
|
|
18
|
+
let hash = 0;
|
|
19
|
+
for (let i = 0; i < value.length; i++) {
|
|
20
|
+
const char = value.charCodeAt(i);
|
|
21
|
+
hash = (hash << 5) - hash + char;
|
|
22
|
+
hash |= 0;
|
|
23
|
+
}
|
|
24
|
+
return hash;
|
|
25
|
+
}
|
|
26
|
+
function gcd(a, b) {
|
|
27
|
+
let x = Math.abs(a);
|
|
28
|
+
let y = Math.abs(b);
|
|
29
|
+
while (y !== 0) {
|
|
30
|
+
const next = x % y;
|
|
31
|
+
x = y;
|
|
32
|
+
y = next;
|
|
33
|
+
}
|
|
34
|
+
return x;
|
|
35
|
+
}
|
|
36
|
+
function modularInverse(value, modulus) {
|
|
37
|
+
let t = 0;
|
|
38
|
+
let newT = 1;
|
|
39
|
+
let r = modulus;
|
|
40
|
+
let newR = positiveMod(value, modulus);
|
|
41
|
+
while (newR !== 0) {
|
|
42
|
+
const quotient = Math.floor(r / newR);
|
|
43
|
+
[t, newT] = [newT, t - quotient * newT];
|
|
44
|
+
[r, newR] = [newR, r - quotient * newR];
|
|
45
|
+
}
|
|
46
|
+
if (r > 1) throw new Error(`No modular inverse for ${value} mod ${modulus}`);
|
|
47
|
+
return positiveMod(t, modulus);
|
|
48
|
+
}
|
|
49
|
+
function getRolloutShuffleParameters(bundleId) {
|
|
50
|
+
let multiplier = positiveMod(hashString(`${bundleId}:multiplier`), 997);
|
|
51
|
+
if (multiplier === 0) multiplier = 1;
|
|
52
|
+
while (gcd(multiplier, NUMERIC_COHORT_SIZE) !== 1) {
|
|
53
|
+
multiplier = positiveMod(multiplier + 1, NUMERIC_COHORT_SIZE);
|
|
54
|
+
if (multiplier === 0) multiplier = 1;
|
|
55
|
+
}
|
|
56
|
+
const offset = positiveMod(hashString(`${bundleId}:offset`), NUMERIC_COHORT_SIZE);
|
|
57
|
+
return {
|
|
58
|
+
multiplier,
|
|
59
|
+
offset,
|
|
60
|
+
inverseMultiplier: modularInverse(multiplier, NUMERIC_COHORT_SIZE)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function normalizeRolloutCohortCount(rolloutCohortCount) {
|
|
64
|
+
if (rolloutCohortCount === null || rolloutCohortCount === void 0) return DEFAULT_ROLLOUT_COHORT_COUNT;
|
|
65
|
+
if (rolloutCohortCount <= 0) return 0;
|
|
66
|
+
if (rolloutCohortCount >= 1e3) return NUMERIC_COHORT_SIZE;
|
|
67
|
+
return Math.floor(rolloutCohortCount);
|
|
68
|
+
}
|
|
69
|
+
function normalizeCohortValue(cohort) {
|
|
70
|
+
const normalized = cohort.trim().toLowerCase();
|
|
71
|
+
const numericCohort = parseNumericCohortValue(normalized);
|
|
72
|
+
if (numericCohort !== null) return String(numericCohort);
|
|
73
|
+
return normalized;
|
|
74
|
+
}
|
|
75
|
+
function getNumericCohortValue(cohort) {
|
|
76
|
+
return parseNumericCohortValue(normalizeCohortValue(cohort));
|
|
77
|
+
}
|
|
78
|
+
function isNumericCohort(cohort) {
|
|
79
|
+
return getNumericCohortValue(cohort) !== null;
|
|
80
|
+
}
|
|
81
|
+
function isCustomCohort(cohort) {
|
|
82
|
+
const normalized = normalizeCohortValue(cohort);
|
|
83
|
+
return normalized.length > 0 && normalized.length <= 64 && !/^\d+$/.test(normalized) && CUSTOM_COHORT_PATTERN.test(normalized);
|
|
84
|
+
}
|
|
85
|
+
function isValidCohort(cohort) {
|
|
86
|
+
const normalized = normalizeCohortValue(cohort);
|
|
87
|
+
return isNumericCohort(normalized) || isCustomCohort(normalized);
|
|
88
|
+
}
|
|
89
|
+
function getDefaultNumericCohort(identifier) {
|
|
90
|
+
const cohortValue = positiveMod(hashString(identifier), NUMERIC_COHORT_SIZE) + 1;
|
|
91
|
+
return String(cohortValue);
|
|
92
|
+
}
|
|
93
|
+
function getNumericCohortRolloutPosition(bundleId, cohortValue) {
|
|
94
|
+
if (cohortValue < 1 || cohortValue > 1e3) throw new Error(`Invalid numeric cohort: ${cohortValue}`);
|
|
95
|
+
const { offset, inverseMultiplier } = getRolloutShuffleParameters(bundleId);
|
|
96
|
+
return positiveMod(inverseMultiplier * (cohortValue - 1 - offset), NUMERIC_COHORT_SIZE);
|
|
97
|
+
}
|
|
98
|
+
function getRolledOutNumericCohorts(bundleId, rolloutCohortCount) {
|
|
99
|
+
const normalizedRolloutCount = normalizeRolloutCohortCount(rolloutCohortCount);
|
|
100
|
+
if (normalizedRolloutCount <= 0) return [];
|
|
101
|
+
return Array.from({ length: NUMERIC_COHORT_SIZE }, (_, index) => index + 1).filter((cohortValue) => {
|
|
102
|
+
if (normalizedRolloutCount >= 1e3) return true;
|
|
103
|
+
return getNumericCohortRolloutPosition(bundleId, cohortValue) < normalizedRolloutCount;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function isCohortEligibleForUpdate(bundleId, cohort, rolloutCohortCount, targetCohorts) {
|
|
107
|
+
const normalizedCohort = cohort === null || cohort === void 0 ? void 0 : normalizeCohortValue(cohort);
|
|
108
|
+
const normalizedTargetCohorts = targetCohorts?.map((targetCohort) => normalizeCohortValue(targetCohort)) ?? [];
|
|
109
|
+
if (normalizedTargetCohorts.length > 0) return normalizedCohort !== void 0 && normalizedTargetCohorts.includes(normalizedCohort);
|
|
110
|
+
const normalizedRolloutCount = normalizeRolloutCohortCount(rolloutCohortCount);
|
|
111
|
+
if (normalizedRolloutCount <= 0) return false;
|
|
112
|
+
if (normalizedCohort === void 0) return normalizedRolloutCount >= NUMERIC_COHORT_SIZE;
|
|
113
|
+
const numericCohort = getNumericCohortValue(normalizedCohort);
|
|
114
|
+
if (numericCohort === null) return false;
|
|
115
|
+
if (normalizedRolloutCount >= 1e3) return true;
|
|
116
|
+
return getNumericCohortRolloutPosition(bundleId, numericCohort) < normalizedRolloutCount;
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
exports.DEFAULT_ROLLOUT_COHORT_COUNT = DEFAULT_ROLLOUT_COHORT_COUNT;
|
|
120
|
+
exports.INVALID_COHORT_ERROR_MESSAGE = INVALID_COHORT_ERROR_MESSAGE;
|
|
121
|
+
exports.MAX_COHORT_LENGTH = MAX_COHORT_LENGTH;
|
|
122
|
+
exports.NUMERIC_COHORT_SIZE = NUMERIC_COHORT_SIZE;
|
|
123
|
+
exports.getDefaultNumericCohort = getDefaultNumericCohort;
|
|
124
|
+
exports.getNumericCohortRolloutPosition = getNumericCohortRolloutPosition;
|
|
125
|
+
exports.getNumericCohortValue = getNumericCohortValue;
|
|
126
|
+
exports.getRolledOutNumericCohorts = getRolledOutNumericCohorts;
|
|
127
|
+
exports.isCohortEligibleForUpdate = isCohortEligibleForUpdate;
|
|
128
|
+
exports.isCustomCohort = isCustomCohort;
|
|
129
|
+
exports.isNumericCohort = isNumericCohort;
|
|
130
|
+
exports.isValidCohort = isValidCohort;
|
|
131
|
+
exports.normalizeCohortValue = normalizeCohortValue;
|
|
132
|
+
exports.normalizeRolloutCohortCount = normalizeRolloutCohortCount;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/rollout.d.ts
|
|
2
|
+
declare const NUMERIC_COHORT_SIZE = 1000;
|
|
3
|
+
declare const DEFAULT_ROLLOUT_COHORT_COUNT = 1000;
|
|
4
|
+
declare const MAX_COHORT_LENGTH = 64;
|
|
5
|
+
declare const INVALID_COHORT_ERROR_MESSAGE = "Invalid cohort. Use 1-1000 or a lowercase slug without spaces, up to 64 characters.";
|
|
6
|
+
declare function normalizeRolloutCohortCount(rolloutCohortCount: number | null | undefined): number;
|
|
7
|
+
declare function normalizeCohortValue(cohort: string): string;
|
|
8
|
+
declare function getNumericCohortValue(cohort: string): number | null;
|
|
9
|
+
declare function isNumericCohort(cohort: string): boolean;
|
|
10
|
+
declare function isCustomCohort(cohort: string): boolean;
|
|
11
|
+
declare function isValidCohort(cohort: string): boolean;
|
|
12
|
+
declare function getDefaultNumericCohort(identifier: string): string;
|
|
13
|
+
declare function getNumericCohortRolloutPosition(bundleId: string, cohortValue: number): number;
|
|
14
|
+
declare function getRolledOutNumericCohorts(bundleId: string, rolloutCohortCount: number | null | undefined): number[];
|
|
15
|
+
declare function isCohortEligibleForUpdate(bundleId: string, cohort: string | null | undefined, rolloutCohortCount: number | null | undefined, targetCohorts: readonly string[] | null | undefined): boolean;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/rollout.d.ts
|
|
2
|
+
declare const NUMERIC_COHORT_SIZE = 1000;
|
|
3
|
+
declare const DEFAULT_ROLLOUT_COHORT_COUNT = 1000;
|
|
4
|
+
declare const MAX_COHORT_LENGTH = 64;
|
|
5
|
+
declare const INVALID_COHORT_ERROR_MESSAGE = "Invalid cohort. Use 1-1000 or a lowercase slug without spaces, up to 64 characters.";
|
|
6
|
+
declare function normalizeRolloutCohortCount(rolloutCohortCount: number | null | undefined): number;
|
|
7
|
+
declare function normalizeCohortValue(cohort: string): string;
|
|
8
|
+
declare function getNumericCohortValue(cohort: string): number | null;
|
|
9
|
+
declare function isNumericCohort(cohort: string): boolean;
|
|
10
|
+
declare function isCustomCohort(cohort: string): boolean;
|
|
11
|
+
declare function isValidCohort(cohort: string): boolean;
|
|
12
|
+
declare function getDefaultNumericCohort(identifier: string): string;
|
|
13
|
+
declare function getNumericCohortRolloutPosition(bundleId: string, cohortValue: number): number;
|
|
14
|
+
declare function getRolledOutNumericCohorts(bundleId: string, rolloutCohortCount: number | null | undefined): number[];
|
|
15
|
+
declare function isCohortEligibleForUpdate(bundleId: string, cohort: string | null | undefined, rolloutCohortCount: number | null | undefined, targetCohorts: readonly string[] | null | undefined): boolean;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
package/dist/rollout.mjs
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//#region src/rollout.ts
|
|
2
|
+
const NUMERIC_COHORT_SIZE = 1e3;
|
|
3
|
+
const DEFAULT_ROLLOUT_COHORT_COUNT = NUMERIC_COHORT_SIZE;
|
|
4
|
+
const MAX_COHORT_LENGTH = 64;
|
|
5
|
+
const INVALID_COHORT_ERROR_MESSAGE = `Invalid cohort. Use 1-1000 or a lowercase slug without spaces, up to 64 characters.`;
|
|
6
|
+
const CUSTOM_COHORT_PATTERN = /^[a-z0-9-]+$/;
|
|
7
|
+
function parseNumericCohortValue(cohort) {
|
|
8
|
+
if (!/^\d+$/.test(cohort)) return null;
|
|
9
|
+
const parsed = Number.parseInt(cohort, 10);
|
|
10
|
+
if (Number.isNaN(parsed) || parsed < 1 || parsed > 1e3) return null;
|
|
11
|
+
return parsed;
|
|
12
|
+
}
|
|
13
|
+
function positiveMod(value, modulus) {
|
|
14
|
+
return (value % modulus + modulus) % modulus;
|
|
15
|
+
}
|
|
16
|
+
function hashString(value) {
|
|
17
|
+
let hash = 0;
|
|
18
|
+
for (let i = 0; i < value.length; i++) {
|
|
19
|
+
const char = value.charCodeAt(i);
|
|
20
|
+
hash = (hash << 5) - hash + char;
|
|
21
|
+
hash |= 0;
|
|
22
|
+
}
|
|
23
|
+
return hash;
|
|
24
|
+
}
|
|
25
|
+
function gcd(a, b) {
|
|
26
|
+
let x = Math.abs(a);
|
|
27
|
+
let y = Math.abs(b);
|
|
28
|
+
while (y !== 0) {
|
|
29
|
+
const next = x % y;
|
|
30
|
+
x = y;
|
|
31
|
+
y = next;
|
|
32
|
+
}
|
|
33
|
+
return x;
|
|
34
|
+
}
|
|
35
|
+
function modularInverse(value, modulus) {
|
|
36
|
+
let t = 0;
|
|
37
|
+
let newT = 1;
|
|
38
|
+
let r = modulus;
|
|
39
|
+
let newR = positiveMod(value, modulus);
|
|
40
|
+
while (newR !== 0) {
|
|
41
|
+
const quotient = Math.floor(r / newR);
|
|
42
|
+
[t, newT] = [newT, t - quotient * newT];
|
|
43
|
+
[r, newR] = [newR, r - quotient * newR];
|
|
44
|
+
}
|
|
45
|
+
if (r > 1) throw new Error(`No modular inverse for ${value} mod ${modulus}`);
|
|
46
|
+
return positiveMod(t, modulus);
|
|
47
|
+
}
|
|
48
|
+
function getRolloutShuffleParameters(bundleId) {
|
|
49
|
+
let multiplier = positiveMod(hashString(`${bundleId}:multiplier`), 997);
|
|
50
|
+
if (multiplier === 0) multiplier = 1;
|
|
51
|
+
while (gcd(multiplier, NUMERIC_COHORT_SIZE) !== 1) {
|
|
52
|
+
multiplier = positiveMod(multiplier + 1, NUMERIC_COHORT_SIZE);
|
|
53
|
+
if (multiplier === 0) multiplier = 1;
|
|
54
|
+
}
|
|
55
|
+
const offset = positiveMod(hashString(`${bundleId}:offset`), NUMERIC_COHORT_SIZE);
|
|
56
|
+
return {
|
|
57
|
+
multiplier,
|
|
58
|
+
offset,
|
|
59
|
+
inverseMultiplier: modularInverse(multiplier, NUMERIC_COHORT_SIZE)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function normalizeRolloutCohortCount(rolloutCohortCount) {
|
|
63
|
+
if (rolloutCohortCount === null || rolloutCohortCount === void 0) return DEFAULT_ROLLOUT_COHORT_COUNT;
|
|
64
|
+
if (rolloutCohortCount <= 0) return 0;
|
|
65
|
+
if (rolloutCohortCount >= 1e3) return NUMERIC_COHORT_SIZE;
|
|
66
|
+
return Math.floor(rolloutCohortCount);
|
|
67
|
+
}
|
|
68
|
+
function normalizeCohortValue(cohort) {
|
|
69
|
+
const normalized = cohort.trim().toLowerCase();
|
|
70
|
+
const numericCohort = parseNumericCohortValue(normalized);
|
|
71
|
+
if (numericCohort !== null) return String(numericCohort);
|
|
72
|
+
return normalized;
|
|
73
|
+
}
|
|
74
|
+
function getNumericCohortValue(cohort) {
|
|
75
|
+
return parseNumericCohortValue(normalizeCohortValue(cohort));
|
|
76
|
+
}
|
|
77
|
+
function isNumericCohort(cohort) {
|
|
78
|
+
return getNumericCohortValue(cohort) !== null;
|
|
79
|
+
}
|
|
80
|
+
function isCustomCohort(cohort) {
|
|
81
|
+
const normalized = normalizeCohortValue(cohort);
|
|
82
|
+
return normalized.length > 0 && normalized.length <= 64 && !/^\d+$/.test(normalized) && CUSTOM_COHORT_PATTERN.test(normalized);
|
|
83
|
+
}
|
|
84
|
+
function isValidCohort(cohort) {
|
|
85
|
+
const normalized = normalizeCohortValue(cohort);
|
|
86
|
+
return isNumericCohort(normalized) || isCustomCohort(normalized);
|
|
87
|
+
}
|
|
88
|
+
function getDefaultNumericCohort(identifier) {
|
|
89
|
+
const cohortValue = positiveMod(hashString(identifier), NUMERIC_COHORT_SIZE) + 1;
|
|
90
|
+
return String(cohortValue);
|
|
91
|
+
}
|
|
92
|
+
function getNumericCohortRolloutPosition(bundleId, cohortValue) {
|
|
93
|
+
if (cohortValue < 1 || cohortValue > 1e3) throw new Error(`Invalid numeric cohort: ${cohortValue}`);
|
|
94
|
+
const { offset, inverseMultiplier } = getRolloutShuffleParameters(bundleId);
|
|
95
|
+
return positiveMod(inverseMultiplier * (cohortValue - 1 - offset), NUMERIC_COHORT_SIZE);
|
|
96
|
+
}
|
|
97
|
+
function getRolledOutNumericCohorts(bundleId, rolloutCohortCount) {
|
|
98
|
+
const normalizedRolloutCount = normalizeRolloutCohortCount(rolloutCohortCount);
|
|
99
|
+
if (normalizedRolloutCount <= 0) return [];
|
|
100
|
+
return Array.from({ length: NUMERIC_COHORT_SIZE }, (_, index) => index + 1).filter((cohortValue) => {
|
|
101
|
+
if (normalizedRolloutCount >= 1e3) return true;
|
|
102
|
+
return getNumericCohortRolloutPosition(bundleId, cohortValue) < normalizedRolloutCount;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function isCohortEligibleForUpdate(bundleId, cohort, rolloutCohortCount, targetCohorts) {
|
|
106
|
+
const normalizedCohort = cohort === null || cohort === void 0 ? void 0 : normalizeCohortValue(cohort);
|
|
107
|
+
const normalizedTargetCohorts = targetCohorts?.map((targetCohort) => normalizeCohortValue(targetCohort)) ?? [];
|
|
108
|
+
if (normalizedTargetCohorts.length > 0) return normalizedCohort !== void 0 && normalizedTargetCohorts.includes(normalizedCohort);
|
|
109
|
+
const normalizedRolloutCount = normalizeRolloutCohortCount(rolloutCohortCount);
|
|
110
|
+
if (normalizedRolloutCount <= 0) return false;
|
|
111
|
+
if (normalizedCohort === void 0) return normalizedRolloutCount >= NUMERIC_COHORT_SIZE;
|
|
112
|
+
const numericCohort = getNumericCohortValue(normalizedCohort);
|
|
113
|
+
if (numericCohort === null) return false;
|
|
114
|
+
if (normalizedRolloutCount >= 1e3) return true;
|
|
115
|
+
return getNumericCohortRolloutPosition(bundleId, numericCohort) < normalizedRolloutCount;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, NUMERIC_COHORT_SIZE, getDefaultNumericCohort, getNumericCohortRolloutPosition, getNumericCohortValue, getRolledOutNumericCohorts, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isValidCohort, normalizeCohortValue, normalizeRolloutCohortCount };
|
package/dist/types.cjs
ADDED
|
File without changes
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
//#region src/hotUpdateDirUtil.d.ts
|
|
2
|
-
declare const HotUpdateDirUtil: {
|
|
3
|
-
readonly dirName: ".hot-updater";
|
|
4
|
-
readonly outputDirName: "output";
|
|
5
|
-
readonly logDirName: "log";
|
|
6
|
-
readonly outputGitignorePath: ".hot-updater/output";
|
|
7
|
-
readonly logGitignorePath: ".hot-updater/log";
|
|
8
|
-
readonly getDirPath: ({
|
|
9
|
-
cwd
|
|
10
|
-
}: {
|
|
11
|
-
cwd: string;
|
|
12
|
-
}) => string;
|
|
13
|
-
readonly getDefaultOutputPath: ({
|
|
14
|
-
cwd
|
|
15
|
-
}: {
|
|
16
|
-
cwd: string;
|
|
17
|
-
}) => string;
|
|
18
|
-
readonly getLogDirPath: ({
|
|
19
|
-
cwd
|
|
20
|
-
}: {
|
|
21
|
-
cwd: string;
|
|
22
|
-
}) => string;
|
|
23
|
-
};
|
|
24
|
-
//#endregion
|
|
25
1
|
//#region src/types.d.ts
|
|
26
2
|
type Platform = "ios" | "android";
|
|
27
3
|
type BundleMetadata = {
|
|
@@ -88,9 +64,28 @@ interface Bundle {
|
|
|
88
64
|
* The metadata of the bundle.
|
|
89
65
|
*/
|
|
90
66
|
metadata?: BundleMetadata;
|
|
67
|
+
/**
|
|
68
|
+
* Rollout cohort count (0-1000). Controls gradual rollout to numeric cohorts.
|
|
69
|
+
* - 0: No cohorts receive this update
|
|
70
|
+
* - 250: 25.0% of numeric cohorts receive this update
|
|
71
|
+
* - 1000 or null: All numeric cohorts receive this update (full rollout)
|
|
72
|
+
*
|
|
73
|
+
* @default 1000
|
|
74
|
+
*/
|
|
75
|
+
rolloutCohortCount?: number | null;
|
|
76
|
+
/**
|
|
77
|
+
* Target specific cohorts for this update.
|
|
78
|
+
* If provided, only these cohorts will receive the update.
|
|
79
|
+
* If empty/null, rolloutCohortCount-based rollout is used.
|
|
80
|
+
*
|
|
81
|
+
* NOTE: This field is stored in database but should NOT be returned to
|
|
82
|
+
* update-check clients for security reasons. Server uses it for rollout
|
|
83
|
+
* decisions only.
|
|
84
|
+
*/
|
|
85
|
+
targetCohorts?: string[] | null;
|
|
91
86
|
}
|
|
92
|
-
type SnakeCase<S extends string> = S extends `${infer T}${infer U}` ?
|
|
93
|
-
type SnakeKeyObject<T
|
|
87
|
+
type SnakeCase<S extends string> = S extends `${infer T}${infer U}` ? T extends "_" ? `_${SnakeCase<U>}` : T extends "-" ? `-${SnakeCase<U>}` : T extends Lowercase<T> ? `${T}${SnakeCase<U>}` : `_${Lowercase<T>}${SnakeCase<U>}` : S;
|
|
88
|
+
type SnakeKeyObject<T> = T extends readonly (infer U)[] ? SnakeKeyObject<U>[] : T extends Record<string, any> ? { [K in keyof T as SnakeCase<Extract<K, string>>]: SnakeKeyObject<T[K]> } : T;
|
|
94
89
|
type SnakeCaseBundle = SnakeKeyObject<Bundle>;
|
|
95
90
|
type UpdateStatus = "ROLLBACK" | "UPDATE";
|
|
96
91
|
/**
|
|
@@ -104,6 +99,15 @@ interface UpdateInfo {
|
|
|
104
99
|
status: UpdateStatus;
|
|
105
100
|
storageUri: string | null;
|
|
106
101
|
fileHash: string | null;
|
|
102
|
+
/**
|
|
103
|
+
* Rollout cohort count (0-1000). Controls gradual rollout to numeric cohorts.
|
|
104
|
+
*/
|
|
105
|
+
rolloutCohortCount?: number | null;
|
|
106
|
+
/**
|
|
107
|
+
* Target specific cohorts for this update.
|
|
108
|
+
* Used internally for rollout decisions.
|
|
109
|
+
*/
|
|
110
|
+
targetCohorts?: string[] | null;
|
|
107
111
|
}
|
|
108
112
|
/**
|
|
109
113
|
* The update info for the app layer.
|
|
@@ -146,6 +150,10 @@ type FingerprintGetBundlesArgs = {
|
|
|
146
150
|
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
147
151
|
*/
|
|
148
152
|
channel?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Cohort identifier used for server-side rollout decisions.
|
|
155
|
+
*/
|
|
156
|
+
cohort?: string;
|
|
149
157
|
/**
|
|
150
158
|
* The fingerprint hash of the bundle.
|
|
151
159
|
*/
|
|
@@ -177,6 +185,10 @@ type AppVersionGetBundlesArgs = {
|
|
|
177
185
|
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
178
186
|
*/
|
|
179
187
|
channel?: string;
|
|
188
|
+
/**
|
|
189
|
+
* Cohort identifier used for server-side rollout decisions.
|
|
190
|
+
*/
|
|
191
|
+
cohort?: string;
|
|
180
192
|
/**
|
|
181
193
|
* The current app version.
|
|
182
194
|
*/
|
|
@@ -192,7 +204,4 @@ type UpdateBundleParams = {
|
|
|
192
204
|
fingerprintHash: string | null;
|
|
193
205
|
};
|
|
194
206
|
//#endregion
|
|
195
|
-
|
|
196
|
-
declare const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
197
|
-
//#endregion
|
|
198
|
-
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdateDirUtil, NIL_UUID, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy };
|
|
207
|
+
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy };
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type Platform = "ios" | "android";
|
|
3
|
+
type BundleMetadata = {
|
|
4
|
+
app_version?: string;
|
|
5
|
+
};
|
|
6
|
+
interface Bundle {
|
|
7
|
+
/**
|
|
8
|
+
* The unique identifier for the bundle. uuidv7
|
|
9
|
+
*/
|
|
10
|
+
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* The platform the bundle is for.
|
|
13
|
+
*/
|
|
14
|
+
platform: Platform;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the bundle should force an update.
|
|
17
|
+
*/
|
|
18
|
+
shouldForceUpdate: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the bundle is enabled.
|
|
21
|
+
*/
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The hash of the bundle.
|
|
25
|
+
*/
|
|
26
|
+
fileHash: string;
|
|
27
|
+
/**
|
|
28
|
+
* The storage key of the bundle.
|
|
29
|
+
* @example "s3://my-bucket/my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
30
|
+
* @example "r2://my-bucket/my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
31
|
+
* @example "firebase-storage://my-bucket/my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
32
|
+
* @example "storage://my-app/00000000-0000-0000-0000-000000000000/bundle.zip"
|
|
33
|
+
*/
|
|
34
|
+
storageUri: string;
|
|
35
|
+
/**
|
|
36
|
+
* The git commit hash of the bundle.
|
|
37
|
+
*/
|
|
38
|
+
gitCommitHash: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* The message of the bundle.
|
|
41
|
+
*/
|
|
42
|
+
message: string | null;
|
|
43
|
+
/**
|
|
44
|
+
* The name of the channel where the bundle is deployed.
|
|
45
|
+
*
|
|
46
|
+
* Examples:
|
|
47
|
+
* - production: Production channel for end users
|
|
48
|
+
* - development: Development channel for testing
|
|
49
|
+
* - staging: Staging channel for quality assurance before production
|
|
50
|
+
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
51
|
+
*
|
|
52
|
+
* Different channel values can be used based on each app's requirements.
|
|
53
|
+
*/
|
|
54
|
+
channel: string;
|
|
55
|
+
/**
|
|
56
|
+
* The target app version of the bundle.
|
|
57
|
+
*/
|
|
58
|
+
targetAppVersion: string | null;
|
|
59
|
+
/**
|
|
60
|
+
* The fingerprint hash of the bundle.
|
|
61
|
+
*/
|
|
62
|
+
fingerprintHash: string | null;
|
|
63
|
+
/**
|
|
64
|
+
* The metadata of the bundle.
|
|
65
|
+
*/
|
|
66
|
+
metadata?: BundleMetadata;
|
|
67
|
+
/**
|
|
68
|
+
* Rollout cohort count (0-1000). Controls gradual rollout to numeric cohorts.
|
|
69
|
+
* - 0: No cohorts receive this update
|
|
70
|
+
* - 250: 25.0% of numeric cohorts receive this update
|
|
71
|
+
* - 1000 or null: All numeric cohorts receive this update (full rollout)
|
|
72
|
+
*
|
|
73
|
+
* @default 1000
|
|
74
|
+
*/
|
|
75
|
+
rolloutCohortCount?: number | null;
|
|
76
|
+
/**
|
|
77
|
+
* Target specific cohorts for this update.
|
|
78
|
+
* If provided, only these cohorts will receive the update.
|
|
79
|
+
* If empty/null, rolloutCohortCount-based rollout is used.
|
|
80
|
+
*
|
|
81
|
+
* NOTE: This field is stored in database but should NOT be returned to
|
|
82
|
+
* update-check clients for security reasons. Server uses it for rollout
|
|
83
|
+
* decisions only.
|
|
84
|
+
*/
|
|
85
|
+
targetCohorts?: string[] | null;
|
|
86
|
+
}
|
|
87
|
+
type SnakeCase<S extends string> = S extends `${infer T}${infer U}` ? T extends "_" ? `_${SnakeCase<U>}` : T extends "-" ? `-${SnakeCase<U>}` : T extends Lowercase<T> ? `${T}${SnakeCase<U>}` : `_${Lowercase<T>}${SnakeCase<U>}` : S;
|
|
88
|
+
type SnakeKeyObject<T> = T extends readonly (infer U)[] ? SnakeKeyObject<U>[] : T extends Record<string, any> ? { [K in keyof T as SnakeCase<Extract<K, string>>]: SnakeKeyObject<T[K]> } : T;
|
|
89
|
+
type SnakeCaseBundle = SnakeKeyObject<Bundle>;
|
|
90
|
+
type UpdateStatus = "ROLLBACK" | "UPDATE";
|
|
91
|
+
/**
|
|
92
|
+
* The update info for the database layer.
|
|
93
|
+
* This is the update info that is used by the database.
|
|
94
|
+
*/
|
|
95
|
+
interface UpdateInfo {
|
|
96
|
+
id: string;
|
|
97
|
+
shouldForceUpdate: boolean;
|
|
98
|
+
message: string | null;
|
|
99
|
+
status: UpdateStatus;
|
|
100
|
+
storageUri: string | null;
|
|
101
|
+
fileHash: string | null;
|
|
102
|
+
/**
|
|
103
|
+
* Rollout cohort count (0-1000). Controls gradual rollout to numeric cohorts.
|
|
104
|
+
*/
|
|
105
|
+
rolloutCohortCount?: number | null;
|
|
106
|
+
/**
|
|
107
|
+
* Target specific cohorts for this update.
|
|
108
|
+
* Used internally for rollout decisions.
|
|
109
|
+
*/
|
|
110
|
+
targetCohorts?: string[] | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The update info for the app layer.
|
|
114
|
+
* This is the update info that is used by the app.
|
|
115
|
+
*/
|
|
116
|
+
interface AppUpdateInfo extends Omit<UpdateInfo, "storageUri"> {
|
|
117
|
+
fileUrl: string | null;
|
|
118
|
+
/**
|
|
119
|
+
* SHA256 hash of the bundle file, optionally with embedded signature.
|
|
120
|
+
* Format when signed: "sig:<base64_signature>"
|
|
121
|
+
* Format when unsigned: "<hex_hash>" (64-character lowercase hex)
|
|
122
|
+
* The client parses this to extract signature for native verification.
|
|
123
|
+
*/
|
|
124
|
+
fileHash: string | null;
|
|
125
|
+
}
|
|
126
|
+
type UpdateStrategy = "fingerprint" | "appVersion";
|
|
127
|
+
type FingerprintGetBundlesArgs = {
|
|
128
|
+
_updateStrategy: "fingerprint";
|
|
129
|
+
platform: Platform;
|
|
130
|
+
/**
|
|
131
|
+
* The current bundle id of the app.
|
|
132
|
+
*/
|
|
133
|
+
bundleId: string;
|
|
134
|
+
/**
|
|
135
|
+
* Minimum bundle id that should be used.
|
|
136
|
+
* This value is generated at build time via getMinBundleId().
|
|
137
|
+
*
|
|
138
|
+
* @default "00000000-0000-0000-0000-000000000000"
|
|
139
|
+
*/
|
|
140
|
+
minBundleId?: string;
|
|
141
|
+
/**
|
|
142
|
+
* The name of the channel where the bundle is deployed.
|
|
143
|
+
*
|
|
144
|
+
* @default "production"
|
|
145
|
+
*
|
|
146
|
+
* Examples:
|
|
147
|
+
* - production: Production channel for end users
|
|
148
|
+
* - development: Development channel for testing
|
|
149
|
+
* - staging: Staging channel for quality assurance before production
|
|
150
|
+
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
151
|
+
*/
|
|
152
|
+
channel?: string;
|
|
153
|
+
/**
|
|
154
|
+
* Cohort identifier used for server-side rollout decisions.
|
|
155
|
+
*/
|
|
156
|
+
cohort?: string;
|
|
157
|
+
/**
|
|
158
|
+
* The fingerprint hash of the bundle.
|
|
159
|
+
*/
|
|
160
|
+
fingerprintHash: string;
|
|
161
|
+
};
|
|
162
|
+
type AppVersionGetBundlesArgs = {
|
|
163
|
+
_updateStrategy: "appVersion";
|
|
164
|
+
platform: Platform;
|
|
165
|
+
/**
|
|
166
|
+
* The current bundle id of the app.
|
|
167
|
+
*/
|
|
168
|
+
bundleId: string;
|
|
169
|
+
/**
|
|
170
|
+
* Minimum bundle id that should be used.
|
|
171
|
+
* This value is generated at build time via getMinBundleId().
|
|
172
|
+
*
|
|
173
|
+
* @default "00000000-0000-0000-0000-000000000000"
|
|
174
|
+
*/
|
|
175
|
+
minBundleId?: string;
|
|
176
|
+
/**
|
|
177
|
+
* The name of the channel where the bundle is deployed.
|
|
178
|
+
*
|
|
179
|
+
* @default "production"
|
|
180
|
+
*
|
|
181
|
+
* Examples:
|
|
182
|
+
* - production: Production channel for end users
|
|
183
|
+
* - development: Development channel for testing
|
|
184
|
+
* - staging: Staging channel for quality assurance before production
|
|
185
|
+
* - app-name: Channel for specific app instances (e.g., my-app, app-test)
|
|
186
|
+
*/
|
|
187
|
+
channel?: string;
|
|
188
|
+
/**
|
|
189
|
+
* Cohort identifier used for server-side rollout decisions.
|
|
190
|
+
*/
|
|
191
|
+
cohort?: string;
|
|
192
|
+
/**
|
|
193
|
+
* The current app version.
|
|
194
|
+
*/
|
|
195
|
+
appVersion: string;
|
|
196
|
+
};
|
|
197
|
+
type GetBundlesArgs = FingerprintGetBundlesArgs | AppVersionGetBundlesArgs;
|
|
198
|
+
type UpdateBundleParams = {
|
|
199
|
+
platform: Platform;
|
|
200
|
+
bundleId: string;
|
|
201
|
+
minBundleId: string;
|
|
202
|
+
channel: string;
|
|
203
|
+
appVersion: string;
|
|
204
|
+
fingerprintHash: string | null;
|
|
205
|
+
};
|
|
206
|
+
//#endregion
|
|
207
|
+
export { AppUpdateInfo, AppVersionGetBundlesArgs, Bundle, BundleMetadata, FingerprintGetBundlesArgs, GetBundlesArgs, Platform, SnakeCaseBundle, UpdateBundleParams, UpdateInfo, UpdateStatus, UpdateStrategy };
|
package/dist/types.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/uuid.cjs
ADDED
package/dist/uuid.d.cts
ADDED
package/dist/uuid.d.mts
ADDED
package/dist/uuid.mjs
ADDED
package/package.json
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
8
|
-
"module": "./dist/index.
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"react-native": "./dist/react-native.mjs",
|
|
9
10
|
"types": "./dist/index.d.cts",
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
12
|
-
"import": "./dist/index.
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
13
14
|
"require": "./dist/index.cjs"
|
|
14
15
|
},
|
|
16
|
+
"./hotUpdateDirUtil": {
|
|
17
|
+
"import": "./dist/hotUpdateDirUtil.mjs",
|
|
18
|
+
"require": "./dist/hotUpdateDirUtil.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./react-native": {
|
|
21
|
+
"import": "./dist/react-native.mjs",
|
|
22
|
+
"require": "./dist/react-native.cjs"
|
|
23
|
+
},
|
|
24
|
+
"./rollout": {
|
|
25
|
+
"import": "./dist/rollout.mjs",
|
|
26
|
+
"require": "./dist/rollout.cjs"
|
|
27
|
+
},
|
|
28
|
+
"./types": {
|
|
29
|
+
"import": "./dist/types.mjs",
|
|
30
|
+
"require": "./dist/types.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./uuid": {
|
|
33
|
+
"import": "./dist/uuid.mjs",
|
|
34
|
+
"require": "./dist/uuid.cjs"
|
|
35
|
+
},
|
|
15
36
|
"./package.json": "./package.json"
|
|
16
37
|
},
|
|
17
38
|
"files": [
|