lim 0.19.5 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/commands/gradle/build.d.ts +7 -0
  2. package/dist/commands/gradle/build.d.ts.map +1 -1
  3. package/dist/commands/gradle/build.js +66 -2
  4. package/dist/commands/gradle/build.js.map +1 -1
  5. package/dist/lib/android-keystore.d.ts +15 -0
  6. package/dist/lib/android-keystore.d.ts.map +1 -0
  7. package/dist/lib/android-keystore.js +65 -0
  8. package/dist/lib/android-keystore.js.map +1 -0
  9. package/dist/lib/android-keystore.test.d.ts +2 -0
  10. package/dist/lib/android-keystore.test.d.ts.map +1 -0
  11. package/dist/lib/android-keystore.test.js +43 -0
  12. package/dist/lib/android-keystore.test.js.map +1 -0
  13. package/dist/lib/auth.d.ts +1 -0
  14. package/dist/lib/auth.d.ts.map +1 -1
  15. package/dist/lib/auth.js +1 -0
  16. package/dist/lib/auth.js.map +1 -1
  17. package/dist/lib/backend.d.ts +32 -0
  18. package/dist/lib/backend.d.ts.map +1 -0
  19. package/dist/lib/backend.js +81 -0
  20. package/dist/lib/backend.js.map +1 -0
  21. package/dist/lib/backend.test.d.ts +2 -0
  22. package/dist/lib/backend.test.d.ts.map +1 -0
  23. package/dist/lib/backend.test.js +124 -0
  24. package/dist/lib/backend.test.js.map +1 -0
  25. package/dist/lib/gradle-build-options.d.ts +21 -0
  26. package/dist/lib/gradle-build-options.d.ts.map +1 -1
  27. package/dist/lib/gradle-build-options.js +41 -0
  28. package/dist/lib/gradle-build-options.js.map +1 -1
  29. package/dist/lib/gradle-build-options.test.d.ts +2 -0
  30. package/dist/lib/gradle-build-options.test.d.ts.map +1 -0
  31. package/dist/lib/gradle-build-options.test.js +63 -0
  32. package/dist/lib/gradle-build-options.test.js.map +1 -0
  33. package/dist/lib/gradle-signing.d.ts +44 -0
  34. package/dist/lib/gradle-signing.d.ts.map +1 -0
  35. package/dist/lib/gradle-signing.js +167 -0
  36. package/dist/lib/gradle-signing.js.map +1 -0
  37. package/dist/lib/gradle-signing.test.d.ts +2 -0
  38. package/dist/lib/gradle-signing.test.d.ts.map +1 -0
  39. package/dist/lib/gradle-signing.test.js +111 -0
  40. package/dist/lib/gradle-signing.test.js.map +1 -0
  41. package/package.json +8 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.test.js","sourceRoot":"","sources":["../../src/lib/backend.test.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,28 @@ export interface GradleBuildFlagValues {
12
12
  abi?: string[];
13
13
  upload?: string;
14
14
  'signed-upload-url'?: string;
15
+ sign?: boolean;
16
+ 'application-id'?: string;
17
+ keystore?: string;
18
+ 'keystore-password'?: string;
19
+ 'key-alias'?: string;
20
+ 'key-password'?: string;
21
+ 'save-key'?: boolean;
15
22
  }
