@imagina-build/ias-cli 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +188 -22
  2. package/package.json +1 -1
  3. package/schema/ias.schema.json +46 -1
  4. package/shared/vault/index.mjs +25 -0
  5. package/shared/vault/policy-vectors.mjs +237 -0
  6. package/shared/vault/policy.mjs +427 -0
  7. package/shared/vault/test-vectors/ias-policy-1/policy.json +4016 -0
  8. package/shared/vault/vectors.mjs +2 -0
  9. package/src/apple/capabilities.mjs +96 -0
  10. package/src/apple/inventory.mjs +75 -0
  11. package/src/apple/signing.mjs +134 -0
  12. package/src/applications.mjs +114 -0
  13. package/src/cli.mjs +28 -10
  14. package/src/commands/apps/index.mjs +61 -11
  15. package/src/commands/apps/store.mjs +367 -0
  16. package/src/commands/auth/index.mjs +3 -3
  17. package/src/commands/build/index.mjs +2 -0
  18. package/src/commands/builds/index.mjs +20 -0
  19. package/src/commands/credentials/apple.mjs +1118 -0
  20. package/src/commands/credentials/generate.mjs +122 -0
  21. package/src/commands/credentials/index.mjs +114 -44
  22. package/src/commands/credentials/seal.mjs +44 -0
  23. package/src/commands/devices/asc.mjs +50 -8
  24. package/src/commands/devices/index.mjs +2 -1
  25. package/src/commands/devices/sync.mjs +57 -4
  26. package/src/commands/dist/index.mjs +12 -0
  27. package/src/commands/doctor/index.mjs +3 -0
  28. package/src/commands/github/index.mjs +13 -3
  29. package/src/commands/init/index.mjs +6 -3
  30. package/src/commands/policy/index.mjs +583 -0
  31. package/src/commands/policy/policy.mjs +182 -0
  32. package/src/commands/policy/progress.mjs +20 -0
  33. package/src/commands/releases/index.mjs +225 -0
  34. package/src/commands/rollout/index.mjs +186 -0
  35. package/src/commands/runners/index.mjs +19 -0
  36. package/src/commands/sdk/index.mjs +31 -4
  37. package/src/commands/setup/index.mjs +184 -0
  38. package/src/commands/skill/index.mjs +43 -0
  39. package/src/commands/submit/index.mjs +135 -19
  40. package/src/commands/testflight/index.mjs +309 -0
  41. package/src/commands/tokens/index.mjs +99 -0
  42. package/src/commands/update/index.mjs +26 -5
  43. package/src/commands/vault/approvers.mjs +5 -1
  44. package/src/commands/vault/index.mjs +26 -6
  45. package/src/commands/vault/runners.mjs +48 -2
  46. package/src/commands/webhooks/index.mjs +19 -5
  47. package/src/config.mjs +16 -1
  48. package/src/errors.mjs +52 -6
  49. package/src/op.mjs +83 -0
  50. package/src/ota-key.mjs +53 -0
  51. package/src/provisioning.mjs +281 -0
  52. package/src/schema.mjs +3 -0
  53. package/src/setup-state.mjs +76 -0
  54. package/src/setup.mjs +701 -0
  55. package/src/skill-files.generated.mjs +10 -0
  56. package/src/skill.mjs +256 -0
  57. package/src/team-vault.mjs +2 -2
  58. package/src/token-store.mjs +1 -1
