@otakit/cli 1.1.2 → 1.3.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/commands/compatibility.d.ts +3 -0
- package/dist/commands/compatibility.d.ts.map +1 -0
- package/dist/commands/compatibility.js +40 -0
- package/dist/commands/compatibility.js.map +1 -0
- package/dist/commands/generate-encryption-key.d.ts +3 -0
- package/dist/commands/generate-encryption-key.d.ts.map +1 -0
- package/dist/commands/generate-encryption-key.js +31 -0
- package/dist/commands/generate-encryption-key.js.map +1 -0
- package/dist/commands/release.d.ts.map +1 -1
- package/dist/commands/release.js +7 -4
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/releases.d.ts.map +1 -1
- package/dist/commands/releases.js +2 -1
- package/dist/commands/releases.js.map +1 -1
- package/dist/commands/upload.d.ts.map +1 -1
- package/dist/commands/upload.js +60 -2
- package/dist/commands/upload.js.map +1 -1
- package/dist/commands/whoami.d.ts.map +1 -1
- package/dist/commands/whoami.js +1 -4
- package/dist/commands/whoami.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +43 -1
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +21 -2
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/capacitor-config.d.ts +2 -0
- package/dist/lib/capacitor-config.d.ts.map +1 -1
- package/dist/lib/capacitor-config.js +11 -0
- package/dist/lib/capacitor-config.js.map +1 -1
- package/dist/lib/compat-check.d.ts +16 -0
- package/dist/lib/compat-check.d.ts.map +1 -0
- package/dist/lib/compat-check.js +26 -0
- package/dist/lib/compat-check.js.map +1 -0
- package/dist/lib/config.d.ts +3 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +11 -10
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/crypto.d.ts +32 -0
- package/dist/lib/crypto.d.ts.map +1 -0
- package/dist/lib/crypto.js +67 -0
- package/dist/lib/crypto.js.map +1 -0
- package/dist/lib/hash.d.ts +9 -0
- package/dist/lib/hash.d.ts.map +1 -1
- package/dist/lib/hash.js +18 -0
- package/dist/lib/hash.js.map +1 -1
- package/dist/lib/native-deps.d.ts +42 -0
- package/dist/lib/native-deps.d.ts.map +1 -0
- package/dist/lib/native-deps.js +233 -0
- package/dist/lib/native-deps.js.map +1 -0
- package/dist/lib/upload-workflow.d.ts +19 -1
- package/dist/lib/upload-workflow.d.ts.map +1 -1
- package/dist/lib/upload-workflow.js +188 -10
- package/dist/lib/upload-workflow.js.map +1 -1
- package/package.json +6 -4
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ApiClient } from './api.js';
|
|
2
|
+
import { type CompatibilityResult, type NativePackage } from './native-deps.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the channel's current (non-reverted) release in the same
|
|
5
|
+
* runtimeVersion lane and compare the local native set against its bundle.
|
|
6
|
+
*
|
|
7
|
+
* Returns `skipped` when the channel has no current release in this lane or
|
|
8
|
+
* the current bundle predates native package capture.
|
|
9
|
+
*/
|
|
10
|
+
export declare function checkCompatibilityAgainstChannel(options: {
|
|
11
|
+
api: ApiClient;
|
|
12
|
+
channel: string | null;
|
|
13
|
+
runtimeVersion: string | undefined;
|
|
14
|
+
nativePackages: NativePackage[];
|
|
15
|
+
}): Promise<CompatibilityResult>;
|
|
16
|
+
//# sourceMappingURL=compat-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat-check.d.ts","sourceRoot":"","sources":["../../src/lib/compat-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAiB,KAAK,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE/F;;;;;;GAMG;AACH,wBAAsB,gCAAgC,CAAC,OAAO,EAAE;IAC9D,GAAG,EAAE,SAAS,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,cAAc,EAAE,aAAa,EAAE,CAAC;CACjC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqB/B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { compareNative } from './native-deps.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the channel's current (non-reverted) release in the same
|
|
4
|
+
* runtimeVersion lane and compare the local native set against its bundle.
|
|
5
|
+
*
|
|
6
|
+
* Returns `skipped` when the channel has no current release in this lane or
|
|
7
|
+
* the current bundle predates native package capture.
|
|
8
|
+
*/
|
|
9
|
+
export async function checkCompatibilityAgainstChannel(options) {
|
|
10
|
+
const { api, channel, runtimeVersion, nativePackages } = options;
|
|
11
|
+
// 200 is the API's max page size; a channel whose lane baseline sits
|
|
12
|
+
// deeper than 200 releases back is treated as skipped (no baseline).
|
|
13
|
+
const { releases } = await api.listReleases(channel, { limit: 200 });
|
|
14
|
+
const lane = runtimeVersion ?? null;
|
|
15
|
+
const currentRelease = releases.find((release) => !release.revertedAt && (release.runtimeVersion ?? null) === lane);
|
|
16
|
+
if (!currentRelease) {
|
|
17
|
+
return { status: 'skipped', findings: [] };
|
|
18
|
+
}
|
|
19
|
+
const bundle = await api.getBundle(currentRelease.bundleId);
|
|
20
|
+
const remote = bundle.nativePackages;
|
|
21
|
+
if (remote === null || remote === undefined) {
|
|
22
|
+
return { status: 'skipped', findings: [] };
|
|
23
|
+
}
|
|
24
|
+
return compareNative(nativePackages, remote);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=compat-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat-check.js","sourceRoot":"","sources":["../../src/lib/compat-check.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAgD,MAAM,kBAAkB,CAAC;AAE/F;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CAAC,OAKtD;IACC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAEjE,qEAAqE;IACrE,qEAAqE;IACrE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,cAAc,IAAI,IAAI,CAAC;IACpC,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAClC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,KAAK,IAAI,CAC9E,CAAC;IACF,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC;IACrC,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,aAAa,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface ProjectConfig {
|
|
|
18
18
|
appId?: string;
|
|
19
19
|
channel?: string;
|
|
20
20
|
runtimeVersion?: string;
|
|
21
|
+
updateStrategy?: 'zip' | 'deltas';
|
|
21
22
|
configuredServerUrl?: string;
|
|
22
23
|
outputDir?: string;
|
|
23
24
|
}
|
|
@@ -25,6 +26,7 @@ export interface CliConfig extends ServerAuthConfig {
|
|
|
25
26
|
appId: string;
|
|
26
27
|
channel?: string;
|
|
27
28
|
runtimeVersion?: string;
|
|
29
|
+
updateStrategy?: 'zip' | 'deltas';
|
|
28
30
|
outputDir?: string;
|
|
29
31
|
}
|
|
30
32
|
export interface ConfigResolveOptions {
|
|
@@ -45,6 +47,7 @@ export interface ConfigResolveSnapshot {
|
|
|
45
47
|
outputDir: ResolvedValue<string | null>;
|
|
46
48
|
channel: ResolvedValue<string | null>;
|
|
47
49
|
runtimeVersion: ResolvedValue<string | null>;
|
|
50
|
+
updateStrategy: ResolvedValue<'zip' | 'deltas' | null>;
|
|
48
51
|
authToken: ResolvedValue<string | null>;
|
|
49
52
|
authSource: AuthSource | null;
|
|
50
53
|
}
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AAKzD,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,kBAAkB,GAAG,MAAM,GAAG,gBAAgB,CAAC;AAEtF,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAExF,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,KAAK,EAAE,CAAC,CAAC;IACT,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,gBAAgB;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,KAAK,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,OAAO,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtC,cAAc,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,SAAS,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAetD;AAsBD,wBAAgB,gBAAgB,CAC9B,IAAI,GAAE,MAAsB,EAC5B,iBAAiB,CAAC,EAAE,MAAM,EAC1B,mBAAmB,CAAC,EAAE,MAAM,GAC3B,MAAM,CAQR;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAY3F;AAED,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,OAAO,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.js
CHANGED
|
@@ -62,11 +62,7 @@ export async function requireServerAndAuth(options) {
|
|
|
62
62
|
const serverUrl = resolveServerUrl(cwd, options?.serverUrl, options?.projectServerUrl);
|
|
63
63
|
const auth = await resolveAuthToken(serverUrl);
|
|
64
64
|
if (!auth) {
|
|
65
|
-
throw new Error([
|
|
66
|
-
'Missing authentication:',
|
|
67
|
-
'- Run `otakit login`',
|
|
68
|
-
'- or set OTAKIT_TOKEN env var',
|
|
69
|
-
].join('\n'));
|
|
65
|
+
throw new Error(['Missing authentication:', '- Run `otakit login`', '- or set OTAKIT_TOKEN env var'].join('\n'));
|
|
70
66
|
}
|
|
71
67
|
return {
|
|
72
68
|
serverUrl,
|
|
@@ -83,6 +79,7 @@ export async function readProjectConfig(cwd = process.cwd()) {
|
|
|
83
79
|
appId: projectConfig.appId,
|
|
84
80
|
channel: projectConfig.channel,
|
|
85
81
|
runtimeVersion: projectConfig.runtimeVersion,
|
|
82
|
+
updateStrategy: projectConfig.updateStrategy,
|
|
86
83
|
configuredServerUrl: projectConfig.configuredServerUrl
|
|
87
84
|
? parseServerUrl(projectConfig.configuredServerUrl, cwd)
|
|
88
85
|
: undefined,
|
|
@@ -147,6 +144,9 @@ export async function resolveConfigSnapshot(options) {
|
|
|
147
144
|
const runtimeVersionFromConfig = projectConfig?.runtimeVersion;
|
|
148
145
|
const runtimeVersionValue = runtimeVersionFromConfig ?? null;
|
|
149
146
|
const runtimeVersionSource = runtimeVersionFromConfig ? 'config' : 'none';
|
|
147
|
+
const updateStrategyFromConfig = projectConfig?.updateStrategy;
|
|
148
|
+
const updateStrategyValue = updateStrategyFromConfig ?? null;
|
|
149
|
+
const updateStrategySource = updateStrategyFromConfig ? 'config' : 'none';
|
|
150
150
|
const outputDirFromFlag = toNonEmptyString(options?.outputDir);
|
|
151
151
|
const outputDirFromEnv = resolveEnvOutputDir();
|
|
152
152
|
const outputDirFromConfig = projectConfig?.outputDir;
|
|
@@ -198,6 +198,10 @@ export async function resolveConfigSnapshot(options) {
|
|
|
198
198
|
value: runtimeVersionValue,
|
|
199
199
|
source: runtimeVersionSource,
|
|
200
200
|
},
|
|
201
|
+
updateStrategy: {
|
|
202
|
+
value: updateStrategyValue,
|
|
203
|
+
source: updateStrategySource,
|
|
204
|
+
},
|
|
201
205
|
authToken: {
|
|
202
206
|
value: authTokenValue,
|
|
203
207
|
source: authTokenSource,
|
|
@@ -208,11 +212,7 @@ export async function resolveConfigSnapshot(options) {
|
|
|
208
212
|
export async function requireConfig(options) {
|
|
209
213
|
const snapshot = await resolveConfigSnapshot(options);
|
|
210
214
|
if (!snapshot.authToken.value || !snapshot.authSource) {
|
|
211
|
-
throw new Error([
|
|
212
|
-
'Missing authentication:',
|
|
213
|
-
'- Run `otakit login`',
|
|
214
|
-
'- or set OTAKIT_TOKEN env var',
|
|
215
|
-
].join('\n'));
|
|
215
|
+
throw new Error(['Missing authentication:', '- Run `otakit login`', '- or set OTAKIT_TOKEN env var'].join('\n'));
|
|
216
216
|
}
|
|
217
217
|
if (!snapshot.appId.value) {
|
|
218
218
|
throw new Error([
|
|
@@ -226,6 +226,7 @@ export async function requireConfig(options) {
|
|
|
226
226
|
appId: snapshot.appId.value,
|
|
227
227
|
channel: snapshot.channel.value ?? undefined,
|
|
228
228
|
runtimeVersion: snapshot.runtimeVersion.value ?? undefined,
|
|
229
|
+
updateStrategy: snapshot.updateStrategy.value ?? undefined,
|
|
229
230
|
outputDir: snapshot.outputDir.value ?? undefined,
|
|
230
231
|
serverUrl: snapshot.serverUrl.value,
|
|
231
232
|
authToken: snapshot.authToken.value,
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,eAAe,GAAG,SAAS,CAAC;AAClC,MAAM,kBAAkB,GAAG,4BAA4B,CAAC;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAC;AAEzD,MAAM,mBAAmB,GAAG,YAAY,CAAC;AACzC,MAAM,qBAAqB,GAAG,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const ENCRYPTION_ALG = "AES-256-GCM";
|
|
2
|
+
export interface BundleEncryptionParams {
|
|
3
|
+
alg: string;
|
|
4
|
+
kid: string;
|
|
5
|
+
wrapNonce: string;
|
|
6
|
+
wrappedDek: string;
|
|
7
|
+
nonce: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Derive the key ID from a bundle encryption key: first 16 hex chars of
|
|
11
|
+
* sha256(key bytes). Must match generate-encryption-key output.
|
|
12
|
+
*/
|
|
13
|
+
export declare function deriveKid(key: Buffer): string;
|
|
14
|
+
export declare function generateEncryptionKey(): {
|
|
15
|
+
kid: string;
|
|
16
|
+
key: Buffer;
|
|
17
|
+
};
|
|
18
|
+
export declare function parseEncryptionKey(base64: string): Buffer;
|
|
19
|
+
/**
|
|
20
|
+
* Wrap a per-bundle DEK under the app KEK with AES-256-GCM.
|
|
21
|
+
* Returns base64 wrapNonce and wrappedDek (ciphertext with tag appended).
|
|
22
|
+
*/
|
|
23
|
+
export declare function wrapDek(kek: Buffer, dek: Buffer): {
|
|
24
|
+
wrapNonce: string;
|
|
25
|
+
wrappedDek: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Encrypt a file with AES-256-GCM under a fresh random DEK, streaming
|
|
29
|
+
* plaintext through the cipher and appending the GCM tag to the output.
|
|
30
|
+
*/
|
|
31
|
+
export declare function encryptFile(kek: Buffer, inputPath: string, outputPath: string): Promise<BundleEncryptionParams>;
|
|
32
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/lib/crypto.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAE5C,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,IAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAGpE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAQ3F;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,sBAAsB,CAAC,CAyBjC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { createCipheriv, createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { createReadStream, createWriteStream } from 'node:fs';
|
|
3
|
+
import { pipeline } from 'node:stream/promises';
|
|
4
|
+
import { Transform } from 'node:stream';
|
|
5
|
+
const ALGORITHM = 'aes-256-gcm';
|
|
6
|
+
const NONCE_LENGTH = 12;
|
|
7
|
+
const KEY_LENGTH = 32;
|
|
8
|
+
export const ENCRYPTION_ALG = 'AES-256-GCM';
|
|
9
|
+
/**
|
|
10
|
+
* Derive the key ID from a bundle encryption key: first 16 hex chars of
|
|
11
|
+
* sha256(key bytes). Must match generate-encryption-key output.
|
|
12
|
+
*/
|
|
13
|
+
export function deriveKid(key) {
|
|
14
|
+
return createHash('sha256').update(key).digest('hex').slice(0, 16);
|
|
15
|
+
}
|
|
16
|
+
export function generateEncryptionKey() {
|
|
17
|
+
const key = randomBytes(KEY_LENGTH);
|
|
18
|
+
return { kid: deriveKid(key), key };
|
|
19
|
+
}
|
|
20
|
+
export function parseEncryptionKey(base64) {
|
|
21
|
+
const key = Buffer.from(base64.trim(), 'base64');
|
|
22
|
+
if (key.length !== KEY_LENGTH) {
|
|
23
|
+
throw new Error(`Invalid encryption key: expected ${KEY_LENGTH} bytes (base64), got ${key.length} bytes.`);
|
|
24
|
+
}
|
|
25
|
+
return key;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wrap a per-bundle DEK under the app KEK with AES-256-GCM.
|
|
29
|
+
* Returns base64 wrapNonce and wrappedDek (ciphertext with tag appended).
|
|
30
|
+
*/
|
|
31
|
+
export function wrapDek(kek, dek) {
|
|
32
|
+
const wrapNonce = randomBytes(NONCE_LENGTH);
|
|
33
|
+
const cipher = createCipheriv(ALGORITHM, kek, wrapNonce);
|
|
34
|
+
const wrapped = Buffer.concat([cipher.update(dek), cipher.final(), cipher.getAuthTag()]);
|
|
35
|
+
return {
|
|
36
|
+
wrapNonce: wrapNonce.toString('base64'),
|
|
37
|
+
wrappedDek: wrapped.toString('base64'),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Encrypt a file with AES-256-GCM under a fresh random DEK, streaming
|
|
42
|
+
* plaintext through the cipher and appending the GCM tag to the output.
|
|
43
|
+
*/
|
|
44
|
+
export async function encryptFile(kek, inputPath, outputPath) {
|
|
45
|
+
const dek = randomBytes(KEY_LENGTH);
|
|
46
|
+
const nonce = randomBytes(NONCE_LENGTH);
|
|
47
|
+
const cipher = createCipheriv(ALGORITHM, dek, nonce);
|
|
48
|
+
const appendTag = new Transform({
|
|
49
|
+
transform(chunk, _encoding, callback) {
|
|
50
|
+
callback(null, chunk);
|
|
51
|
+
},
|
|
52
|
+
flush(callback) {
|
|
53
|
+
// cipher.final() has run by the time flush is reached in the pipeline
|
|
54
|
+
callback(null, cipher.getAuthTag());
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
await pipeline(createReadStream(inputPath), cipher, appendTag, createWriteStream(outputPath));
|
|
58
|
+
const { wrapNonce, wrappedDek } = wrapDek(kek, dek);
|
|
59
|
+
return {
|
|
60
|
+
alg: ENCRYPTION_ALG,
|
|
61
|
+
kid: deriveKid(kek),
|
|
62
|
+
wrapNonce,
|
|
63
|
+
wrappedDek,
|
|
64
|
+
nonce: nonce.toString('base64'),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/lib/crypto.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/hash.d.ts
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
* Calculate SHA-256 hash of a file
|
|
3
3
|
*/
|
|
4
4
|
export declare function hashFile(filePath: string): Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Calculate SHA-256 (hex) and MD5 (base64) of a file in one read.
|
|
7
|
+
* The MD5 is pinned into presigned PUTs as Content-MD5 so storage rejects
|
|
8
|
+
* an upload whose bytes don't match what was hashed.
|
|
9
|
+
*/
|
|
10
|
+
export declare function hashFileWithMd5(filePath: string): Promise<{
|
|
11
|
+
sha256: string;
|
|
12
|
+
md5: string;
|
|
13
|
+
}>;
|
|
5
14
|
/**
|
|
6
15
|
* Calculate SHA-256 hash of a buffer
|
|
7
16
|
*/
|
package/dist/lib/hash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/lib/hash.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAShE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/lib/hash.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAShE;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAahG;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
package/dist/lib/hash.js
CHANGED
|
@@ -12,6 +12,24 @@ export async function hashFile(filePath) {
|
|
|
12
12
|
stream.on('error', reject);
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Calculate SHA-256 (hex) and MD5 (base64) of a file in one read.
|
|
17
|
+
* The MD5 is pinned into presigned PUTs as Content-MD5 so storage rejects
|
|
18
|
+
* an upload whose bytes don't match what was hashed.
|
|
19
|
+
*/
|
|
20
|
+
export async function hashFileWithMd5(filePath) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const sha256 = createHash('sha256');
|
|
23
|
+
const md5 = createHash('md5');
|
|
24
|
+
const stream = createReadStream(filePath);
|
|
25
|
+
stream.on('data', (data) => {
|
|
26
|
+
sha256.update(data);
|
|
27
|
+
md5.update(data);
|
|
28
|
+
});
|
|
29
|
+
stream.on('end', () => resolve({ sha256: sha256.digest('hex'), md5: md5.digest('base64') }));
|
|
30
|
+
stream.on('error', reject);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
15
33
|
/**
|
|
16
34
|
* Calculate SHA-256 hash of a buffer
|
|
17
35
|
*/
|
package/dist/lib/hash.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/lib/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC"}
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/lib/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A dependency that ships native (iOS/Android) code, captured at upload time
|
|
3
|
+
* so later uploads can detect native changes that require a store build.
|
|
4
|
+
*/
|
|
5
|
+
export interface NativePackage {
|
|
6
|
+
name: string;
|
|
7
|
+
version: string;
|
|
8
|
+
requestedVersion?: string;
|
|
9
|
+
iosChecksum?: string;
|
|
10
|
+
androidChecksum?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CollectNativePackagesOptions {
|
|
13
|
+
/** Path to the project package.json. Defaults to ./package.json. */
|
|
14
|
+
packageJsonPath?: string;
|
|
15
|
+
/** Path to the resolved node_modules. Defaults to a sibling of package.json. */
|
|
16
|
+
nodeModulesPath?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function collectNativePackages(options?: CollectNativePackagesOptions): NativePackage[];
|
|
19
|
+
export type CompatibilityStatus = 'compatible' | 'incompatible' | 'skipped';
|
|
20
|
+
export type FindingKind = 'new_plugin' | 'native_code_changed' | 'version_mismatch' | 'range_changed' | 'removed' | 'unchanged';
|
|
21
|
+
export interface CompatibilityFinding {
|
|
22
|
+
name: string;
|
|
23
|
+
kind: FindingKind;
|
|
24
|
+
incompatible: boolean;
|
|
25
|
+
localVersion?: string;
|
|
26
|
+
remoteVersion?: string;
|
|
27
|
+
note?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface CompatibilityResult {
|
|
30
|
+
status: CompatibilityStatus;
|
|
31
|
+
findings: CompatibilityFinding[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Compare the local native set against the channel's current bundle.
|
|
35
|
+
*
|
|
36
|
+
* The checksum is the authoritative "native code actually changed" signal;
|
|
37
|
+
* a changed requested-version range that resolves to identical native code
|
|
38
|
+
* is reported as informational only.
|
|
39
|
+
*/
|
|
40
|
+
export declare function compareNative(local: NativePackage[], remote: NativePackage[] | null | undefined): CompatibilityResult;
|
|
41
|
+
export declare function formatCompatibilityReport(result: CompatibilityResult): string;
|
|
42
|
+
//# sourceMappingURL=native-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-deps.d.ts","sourceRoot":"","sources":["../../src/lib/native-deps.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,4BAA4B;IAC3C,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AASD,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,4BAAiC,GAAG,aAAa,EAAE,CAqEjG;AAgDD,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,cAAc,GAAG,SAAS,CAAC;AAE5E,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,qBAAqB,GACrB,kBAAkB,GAClB,eAAe,GACf,SAAS,GACT,WAAW,CAAC;AAEhB,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,aAAa,EAAE,EACtB,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,GAAG,SAAS,GACzC,mBAAmB,CAsCrB;AA4ED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAqC7E"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import semver from 'semver';
|
|
5
|
+
import { CliError } from './errors.js';
|
|
6
|
+
const NATIVE_FILE_REGEX = /\.(java|swift|kt|scala)$/;
|
|
7
|
+
const IOS_SOURCE_REGEX = /\.swift$/;
|
|
8
|
+
const ANDROID_SOURCE_REGEX = /\.(java|kt|scala)$/;
|
|
9
|
+
const IOS_CONFIG_REGEX = /(\.podspec|(^|\/)Package\.swift)$/;
|
|
10
|
+
const ANDROID_CONFIG_REGEX = /(^|\/)build\.gradle(\.kts)?$/;
|
|
11
|
+
const SKIPPED_DIRECTORIES = new Set(['node_modules', '.git', 'dist', 'build']);
|
|
12
|
+
export function collectNativePackages(options = {}) {
|
|
13
|
+
const packageJsonPath = resolve(options.packageJsonPath ?? join(process.cwd(), 'package.json'));
|
|
14
|
+
if (!existsSync(packageJsonPath)) {
|
|
15
|
+
throw new CliError(`package.json not found at ${packageJsonPath} (use --package-json).`);
|
|
16
|
+
}
|
|
17
|
+
const nodeModulesPath = resolve(options.nodeModulesPath ?? join(dirname(packageJsonPath), 'node_modules'));
|
|
18
|
+
if (!existsSync(nodeModulesPath)) {
|
|
19
|
+
throw new CliError(`node_modules not found at ${nodeModulesPath} (use --node-modules).`);
|
|
20
|
+
}
|
|
21
|
+
const rootPackage = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
22
|
+
const dependencies = rootPackage.dependencies ?? {};
|
|
23
|
+
const nativePackages = [];
|
|
24
|
+
for (const [name, requestedVersion] of Object.entries(dependencies)) {
|
|
25
|
+
const packageDir = join(nodeModulesPath, ...name.split('/'));
|
|
26
|
+
const packageJson = join(packageDir, 'package.json');
|
|
27
|
+
if (!existsSync(packageJson)) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
let installedVersion;
|
|
31
|
+
try {
|
|
32
|
+
const parsed = JSON.parse(readFileSync(packageJson, 'utf-8'));
|
|
33
|
+
if (typeof parsed.version !== 'string' || parsed.version.length === 0) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
installedVersion = parsed.version;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const files = listFilesRecursively(packageDir);
|
|
42
|
+
const relativePaths = files
|
|
43
|
+
.map((file) => relative(packageDir, file).split(sep).join('/'))
|
|
44
|
+
.sort();
|
|
45
|
+
if (!relativePaths.some((path) => NATIVE_FILE_REGEX.test(path))) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const iosChecksum = checksumForPlatform(packageDir, relativePaths, IOS_SOURCE_REGEX, IOS_CONFIG_REGEX);
|
|
49
|
+
const androidChecksum = checksumForPlatform(packageDir, relativePaths, ANDROID_SOURCE_REGEX, ANDROID_CONFIG_REGEX);
|
|
50
|
+
nativePackages.push({
|
|
51
|
+
name,
|
|
52
|
+
version: installedVersion,
|
|
53
|
+
requestedVersion,
|
|
54
|
+
...(iosChecksum ? { iosChecksum } : {}),
|
|
55
|
+
...(androidChecksum ? { androidChecksum } : {}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return nativePackages.sort((a, b) => a.name.localeCompare(b.name));
|
|
59
|
+
}
|
|
60
|
+
function listFilesRecursively(directory) {
|
|
61
|
+
const files = [];
|
|
62
|
+
const entries = readdirSync(directory, { withFileTypes: true });
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
if (entry.isSymbolicLink()) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const fullPath = join(directory, entry.name);
|
|
68
|
+
if (entry.isDirectory()) {
|
|
69
|
+
if (!SKIPPED_DIRECTORIES.has(entry.name)) {
|
|
70
|
+
files.push(...listFilesRecursively(fullPath));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (entry.isFile()) {
|
|
74
|
+
files.push(fullPath);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return files;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* SHA-256 over the platform's sorted native + config files, with each file's
|
|
81
|
+
* relative path mixed into the hash so renames are detected.
|
|
82
|
+
*/
|
|
83
|
+
function checksumForPlatform(packageDir, sortedRelativePaths, sourceRegex, configRegex) {
|
|
84
|
+
const platformPaths = sortedRelativePaths.filter((path) => sourceRegex.test(path) || configRegex.test(path));
|
|
85
|
+
if (platformPaths.length === 0) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const hash = createHash('sha256');
|
|
89
|
+
for (const path of platformPaths) {
|
|
90
|
+
hash.update(path);
|
|
91
|
+
hash.update('\0');
|
|
92
|
+
hash.update(readFileSync(join(packageDir, path)));
|
|
93
|
+
hash.update('\0');
|
|
94
|
+
}
|
|
95
|
+
return hash.digest('hex');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Compare the local native set against the channel's current bundle.
|
|
99
|
+
*
|
|
100
|
+
* The checksum is the authoritative "native code actually changed" signal;
|
|
101
|
+
* a changed requested-version range that resolves to identical native code
|
|
102
|
+
* is reported as informational only.
|
|
103
|
+
*/
|
|
104
|
+
export function compareNative(local, remote) {
|
|
105
|
+
if (remote === null || remote === undefined) {
|
|
106
|
+
return { status: 'skipped', findings: [] };
|
|
107
|
+
}
|
|
108
|
+
const remoteByName = new Map(remote.map((entry) => [entry.name, entry]));
|
|
109
|
+
const findings = [];
|
|
110
|
+
for (const pkg of local) {
|
|
111
|
+
const remotePkg = remoteByName.get(pkg.name);
|
|
112
|
+
remoteByName.delete(pkg.name);
|
|
113
|
+
if (!remotePkg) {
|
|
114
|
+
findings.push({
|
|
115
|
+
name: pkg.name,
|
|
116
|
+
kind: 'new_plugin',
|
|
117
|
+
incompatible: true,
|
|
118
|
+
localVersion: pkg.version,
|
|
119
|
+
note: 'native plugin not present in the current release',
|
|
120
|
+
});
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
findings.push(compareEntry(pkg, remotePkg));
|
|
124
|
+
}
|
|
125
|
+
for (const remotePkg of remoteByName.values()) {
|
|
126
|
+
findings.push({
|
|
127
|
+
name: remotePkg.name,
|
|
128
|
+
kind: 'removed',
|
|
129
|
+
incompatible: false,
|
|
130
|
+
remoteVersion: remotePkg.version,
|
|
131
|
+
note: 'removed locally (safe to ship OTA)',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const status = findings.some((finding) => finding.incompatible) ? 'incompatible' : 'compatible';
|
|
135
|
+
return { status, findings };
|
|
136
|
+
}
|
|
137
|
+
function compareEntry(local, remote) {
|
|
138
|
+
const base = {
|
|
139
|
+
name: local.name,
|
|
140
|
+
localVersion: local.version,
|
|
141
|
+
remoteVersion: remote.version,
|
|
142
|
+
};
|
|
143
|
+
// Native code added for a platform the baseline never had (e.g. a plugin
|
|
144
|
+
// gains Android sources): devices on that platform need a store build,
|
|
145
|
+
// same as a brand-new plugin. The reverse (remote-only checksum) is a
|
|
146
|
+
// removal and stays compatible.
|
|
147
|
+
const addedPlatforms = [
|
|
148
|
+
['ios', local.iosChecksum, remote.iosChecksum],
|
|
149
|
+
['android', local.androidChecksum, remote.androidChecksum],
|
|
150
|
+
].filter(([, localSum, remoteSum]) => localSum !== undefined && remoteSum === undefined);
|
|
151
|
+
if (addedPlatforms.length > 0) {
|
|
152
|
+
return {
|
|
153
|
+
...base,
|
|
154
|
+
kind: 'native_code_changed',
|
|
155
|
+
incompatible: true,
|
|
156
|
+
note: `native code added for ${addedPlatforms.map(([platform]) => platform).join(' + ')} (not in the current release)`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
const comparablePlatforms = [
|
|
160
|
+
[local.iosChecksum, remote.iosChecksum],
|
|
161
|
+
[local.androidChecksum, remote.androidChecksum],
|
|
162
|
+
].filter(([localSum, remoteSum]) => localSum !== undefined && remoteSum !== undefined);
|
|
163
|
+
if (comparablePlatforms.length > 0) {
|
|
164
|
+
const changed = comparablePlatforms.some(([localSum, remoteSum]) => localSum !== remoteSum);
|
|
165
|
+
if (changed) {
|
|
166
|
+
return {
|
|
167
|
+
...base,
|
|
168
|
+
kind: 'native_code_changed',
|
|
169
|
+
incompatible: true,
|
|
170
|
+
note: 'native code differs from the current release',
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (local.requestedVersion !== remote.requestedVersion) {
|
|
174
|
+
return {
|
|
175
|
+
...base,
|
|
176
|
+
kind: 'range_changed',
|
|
177
|
+
incompatible: false,
|
|
178
|
+
note: `requested range changed (${remote.requestedVersion ?? '?'} -> ${local.requestedVersion ?? '?'}) but native code is identical`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return { ...base, kind: 'unchanged', incompatible: false };
|
|
182
|
+
}
|
|
183
|
+
// No comparable checksums (older baseline data) — fall back to versions.
|
|
184
|
+
if (!versionsIntersect(local, remote)) {
|
|
185
|
+
return {
|
|
186
|
+
...base,
|
|
187
|
+
kind: 'version_mismatch',
|
|
188
|
+
incompatible: true,
|
|
189
|
+
note: 'installed native versions do not intersect',
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return { ...base, kind: 'unchanged', incompatible: false };
|
|
193
|
+
}
|
|
194
|
+
function versionsIntersect(local, remote) {
|
|
195
|
+
const localRange = local.requestedVersion ?? local.version;
|
|
196
|
+
const remoteRange = remote.requestedVersion ?? remote.version;
|
|
197
|
+
try {
|
|
198
|
+
return semver.intersects(localRange, remoteRange, { includePrerelease: true });
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return local.version === remote.version;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export function formatCompatibilityReport(result) {
|
|
205
|
+
if (result.status === 'skipped') {
|
|
206
|
+
return 'Compatibility check skipped: the current release has no native package baseline yet.';
|
|
207
|
+
}
|
|
208
|
+
const lines = [];
|
|
209
|
+
const rows = result.findings.map((finding) => [
|
|
210
|
+
finding.incompatible ? 'INCOMPATIBLE' : finding.kind === 'unchanged' ? 'ok' : 'info',
|
|
211
|
+
finding.name,
|
|
212
|
+
finding.localVersion ?? '-',
|
|
213
|
+
finding.remoteVersion ?? '-',
|
|
214
|
+
finding.note ?? finding.kind,
|
|
215
|
+
]);
|
|
216
|
+
const header = ['status', 'package', 'local', 'remote', 'detail'];
|
|
217
|
+
const widths = header.map((title, column) => Math.max(title.length, ...rows.map((row) => row[column].length)));
|
|
218
|
+
const renderRow = (row) => row.map((cell, column) => cell.padEnd(widths[column])).join(' ');
|
|
219
|
+
lines.push(renderRow(header));
|
|
220
|
+
lines.push(widths.map((width) => '-'.repeat(width)).join(' '));
|
|
221
|
+
for (const row of rows) {
|
|
222
|
+
lines.push(renderRow(row));
|
|
223
|
+
}
|
|
224
|
+
if (rows.length === 0) {
|
|
225
|
+
lines.push('(no native packages detected)');
|
|
226
|
+
}
|
|
227
|
+
if (result.status === 'incompatible') {
|
|
228
|
+
lines.push('');
|
|
229
|
+
lines.push('These native changes require a new store build. Bump runtimeVersion and ship a native build before releasing this bundle OTA.');
|
|
230
|
+
}
|
|
231
|
+
return lines.join('\n');
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=native-deps.js.map
|