23
+ /** Whether any explicit task produces an app bundle (AAB) artifact. */
24
+ export declare function tasksIncludeBundle(tasks: string[]): boolean;
25
+ /**
26
+ * Validates the signing flag combinations. Separate from the options
27
+ * mapping because signing material is resolved asynchronously (file read
28
+ * or escrow round-trip) after validation, while the mapper stays pure.
29
+ *
30
+ * The bring-your-own group is anchored on --keystore alone: the password
31
+ * flags are env-backed (LIM_KEYSTORE_PASSWORD, LIM_KEY_PASSWORD), so an
32
+ * ambient export must not drag a plain or --sign build into BYO
33
+ * validation. Presence checks use undefined, not truthiness: empty
34
+ * keystore passwords are legal.
35
+ */
36
+ export declare function validateSigningFlags(flags: GradleBuildFlagValues): void;
16
37
  /**
17
38
  * Maps parsed `lim gradle build` flags to the exec options, throwing on
18
39
  * contradictory combinations. Pure and oclif-free so it is unit-testable and
@@ -1 +1 @@
1
- {"version":3,"file":"gradle-build-options.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,+DAMkB,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,qBAAqB,GAAG,kBAAkB,CA8B5F"}
1
+ {"version":3,"file":"gradle-build-options.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,+DAMkB,CAAC;AAEjD,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAE3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CA2BvE;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,qBAAqB,GAAG,kBAAkB,CA+B5F"}
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.gradleAndroidABIs = void 0;
4
+ exports.tasksIncludeBundle = tasksIncludeBundle;
5
+ exports.validateSigningFlags = validateSigningFlags;
4
6
  exports.gradleBuildOptionsFromFlags = gradleBuildOptionsFromFlags;
5
7
  /**
6
8
  * Single source for the --abi enum: `satisfies` pins every entry to the SDK
@@ -14,6 +16,44 @@ exports.gradleAndroidABIs = [
14
16
  'x86_64',
15
17
  'all',
16
18
  ];
19
+ /** Whether any explicit task produces an app bundle (AAB) artifact. */
20
+ function tasksIncludeBundle(tasks) {
21
+ return tasks.some((t) => t.toLowerCase().includes('bundle'));
22
+ }
23
+ /**
24
+ * Validates the signing flag combinations. Separate from the options
25
+ * mapping because signing material is resolved asynchronously (file read
26
+ * or escrow round-trip) after validation, while the mapper stays pure.
27
+ *
28
+ * The bring-your-own group is anchored on --keystore alone: the password
29
+ * flags are env-backed (LIM_KEYSTORE_PASSWORD, LIM_KEY_PASSWORD), so an
30
+ * ambient export must not drag a plain or --sign build into BYO
31
+ * validation. Presence checks use undefined, not truthiness: empty
32
+ * keystore passwords are legal.
33
+ */
34
+ function validateSigningFlags(flags) {
35
+ if (flags.sign && flags.keystore) {
36
+ throw new Error('Use either --sign (escrowed key) or --keystore (bring your own key), not both.');
37
+ }
38
+ if (flags.keystore) {
39
+ const missing = ['keystore-password', 'key-alias', 'key-password'].filter((f) => flags[f] === undefined);
40
+ if (missing.length > 0) {
41
+ throw new Error(`Signing with your own key requires ${missing.map((f) => `--${f}`).join(', ')} as well.`);
42
+ }
43
+ }
44
+ else if (flags['key-alias'] !== undefined) {
45
+ throw new Error('--key-alias requires --keystore.');
46
+ }
47
+ if (flags['save-key'] && !flags.keystore) {
48
+ throw new Error('--save-key escrows a provided key and requires the --keystore flags.');
49
+ }
50
+ if (flags['application-id'] && !flags.sign && !flags['save-key']) {
51
+ throw new Error('--application-id only applies to --sign or --save-key.');
52
+ }
53
+ if (flags.sign && flags.task?.length && !tasksIncludeBundle(flags.task)) {
54
+ throw new Error('--sign produces a Play-ready signed AAB; include a bundle task (e.g. bundleRelease) in --task or omit --task.');
55
+ }
56
+ }
17
57
  /**
18
58
  * Maps parsed `lim gradle build` flags to the exec options, throwing on
19
59
  * contradictory combinations. Pure and oclif-free so it is unit-testable and
@@ -26,6 +66,7 @@ function gradleBuildOptionsFromFlags(flags) {
26
66
  if (flags.upload && flags['signed-upload-url']) {
27
67
  throw new Error('Use either --upload or --signed-upload-url, not both.');
28
68
  }
69
+ validateSigningFlags(flags);
29
70
  const options = {};
30
71
  if (flags.task?.length) {
31
72
  options.tasks = flags.task;
@@ -1 +1 @@
1
- {"version":3,"file":"gradle-build-options.js","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":";;;AAgCA,kEA8BC;AA5DD;;;;GAIG;AACU,QAAA,iBAAiB,GAAG;IAC/B,aAAa;IACb,WAAW;IACX,KAAK;IACL,QAAQ;IACR,KAAK;CACyC,CAAC;AAWjD;;;;;;;GAOG;AACH,SAAgB,2BAA2B,CAAC,KAA4B;IACtE,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAwB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,IAAI,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,WAAW,GAAG;YACpB,GAAG,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SACrC,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;SAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,GAAG,EAAE,eAAe,EAAE,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"gradle-build-options.js","sourceRoot":"","sources":["../../src/lib/gradle-build-options.ts"],"names":[],"mappings":";;;AAgCA,gDAEC;AAaD,oDA2BC;AAUD,kEA+BC;AAjHD;;;;GAIG;AACU,QAAA,iBAAiB,GAAG;IAC/B,aAAa;IACb,WAAW;IACX,KAAK;IACL,QAAQ;IACR,KAAK;CACyC,CAAC;AAkBjD,uEAAuE;AACvE,SAAgB,kBAAkB,CAAC,KAAe;IAChD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,oBAAoB,CAAC,KAA4B;IAC/D,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,OAAO,GAAI,CAAC,mBAAmB,EAAE,WAAW,EAAE,cAAc,CAAW,CAAC,MAAM,CAClF,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAC9B,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,sCAAsC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CACzF,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,KAAK,CACb,+GAA+G,CAChH,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,2BAA2B,CAAC,KAA4B;IACtE,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,IAAI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAwB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,IAAI,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,WAAW,GAAG;YACpB,GAAG,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SACrC,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;SAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,GAAG,EAAE,eAAe,EAAE,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gradle-build-options.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-build-options.test.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-build-options.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const gradle_build_options_1 = require("./gradle-build-options");
4
+ const byo = {
5
+ keystore: 'upload.jks',
6
+ 'keystore-password': 'store-pass',
7
+ 'key-alias': 'upload',
8
+ 'key-password': 'key-pass',
9
+ };
10
+ describe('gradleBuildOptionsFromFlags signing validation', () => {
11
+ const cases = [
12
+ { name: 'no signing flags', flags: {} },
13
+ { name: 'sign alone', flags: { sign: true } },
14
+ { name: 'sign with application-id', flags: { sign: true, 'application-id': 'com.x' } },
15
+ { name: 'full BYO group', flags: { ...byo } },
16
+ { name: 'full BYO group with save-key', flags: { ...byo, 'save-key': true, 'application-id': 'com.x' } },
17
+ {
18
+ name: 'empty-string keystore password is provided, not missing',
19
+ flags: { ...byo, 'keystore-password': '' },
20
+ },
21
+ {
22
+ name: 'ambient env passwords without --keystore do not poison a plain build',
23
+ flags: { 'keystore-password': 'from-env', 'key-password': 'from-env' },
24
+ },
25
+ {
26
+ name: 'ambient env passwords without --keystore do not poison --sign',
27
+ flags: { sign: true, 'keystore-password': 'from-env', 'key-password': 'from-env' },
28
+ },
29
+ { name: 'sign and keystore together', flags: { sign: true, ...byo }, error: /not both/ },
30
+ {
31
+ name: 'keystore without the rest names the missing flags',
32
+ flags: { keystore: 'upload.jks', 'key-alias': 'upload' },
33
+ error: /--keystore-password, --key-password/,
34
+ },
35
+ { name: 'key-alias without keystore', flags: { 'key-alias': 'upload' }, error: /requires --keystore/ },
36
+ { name: 'save-key without keystore', flags: { 'save-key': true }, error: /requires the --keystore/ },
37
+ {
38
+ name: 'application-id without sign or save-key',
39
+ flags: { 'application-id': 'com.x' },
40
+ error: /only applies to --sign or --save-key/,
41
+ },
42
+ {
43
+ name: 'sign with an explicit non-bundle task',
44
+ flags: { sign: true, task: ['assembleDebug'] },
45
+ error: /include a bundle task/,
46
+ },
47
+ { name: 'sign with an explicit bundle task', flags: { sign: true, task: [':app:bundleRelease'] } },
48
+ { name: 'BYO keystore with a debug task stays allowed', flags: { ...byo, task: ['assembleDebug'] } },
49
+ ];
50
+ it.each(cases)('$name', ({ flags, error }) => {
51
+ if (error) {
52
+ expect(() => (0, gradle_build_options_1.gradleBuildOptionsFromFlags)(flags)).toThrow(error);
53
+ }
54
+ else {
55
+ expect(() => (0, gradle_build_options_1.gradleBuildOptionsFromFlags)(flags)).not.toThrow();
56
+ }
57
+ });
58
+ it('never maps signing material itself: the command resolves it asynchronously', () => {
59
+ expect((0, gradle_build_options_1.gradleBuildOptionsFromFlags)({ ...byo }).signing).toBeUndefined();
60
+ expect((0, gradle_build_options_1.gradleBuildOptionsFromFlags)({ sign: true }).signing).toBeUndefined();
61
+ });
62
+ });
63
+ //# sourceMappingURL=gradle-build-options.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-build-options.test.js","sourceRoot":"","sources":["../../src/lib/gradle-build-options.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { GradleSigningConfig } from '@limrun/api';
2
+ import type Limrun from '@limrun/api';
3
+ /**
4
+ * Resolves the Android applicationId that names the escrowed signing key.
5
+ * Precedence: explicit flag, Expo app config, Gradle build script. The
6
+ * file probes are heuristics; --application-id is the escape hatch.
7
+ */
8
+ export declare function resolveApplicationId(opts: {
9
+ explicit?: string;
10
+ syncPath: string;
11
+ expoAppDir?: string;
12
+ projectPath?: string;
13
+ }): string;
14
+ /**
15
+ * Reads a bring-your-own keystore file into the wire signing shape. The
16
+ * flag validator guarantees the passwords and alias are set; the checks
17
+ * here keep that invariant local instead of relying on call-site order.
18
+ */
19
+ export declare function readProvidedSigning(flags: {
20
+ keystore: string;
21
+ keystorePassword?: string;
22
+ keyAlias?: string;
23
+ keyPassword?: string;
24
+ }): GradleSigningConfig;
25
+ export type EscrowedSigning = {
26
+ signing: GradleSigningConfig;
27
+ /** True when this invocation created the key; false when it already existed. */
28
+ created: boolean;
29
+ };
30
+ /**
31
+ * Fetches the organization's upload key for the application, generating
32
+ * and escrowing one on first use. The backend's get-or-create makes the
33
+ * concurrent-first-build race safe: whichever caller wins, everyone signs
34
+ * with the same key, because the response data is authoritative.
35
+ */
36
+ export declare function resolveEscrowedSigning(client: Limrun, applicationId: string): Promise<EscrowedSigning>;
37
+ /**
38
+ * Escrows a user-provided key under the application's name. Refuses to
39
+ * proceed when a DIFFERENT key is already escrowed: silently signing with
40
+ * either key would surprise someone, and replacing an upload key is not a
41
+ * side effect a build command should have.
42
+ */
43
+ export declare function saveProvidedKey(client: Limrun, applicationId: string, provided: GradleSigningConfig): Promise<boolean>;
44
+ //# sourceMappingURL=gradle-signing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-signing.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-signing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAMtC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAoBT;AAmCD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,mBAAmB,CAwBtB;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAgBlB"}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolveApplicationId = resolveApplicationId;
37
+ exports.readProvidedSigning = readProvidedSigning;
38
+ exports.resolveEscrowedSigning = resolveEscrowedSigning;
39
+ exports.saveProvidedKey = saveProvidedKey;
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const android_keystore_1 = require("./android-keystore");
43
+ const backend_1 = require("./backend");
44
+ const signingFields = ['keystoreBase64', 'keystorePassword', 'keyAlias', 'keyPassword'];
45
+ /**
46
+ * Resolves the Android applicationId that names the escrowed signing key.
47
+ * Precedence: explicit flag, Expo app config, Gradle build script. The
48
+ * file probes are heuristics; --application-id is the escape hatch.
49
+ */
50
+ function resolveApplicationId(opts) {
51
+ if (opts.explicit) {
52
+ return opts.explicit;
53
+ }
54
+ const fromExpo = expoAndroidPackage(path.join(opts.syncPath, opts.expoAppDir ?? '.'));
55
+ if (fromExpo) {
56
+ return fromExpo;
57
+ }
58
+ // Probe the explicit gradle root first, then the conventional bare
59
+ // React Native layout (android/), which users rarely spell out because
60
+ // the server auto-discovers it.
61
+ for (const root of [...new Set([opts.projectPath ?? '.', 'android'])]) {
62
+ const fromGradle = gradleApplicationId(path.join(opts.syncPath, root));
63
+ if (fromGradle) {
64
+ return fromGradle;
65
+ }
66
+ }
67
+ throw new Error('Cannot determine the Android application ID for signing. Pass --application-id <id> (the value of android.package in app.json, or applicationId in app/build.gradle).');
68
+ }
69
+ function expoAndroidPackage(appDir) {
70
+ try {
71
+ const raw = fs.readFileSync(path.join(appDir, 'app.json'), 'utf8');
72
+ const parsed = JSON.parse(raw);
73
+ return parsed.expo?.android?.package || undefined;
74
+ }
75
+ catch {
76
+ return undefined;
77
+ }
78
+ }
79
+ function gradleApplicationId(gradleRoot) {
80
+ for (const candidate of ['app/build.gradle', 'app/build.gradle.kts']) {
81
+ let content;
82
+ try {
83
+ content = fs.readFileSync(path.join(gradleRoot, candidate), 'utf8');
84
+ }
85
+ catch {
86
+ continue;
87
+ }
88
+ // Matches both Groovy (applicationId "com.x") and Kotlin DSL
89
+ // (applicationId = "com.x"), skipping line comments so a commented-out
90
+ // previous ID cannot shadow the live one. First live match wins;
91
+ // flavor-specific overrides are out of heuristic scope.
92
+ for (const line of content.split('\n')) {
93
+ const code = line.split('//', 1)[0];
94
+ const match = code.match(/applicationId\s*=?\s*["']([A-Za-z0-9_.]+)["']/);
95
+ if (match) {
96
+ return match[1];
97
+ }
98
+ }
99
+ }
100
+ return undefined;
101
+ }
102
+ /**
103
+ * Reads a bring-your-own keystore file into the wire signing shape. The
104
+ * flag validator guarantees the passwords and alias are set; the checks
105
+ * here keep that invariant local instead of relying on call-site order.
106
+ */
107
+ function readProvidedSigning(flags) {
108
+ const { keystorePassword, keyAlias, keyPassword } = flags;
109
+ if (keystorePassword === undefined || keyAlias === undefined || keyPassword === undefined) {
110
+ throw new Error('Signing with your own key requires --keystore-password, --key-alias and --key-password.');
111
+ }
112
+ let keystore;
113
+ try {
114
+ keystore = fs.readFileSync(flags.keystore);
115
+ }
116
+ catch (err) {
117
+ throw new Error(`Cannot read the keystore file ${flags.keystore}: ${err instanceof Error ? err.message : String(err)}`);
118
+ }
119
+ if (keystore.length === 0) {
120
+ throw new Error(`The keystore file ${flags.keystore} is empty.`);
121
+ }
122
+ return {
123
+ keystoreBase64: keystore.toString('base64'),
124
+ keystorePassword,
125
+ keyAlias,
126
+ keyPassword,
127
+ };
128
+ }
129
+ /**
130
+ * Fetches the organization's upload key for the application, generating
131
+ * and escrowing one on first use. The backend's get-or-create makes the
132
+ * concurrent-first-build race safe: whichever caller wins, everyone signs
133
+ * with the same key, because the response data is authoritative.
134
+ */
135
+ async function resolveEscrowedSigning(client, applicationId) {
136
+ const organizationId = await (0, backend_1.whoAmI)(client);
137
+ const existing = await (0, backend_1.getSecret)(client, organizationId, backend_1.androidSigningKeySecretType, applicationId);
138
+ if (existing) {
139
+ return { signing: asSigningConfig(existing, applicationId), created: false };
140
+ }
141
+ const generated = (0, android_keystore_1.generateAndroidSigningKey)(applicationId);
142
+ const result = await (0, backend_1.putSecret)(client, organizationId, backend_1.androidSigningKeySecretType, applicationId, generated);
143
+ return { signing: asSigningConfig(result.data, applicationId), created: result.created };
144
+ }
145
+ /**
146
+ * Escrows a user-provided key under the application's name. Refuses to
147
+ * proceed when a DIFFERENT key is already escrowed: silently signing with
148
+ * either key would surprise someone, and replacing an upload key is not a
149
+ * side effect a build command should have.
150
+ */
151
+ async function saveProvidedKey(client, applicationId, provided) {
152
+ const organizationId = await (0, backend_1.whoAmI)(client);
153
+ const result = await (0, backend_1.putSecret)(client, organizationId, backend_1.androidSigningKeySecretType, applicationId, provided);
154
+ if (!result.created && !signingFields.every((f) => result.data[f] === provided[f])) {
155
+ throw new Error(`The organization already has a different upload key escrowed for ${applicationId}. ` +
156
+ 'Builds with --sign use that key; drop --save-key to sign with the provided keystore for this build only.');
157
+ }
158
+ return result.created;
159
+ }
160
+ function asSigningConfig(data, applicationId) {
161
+ if (signingFields.some((f) => !data[f])) {
162
+ throw new Error(`The escrowed signing key for ${applicationId} is missing required fields; contact support before retrying.`);
163
+ }
164
+ const { keystoreBase64, keystorePassword, keyAlias, keyPassword } = data;
165
+ return { keystoreBase64, keystorePassword, keyAlias, keyPassword };
166
+ }
167
+ //# sourceMappingURL=gradle-signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-signing.js","sourceRoot":"","sources":["../../src/lib/gradle-signing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gradle-signing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-signing.test.d.ts","sourceRoot":"","sources":["../../src/lib/gradle-signing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("node:fs"));
37
+ const os = __importStar(require("node:os"));
38
+ const path = __importStar(require("node:path"));
39
+ const gradle_signing_1 = require("./gradle-signing");
40
+ const backend = __importStar(require("./backend"));
41
+ describe('resolveApplicationId', () => {
42
+ let dir;
43
+ beforeEach(() => {
44
+ dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lim-sign-'));
45
+ });
46
+ afterEach(() => {
47
+ fs.rmSync(dir, { recursive: true, force: true });
48
+ });
49
+ it('prefers the explicit flag over any detection', () => {
50
+ fs.writeFileSync(path.join(dir, 'app.json'), JSON.stringify({ expo: { android: { package: 'com.expo' } } }));
51
+ expect((0, gradle_signing_1.resolveApplicationId)({ explicit: 'com.flag', syncPath: dir })).toBe('com.flag');
52
+ });
53
+ it('reads the Expo android package, honoring --expo-app-dir', () => {
54
+ const appDir = path.join(dir, 'apps/mobile');
55
+ fs.mkdirSync(appDir, { recursive: true });
56
+ fs.writeFileSync(path.join(appDir, 'app.json'), JSON.stringify({ expo: { android: { package: 'com.expo' } } }));
57
+ expect((0, gradle_signing_1.resolveApplicationId)({ syncPath: dir, expoAppDir: 'apps/mobile' })).toBe('com.expo');
58
+ });
59
+ it('falls back to app/build.gradle in Groovy form', () => {
60
+ fs.mkdirSync(path.join(dir, 'app'), { recursive: true });
61
+ fs.writeFileSync(path.join(dir, 'app/build.gradle'), 'android {\n defaultConfig {\n applicationId "com.groovy"\n }\n}\n');
62
+ expect((0, gradle_signing_1.resolveApplicationId)({ syncPath: dir })).toBe('com.groovy');
63
+ });
64
+ it('parses the Kotlin DSL form, honoring --project-path', () => {
65
+ fs.mkdirSync(path.join(dir, 'android/app'), { recursive: true });
66
+ fs.writeFileSync(path.join(dir, 'android/app/build.gradle.kts'), 'applicationId = "com.kts"\n');
67
+ expect((0, gradle_signing_1.resolveApplicationId)({ syncPath: dir, projectPath: 'android' })).toBe('com.kts');
68
+ });
69
+ it('finds the conventional android/ layout without --project-path (bare React Native)', () => {
70
+ fs.mkdirSync(path.join(dir, 'android/app'), { recursive: true });
71
+ fs.writeFileSync(path.join(dir, 'android/app/build.gradle'), 'android {\n defaultConfig {\n applicationId "com.bare.rn"\n }\n}\n');
72
+ expect((0, gradle_signing_1.resolveApplicationId)({ syncPath: dir })).toBe('com.bare.rn');
73
+ });
74
+ it('skips commented-out applicationId lines', () => {
75
+ fs.mkdirSync(path.join(dir, 'app'), { recursive: true });
76
+ fs.writeFileSync(path.join(dir, 'app/build.gradle'), '// applicationId "com.old.name"\napplicationId "com.live.name" // was com.older\n');
77
+ expect((0, gradle_signing_1.resolveApplicationId)({ syncPath: dir })).toBe('com.live.name');
78
+ });
79
+ it('asks for --application-id when nothing is detectable', () => {
80
+ expect(() => (0, gradle_signing_1.resolveApplicationId)({ syncPath: dir })).toThrow(/--application-id/);
81
+ });
82
+ });
83
+ describe('saveProvidedKey', () => {
84
+ const client = {};
85
+ const provided = {
86
+ keystoreBase64: 'a2V5c3RvcmU=',
87
+ keystorePassword: 'store',
88
+ keyAlias: 'upload',
89
+ keyPassword: 'key',
90
+ };
91
+ beforeEach(() => {
92
+ jest.spyOn(backend, 'whoAmI').mockResolvedValue('org_1');
93
+ });
94
+ afterEach(() => jest.restoreAllMocks());
95
+ it('escrows a new key', async () => {
96
+ const put = jest.spyOn(backend, 'putSecret').mockResolvedValue({ data: { ...provided }, created: true });
97
+ await expect((0, gradle_signing_1.saveProvidedKey)(client, 'com.x', provided)).resolves.toBe(true);
98
+ expect(put).toHaveBeenCalledWith(client, 'org_1', 'androidSigningKey', 'com.x', provided);
99
+ });
100
+ it('accepts an identical already-escrowed key', async () => {
101
+ jest.spyOn(backend, 'putSecret').mockResolvedValue({ data: { ...provided }, created: false });
102
+ await expect((0, gradle_signing_1.saveProvidedKey)(client, 'com.x', provided)).resolves.toBe(false);
103
+ });
104
+ it('hard-fails when a DIFFERENT key is already escrowed', async () => {
105
+ jest
106
+ .spyOn(backend, 'putSecret')
107
+ .mockResolvedValue({ data: { ...provided, keystoreBase64: 'b3RoZXI=' }, created: false });
108
+ await expect((0, gradle_signing_1.saveProvidedKey)(client, 'com.x', provided)).rejects.toThrow(/already has a different upload key/);
109
+ });
110
+ });
111
+ //# sourceMappingURL=gradle-signing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gradle-signing.test.js","sourceRoot":"","sources":["../../src/lib/gradle-signing.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lim",
3
- "version": "0.19.5",
4
- "description": "Use remote XCode, iOS Simulator, Android Emulator and more to build and test apps from Linux, Windows or macOS.",
3
+ "version": "0.20.0",
4
+ "description": "Use remote XCode, Gradle, iOS Simulator, Android Emulator and more to build and test apps from Linux, Windows or macOS.",
5
5
  "bin": {
6
6
  "lim": "./bin/run.js"
7
7
  },
@@ -25,21 +25,26 @@
25
25
  "test": "jest"
26
26
  },
27
27
  "dependencies": {
28
- "@limrun/api": "0.43.0",
28
+ "@limrun/api": "0.43.1",
29
29
  "@oclif/core": "^4",
30
30
  "cli-progress": "^3.12.0",
31
31
  "cli-table3": "^0.6.5",
32
32
  "dotenv": "^17.4.2",
33
33
  "js-yaml": "^4.1.0",
34
+ "node-forge": "^1.4.0",
34
35
  "open": "^10.1.0",
35
36
  "prompts": "^2.4.2"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@oclif/test": "^4",
39
40
  "@types/cli-progress": "^3.11.6",
41
+ "@types/jest": "^30.0.0",
40
42
  "@types/js-yaml": "^4.0.9",
41
43
  "@types/node": "^22",
44
+ "@types/node-forge": "^1.3.14",
42
45
  "@types/prompts": "^2.4.9",
46
+ "jest": "^30.4.2",
47
+ "ts-jest": "^29.4.11",
43
48
  "typescript": "^5.8.3"
44
49
  },
45
50
  "oclif": {