@@ -0,0 +1,76 @@
1
+ // The state of ias setup: which services the app uses and what a person acknowledged. It lives outside the repository,
2
+ // because ias build refuses a dirty tree and onboarding is per computer (a teammate runs ias setup on theirs).
3
+ import { createHash } from 'node:crypto';
4
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
5
+ import { homedir } from 'node:os';
6
+ import { dirname, join, resolve } from 'node:path';
7
+ import process from 'node:process';
8
+
9
+ export const SETUP_STATE_VERSION = 1;
10
+
11
+ /** The services of an application, as the panel and the management API name them. */
12
+ export const SERVICES = Object.freeze(['updates', 'distribution', 'push']);
13
+
14
+ /** The folder of the state of this computer: IAS_STATE_DIR, or the one of the platform. */
15
+ export function stateHome(env = process.env) {
16
+ if (env.IAS_STATE_DIR) return resolve(env.IAS_STATE_DIR);
17
+ if (process.platform === 'darwin') return join(homedir(), 'Library', 'Application Support', 'ias');
18
+ return join(env.XDG_STATE_HOME ?? join(homedir(), '.local', 'state'), 'ias');
19
+ }
20
+
21
+ /** The file of the setup of `dir`: one per app, named after its real path. */
22
+ export function setupStateFile(dir, env = process.env) {
23
+ const key = createHash('sha256').update(resolve(dir)).digest('hex').slice(0, 24);
24
+ return join(stateHome(env), 'setup', `${key}.json`);
25
+ }
26
+
27
+ /** The state of `dir`: { version, dir, services, acknowledged, updated_at }, or a new one. */
28
+ export function readSetupState(dir, env = process.env) {
29
+ const file = setupStateFile(dir, env);
30
+ if (!existsSync(file)) return { version: SETUP_STATE_VERSION, dir: resolve(dir), services: undefined, acknowledged: {}, updated_at: null };
31
+ try {
32
+ const state = JSON.parse(readFileSync(file, 'utf8'));
33
+ if (state.version !== SETUP_STATE_VERSION) return { version: SETUP_STATE_VERSION, dir: resolve(dir), services: state.services, acknowledged: {}, updated_at: null };
34
+ return { version: SETUP_STATE_VERSION, dir: resolve(dir), services: state.services, acknowledged: state.acknowledged ?? {}, updated_at: state.updated_at ?? null };
35
+ } catch {
36
+ return { version: SETUP_STATE_VERSION, dir: resolve(dir), services: undefined, acknowledged: {}, updated_at: null };
37
+ }
38
+ }
39
+
40
+ /** Writes the state of `dir` with mode 600, in a folder with mode 700. It holds no secret. */
41
+ export function writeSetupState(dir, { services, acknowledged }, env = process.env) {
42
+ const file = setupStateFile(dir, env);
43
+ mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
44
+ const state = { version: SETUP_STATE_VERSION, dir: resolve(dir), services, acknowledged, updated_at: new Date().toISOString() };
45
+ writeFileSync(file, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
46
+ return state;
47
+ }
48
+
49
+ /** Forgets the state of `dir` (ias setup reset): the checklist starts from what the files and the server say. */
50
+ export function resetSetupState(dir, env = process.env) {
51
+ rmSync(setupStateFile(dir, env), { force: true });
52
+ }
53
+
54
+ /** The services of `--services`: a comma-separated list of updates, distribution and push, or one of them. */
55
+ export function parseServices(text) {
56
+ const names = String(text).split(',').map((name) => name.trim()).filter(Boolean);
57
+ const unknown = names.filter((name) => !SERVICES.includes(name));
58
+ if (unknown.length > 0) return { error: `unknown service ${unknown.join(', ')}` };
59
+ return { services: [...new Set(names)] };
60
+ }
61
+
62
+ /**
63
+ * The services of an app when nobody said: those its configuration and its app.json show, or updates and distribution
64
+ * for a new one, which is what ias is for.
65
+ */
66
+ export function inferServices({ config, expo, dependencies = {} }) {
67
+ const services = new Set();
68
+ if (config?.updates || expo?.updates?.url) services.add('updates');
69
+ if (config?.distribution) services.add('distribution');
70
+ if (config?.push || dependencies['expo-notifications']) services.add('push');
71
+ if (services.size === 0) {
72
+ services.add('updates');
73
+ services.add('distribution');
74
+ }
75
+ return [...services];
76
+ }