@otakit/cli 1.0.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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +145 -0
  3. package/bin/otakit.js +3 -0
  4. package/dist/commands/config.d.ts +3 -0
  5. package/dist/commands/config.d.ts.map +1 -0
  6. package/dist/commands/config.js +115 -0
  7. package/dist/commands/config.js.map +1 -0
  8. package/dist/commands/delete.d.ts +3 -0
  9. package/dist/commands/delete.d.ts.map +1 -0
  10. package/dist/commands/delete.js +30 -0
  11. package/dist/commands/delete.js.map +1 -0
  12. package/dist/commands/generate-signing-key.d.ts +3 -0
  13. package/dist/commands/generate-signing-key.d.ts.map +1 -0
  14. package/dist/commands/generate-signing-key.js +41 -0
  15. package/dist/commands/generate-signing-key.js.map +1 -0
  16. package/dist/commands/list.d.ts +3 -0
  17. package/dist/commands/list.d.ts.map +1 -0
  18. package/dist/commands/list.js +30 -0
  19. package/dist/commands/list.js.map +1 -0
  20. package/dist/commands/login.d.ts +3 -0
  21. package/dist/commands/login.d.ts.map +1 -0
  22. package/dist/commands/login.js +79 -0
  23. package/dist/commands/login.js.map +1 -0
  24. package/dist/commands/logout.d.ts +3 -0
  25. package/dist/commands/logout.d.ts.map +1 -0
  26. package/dist/commands/logout.js +25 -0
  27. package/dist/commands/logout.js.map +1 -0
  28. package/dist/commands/register.d.ts +3 -0
  29. package/dist/commands/register.d.ts.map +1 -0
  30. package/dist/commands/register.js +77 -0
  31. package/dist/commands/register.js.map +1 -0
  32. package/dist/commands/release.d.ts +3 -0
  33. package/dist/commands/release.d.ts.map +1 -0
  34. package/dist/commands/release.js +40 -0
  35. package/dist/commands/release.js.map +1 -0
  36. package/dist/commands/releases.d.ts +3 -0
  37. package/dist/commands/releases.d.ts.map +1 -0
  38. package/dist/commands/releases.js +49 -0
  39. package/dist/commands/releases.js.map +1 -0
  40. package/dist/commands/upload.d.ts +3 -0
  41. package/dist/commands/upload.d.ts.map +1 -0
  42. package/dist/commands/upload.js +76 -0
  43. package/dist/commands/upload.js.map +1 -0
  44. package/dist/commands/whoami.d.ts +3 -0
  45. package/dist/commands/whoami.d.ts.map +1 -0
  46. package/dist/commands/whoami.js +43 -0
  47. package/dist/commands/whoami.js.map +1 -0
  48. package/dist/index.d.ts +3 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +32 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/lib/api.d.ts +61 -0
  53. package/dist/lib/api.d.ts.map +1 -0
  54. package/dist/lib/api.js +102 -0
  55. package/dist/lib/api.js.map +1 -0
  56. package/dist/lib/capacitor-config.d.ts +11 -0
  57. package/dist/lib/capacitor-config.d.ts.map +1 -0
  58. package/dist/lib/capacitor-config.js +105 -0
  59. package/dist/lib/capacitor-config.js.map +1 -0
  60. package/dist/lib/config.d.ts +60 -0
  61. package/dist/lib/config.d.ts.map +1 -0
  62. package/dist/lib/config.js +253 -0
  63. package/dist/lib/config.js.map +1 -0
  64. package/dist/lib/errors.d.ts +6 -0
  65. package/dist/lib/errors.d.ts.map +1 -0
  66. package/dist/lib/errors.js +19 -0
  67. package/dist/lib/errors.js.map +1 -0
  68. package/dist/lib/hash.d.ts +9 -0
  69. package/dist/lib/hash.d.ts.map +1 -0
  70. package/dist/lib/hash.js +21 -0
  71. package/dist/lib/hash.js.map +1 -0
  72. package/dist/lib/http.d.ts +9 -0
  73. package/dist/lib/http.d.ts.map +1 -0
  74. package/dist/lib/http.js +43 -0
  75. package/dist/lib/http.js.map +1 -0
  76. package/dist/lib/prompt.d.ts +3 -0
  77. package/dist/lib/prompt.d.ts.map +1 -0
  78. package/dist/lib/prompt.js +23 -0
  79. package/dist/lib/prompt.js.map +1 -0
  80. package/dist/lib/token-store.d.ts +12 -0
  81. package/dist/lib/token-store.d.ts.map +1 -0
  82. package/dist/lib/token-store.js +151 -0
  83. package/dist/lib/token-store.js.map +1 -0
  84. package/dist/lib/upload-workflow.d.ts +27 -0
  85. package/dist/lib/upload-workflow.d.ts.map +1 -0
  86. package/dist/lib/upload-workflow.js +252 -0
  87. package/dist/lib/upload-workflow.js.map +1 -0
  88. package/dist/lib/validate.d.ts +3 -0
  89. package/dist/lib/validate.d.ts.map +1 -0
  90. package/dist/lib/validate.js +16 -0
  91. package/dist/lib/validate.js.map +1 -0
  92. package/dist/lib/version.d.ts +4 -0
  93. package/dist/lib/version.d.ts.map +1 -0
  94. package/dist/lib/version.js +24 -0
  95. package/dist/lib/version.js.map +1 -0
  96. package/dist/lib/zip.d.ts +8 -0
  97. package/dist/lib/zip.d.ts.map +1 -0
  98. package/dist/lib/zip.js +78 -0
  99. package/dist/lib/zip.js.map +1 -0
  100. package/package.json +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OtaKit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # @otakit/cli
2
+
3
+ Upload and release CLI for OtaKit.
4
+
5
+ ## What it does
6
+
7
+ - reads project config from `capacitor.config.*`
8
+ - authenticates with login or env tokens
9
+ - zips the build output
10
+ - computes the bundle SHA-256 checksum
11
+ - creates an upload session
12
+ - uploads the zip directly to object storage
13
+ - finalizes the bundle
14
+ - optionally releases it to the unnamed channel or a named channel
15
+
16
+ The normal hosted flow is dashboard-first. Create the app in the dashboard,
17
+ paste its `appId` into `plugins.OtaKit.appId`, then ship:
18
+
19
+ ```bash
20
+ otakit login
21
+ npm run build
22
+ otakit upload --release
23
+ ```
24
+
25
+ If you want to create the app from the CLI instead:
26
+
27
+ ```bash
28
+ otakit register --slug com.example.app
29
+ ```
30
+
31
+ There is no `otakit init`.
32
+
33
+ ## Config model
34
+
35
+ The CLI reads these files when present:
36
+
37
+ - `capacitor.config.ts`
38
+ - `capacitor.config.js`
39
+ - `capacitor.config.mjs`
40
+ - `capacitor.config.cjs`
41
+ - `capacitor.config.json`
42
+
43
+ Important values:
44
+
45
+ ```ts
46
+ webDir: "out",
47
+ plugins: {
48
+ OtaKit: {
49
+ appId: "app_xxxxxxxx",
50
+ // Optional:
51
+ // channel: "staging",
52
+ // serverUrl: "https://your-server.com/api/v1"
53
+ }
54
+ }
55
+ ```
56
+
57
+ Resolution order:
58
+
59
+ 1. CLI flags
60
+ 2. environment variables
61
+ 3. `capacitor.config.*`
62
+ 4. built-in defaults
63
+
64
+ Main rules:
65
+
66
+ 1. `appId`: `--app-id` -> `OTAKIT_APP_ID` -> `plugins.OtaKit.appId`
67
+ 2. `serverUrl`: `--server` -> `OTAKIT_SERVER_URL` -> `plugins.OtaKit.serverUrl` -> `https://otakit.app/api/v1`
68
+ 3. `outputDir`: upload path arg -> `OTAKIT_BUILD_DIR` / `OTAKIT_OUTPUT_DIR` -> `webDir`
69
+ 4. release channel: `--release` -> unnamed channel, `--release <channel>` -> named channel
70
+
71
+ Auth precedence:
72
+
73
+ 1. `OTAKIT_TOKEN`
74
+ 2. `OTAKIT_ACCESS_TOKEN`
75
+ 3. stored token from `otakit login`
76
+ 4. `OTAKIT_SECRET_KEY`
77
+
78
+ Version precedence:
79
+
80
+ 1. `--version`
81
+ 2. `OTAKIT_VERSION`
82
+ 3. auto-generated `<base>+otk.<commit>.<run>`
83
+
84
+ ## Release model
85
+
86
+ - `otakit upload`
87
+ upload only
88
+ - `otakit upload --release`
89
+ upload and release to the unnamed channel
90
+ - `otakit upload --release staging`
91
+ upload and release to a named channel
92
+ - `otakit release <bundleId> --channel staging`
93
+ promote an existing bundle later
94
+
95
+ Releases are append-only. The newest release for `(appId, channel)` is what
96
+ devices see on manifest checks.
97
+
98
+ ## Common commands
99
+
100
+ - `otakit login`
101
+ - `otakit logout`
102
+ - `otakit whoami`
103
+ - `otakit register --slug <slug>`
104
+ - `otakit upload [path] [--release [channel]]`
105
+ - `otakit release [bundleId] [--channel <channel>]`
106
+ - `otakit releases [--channel <channel> | --base]`
107
+ - `otakit list`
108
+ - `otakit delete <bundleId> --force`
109
+ - `otakit config validate`
110
+ - `otakit config resolve --json`
111
+ - `otakit generate-signing-key`
112
+
113
+ ## CI
114
+
115
+ ```bash
116
+ export OTAKIT_SECRET_KEY=otakit_sk_...
117
+ export OTAKIT_APP_ID=app_xxxxxxxx
118
+ export OTAKIT_BUILD_DIR=out
119
+
120
+ otakit upload --release
121
+ ```
122
+
123
+ Set `OTAKIT_SERVER_URL` only for custom or self-hosted servers.
124
+
125
+ ## Upload flow
126
+
127
+ 1. resolve the build output directory
128
+ 2. require `index.html`
129
+ 3. zip the output
130
+ 4. compute SHA-256 and size
131
+ 5. call `bundles/initiate`
132
+ 6. upload directly to object storage
133
+ 7. call `bundles/finalize`
134
+ 8. optionally call `releases`
135
+
136
+ The CLI does not own app creation or channel strategy. It packages the build,
137
+ uploads it, and optionally promotes it.
138
+
139
+ ## Build locally
140
+
141
+ ```bash
142
+ pnpm --filter @otakit/cli build
143
+ pnpm --filter @otakit/cli typecheck
144
+ pnpm --filter @otakit/cli dev
145
+ ```
package/bin/otakit.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import '../dist/index.js';
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const configCommand: Command;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmKpC,eAAO,MAAM,aAAa,SAGM,CAAC"}
@@ -0,0 +1,115 @@
1
+ import { Command } from 'commander';
2
+ import { PROJECT_CONFIG_LABEL, readProjectConfig, resolveConfigSnapshot } from '../lib/config.js';
3
+ import { CliError, runCommand } from '../lib/errors.js';
4
+ function formatMaybe(value) {
5
+ return value ?? '(unset)';
6
+ }
7
+ function formatAuthSource(source) {
8
+ if (!source) {
9
+ return 'none';
10
+ }
11
+ if (source === 'env_access_token') {
12
+ return 'env (OTAKIT_ACCESS_TOKEN)';
13
+ }
14
+ if (source === 'env_secret_key') {
15
+ return 'env (OTAKIT_SECRET_KEY)';
16
+ }
17
+ if (source === 'env_token') {
18
+ return 'env (OTAKIT_TOKEN)';
19
+ }
20
+ return source;
21
+ }
22
+ const resolveSubcommand = new Command('resolve')
23
+ .description('Resolve effective config values and their sources')
24
+ .option('--app-id <id>', 'App ID override')
25
+ .option('--server <url>', 'Server URL override')
26
+ .option('--output-dir <path>', 'Output directory override')
27
+ .option('--channel <channel>', 'Channel override')
28
+ .option('--json', 'Print machine-readable JSON output')
29
+ .action(async (options) => {
30
+ await runCommand(async () => {
31
+ const snapshot = await resolveConfigSnapshot({
32
+ appId: options.appId,
33
+ serverUrl: options.server,
34
+ outputDir: options.outputDir,
35
+ channel: options.channel,
36
+ });
37
+ const jsonPayload = {
38
+ configFile: snapshot.configFile,
39
+ appId: snapshot.appId,
40
+ serverUrl: snapshot.serverUrl,
41
+ outputDir: snapshot.outputDir,
42
+ channel: snapshot.channel,
43
+ auth: {
44
+ present: snapshot.authToken.value !== null,
45
+ source: snapshot.authSource ?? 'none',
46
+ },
47
+ };
48
+ if (options.json) {
49
+ console.log(JSON.stringify(jsonPayload, null, 2));
50
+ return;
51
+ }
52
+ console.log(`config file: ${snapshot.configFile.path}`);
53
+ console.log(`config found: ${snapshot.configFile.found ? 'yes' : 'no'}`);
54
+ console.log(`appId: ${formatMaybe(snapshot.appId.value)} (${snapshot.appId.source})`);
55
+ console.log(`serverUrl: ${snapshot.serverUrl.value} (${snapshot.serverUrl.source})`);
56
+ console.log(`outputDir: ${formatMaybe(snapshot.outputDir.value)} (${snapshot.outputDir.source})`);
57
+ console.log(`channel: ${formatMaybe(snapshot.channel.value)} (${snapshot.channel.source})`);
58
+ console.log(`auth token: ${snapshot.authToken.value ? 'present' : 'missing'} (${formatAuthSource(snapshot.authSource)})`);
59
+ if (!snapshot.appId.value) {
60
+ console.log('fix appId: export OTAKIT_APP_ID=<app-id>');
61
+ }
62
+ if (!snapshot.authToken.value) {
63
+ console.log('fix auth: export OTAKIT_TOKEN=<token> # or run: otakit login');
64
+ }
65
+ });
66
+ });
67
+ const validateSubcommand = new Command('validate')
68
+ .description('Validate capacitor.config.* OtaKit settings in the current project')
69
+ .option('--json', 'Print machine-readable JSON output')
70
+ .action(async (options) => {
71
+ await runCommand(async () => {
72
+ try {
73
+ const config = readProjectConfig();
74
+ if (!config) {
75
+ const message = `No ${PROJECT_CONFIG_LABEL} found in the current directory or its parents.`;
76
+ if (options.json) {
77
+ console.log(JSON.stringify({
78
+ ok: false,
79
+ error: message,
80
+ }, null, 2));
81
+ process.exitCode = 2;
82
+ return;
83
+ }
84
+ throw new CliError([
85
+ message,
86
+ 'Add OtaKit plugin config to capacitor.config.ts, or pass flags/env directly.',
87
+ ].join('\n'), 2);
88
+ }
89
+ if (options.json) {
90
+ console.log(JSON.stringify({
91
+ ok: true,
92
+ config,
93
+ }, null, 2));
94
+ return;
95
+ }
96
+ console.log(`${PROJECT_CONFIG_LABEL} OtaKit settings are valid.`);
97
+ }
98
+ catch (error) {
99
+ if (!options.json) {
100
+ throw error;
101
+ }
102
+ const message = error instanceof Error ? error.message : 'Config validation failed.';
103
+ console.log(JSON.stringify({
104
+ ok: false,
105
+ error: message,
106
+ }, null, 2));
107
+ process.exitCode = 1;
108
+ }
109
+ });
110
+ });
111
+ export const configCommand = new Command('config')
112
+ .description('Validate and inspect resolved CLI configuration')
113
+ .addCommand(validateSubcommand)
114
+ .addCommand(resolveSubcommand);
115
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const deleteCommand: Command;
3
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,aAAa,SAyBtB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Command } from 'commander';
2
+ import { ApiClient } from '../lib/api.js';
3
+ import { requireConfig } from '../lib/config.js';
4
+ import { runCommand } from '../lib/errors.js';
5
+ import { confirm } from '../lib/prompt.js';
6
+ export const deleteCommand = new Command('delete')
7
+ .description('Delete a bundle')
8
+ .argument('<bundleId>', 'Bundle ID to delete')
9
+ .option('--app-id <id>', 'App ID override')
10
+ .option('--server <url>', 'Server URL override')
11
+ .option('--force', 'Skip confirmation')
12
+ .action(async (bundleId, options) => {
13
+ await runCommand(async () => {
14
+ const config = await requireConfig({
15
+ appId: options.appId,
16
+ serverUrl: options.server,
17
+ });
18
+ const api = new ApiClient(config);
19
+ if (!options.force) {
20
+ const accepted = await confirm(`Delete bundle ${bundleId}?`);
21
+ if (!accepted) {
22
+ console.log('Cancelled.');
23
+ return;
24
+ }
25
+ }
26
+ await api.deleteBundle(bundleId);
27
+ console.log(`Deleted bundle ${bundleId}.`);
28
+ });
29
+ });
30
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAQ3C,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,iBAAiB,CAAC;KAC9B,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAC;KAC7C,MAAM,CAAC,eAAe,EAAE,iBAAiB,CAAC;KAC1C,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KAC/C,MAAM,CAAC,SAAS,EAAE,mBAAmB,CAAC;KACtC,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAAsB,EAAE,EAAE;IACzD,MAAM,UAAU,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,SAAS,EAAE,OAAO,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,iBAAiB,QAAQ,GAAG,CAAC,CAAC;YAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,kBAAkB,QAAQ,GAAG,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const generateSigningKeyCommand: Command;
3
+ //# sourceMappingURL=generate-signing-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-signing-key.d.ts","sourceRoot":"","sources":["../../src/commands/generate-signing-key.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,yBAAyB,SA+ClC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import crypto from 'node:crypto';
2
+ import { Command } from 'commander';
3
+ import { runCommand } from '../lib/errors.js';
4
+ export const generateSigningKeyCommand = new Command('generate-signing-key')
5
+ .description('Generate an ES256 key pair for manifest signing')
6
+ .option('--kid <kid>', 'Key ID (default: auto-generated)')
7
+ .action(async (options) => {
8
+ await runCommand(async () => {
9
+ const kid = options.kid ??
10
+ `key-${new Date().toISOString().slice(0, 10)}-${crypto.randomBytes(4).toString('hex')}`;
11
+ const keyPair = crypto.generateKeyPairSync('ec', {
12
+ namedCurve: 'prime256v1',
13
+ });
14
+ const verificationKeyObject = keyPair['public' + 'Key'];
15
+ if (!(verificationKeyObject instanceof crypto.KeyObject)) {
16
+ throw new Error('Failed to derive verification key');
17
+ }
18
+ const verificationKeyDer = verificationKeyObject.export({
19
+ type: 'spki',
20
+ format: 'der',
21
+ });
22
+ const signingKeyPem = keyPair.privateKey.export({
23
+ type: 'pkcs8',
24
+ format: 'pem',
25
+ });
26
+ const verificationKeyBase64 = verificationKeyDer.toString('base64');
27
+ console.log('=== Manifest Signing Key Pair ===\n');
28
+ console.log(`Key ID (kid): ${kid}\n`);
29
+ console.log('--- Server Environment Variable ---');
30
+ console.log('Add these to your server .env:\n');
31
+ console.log(`MANIFEST_SIGNING_KID=${kid}`);
32
+ console.log(`MANIFEST_SIGNING_KEY="${signingKeyPem.replace(/\n/g, '\\n')}"\n`);
33
+ console.log('--- Plugin Config (capacitor.config.ts) ---');
34
+ console.log('Add this to your OtaKit plugin config:\n');
35
+ console.log(JSON.stringify({
36
+ manifestKeys: [{ kid, key: verificationKeyBase64 }],
37
+ }, null, 2));
38
+ console.log('');
39
+ });
40
+ });
41
+ //# sourceMappingURL=generate-signing-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-signing-key.js","sourceRoot":"","sources":["../../src/commands/generate-signing-key.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,OAAO,CAAC,sBAAsB,CAAC;KACzE,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,aAAa,EAAE,kCAAkC,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC1C,MAAM,UAAU,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,GAAG,GACP,OAAO,CAAC,GAAG;YACX,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAE1F,MAAM,OAAO,GAAG,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE;YAC/C,UAAU,EAAE,YAAY;SACzB,CAAC,CAAC;QACH,MAAM,qBAAqB,GAAI,OAAuD,CACpF,QAAQ,GAAG,KAAK,CACjB,CAAC;QACF,IAAI,CAAC,CAAC,qBAAqB,YAAY,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,MAAM,CAAC;YACtD,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,KAAK;SACd,CAAW,CAAC;QACb,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC;YAC9C,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,KAAK;SACd,CAAW,CAAC;QACb,MAAM,qBAAqB,GAAG,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEpE,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,yBAAyB,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ;YACE,YAAY,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,qBAAqB,EAAE,CAAC;SACpD,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const listCommand: Command;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,WAAW,SA2BpB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Command } from 'commander';
2
+ import { ApiClient } from '../lib/api.js';
3
+ import { requireConfig } from '../lib/config.js';
4
+ import { runCommand } from '../lib/errors.js';
5
+ import { parsePositiveInteger } from '../lib/validate.js';
6
+ export const listCommand = new Command('list')
7
+ .description('List all bundles')
8
+ .option('--app-id <id>', 'App ID override')
9
+ .option('--server <url>', 'Server URL override')
10
+ .option('--limit <n>', 'Limit results', '20')
11
+ .action(async (options) => {
12
+ await runCommand(async () => {
13
+ const config = await requireConfig({
14
+ appId: options.appId,
15
+ serverUrl: options.server,
16
+ });
17
+ const api = new ApiClient(config);
18
+ const limit = Math.min(parsePositiveInteger(options.limit, 'limit'), 200);
19
+ const response = await api.listBundles({ limit });
20
+ if (response.bundles.length === 0) {
21
+ console.log('No bundles found.');
22
+ return;
23
+ }
24
+ for (const bundle of response.bundles) {
25
+ console.log(`${bundle.id} ${bundle.version} ${bundle.size} bytes`);
26
+ }
27
+ console.log(`Total: ${response.total}`);
28
+ });
29
+ });
30
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAQ1D,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,kBAAkB,CAAC;KAC/B,MAAM,CAAC,eAAe,EAAE,iBAAiB,CAAC;KAC1C,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KAC/C,MAAM,CAAC,aAAa,EAAE,eAAe,EAAE,IAAI,CAAC;KAC5C,MAAM,CAAC,KAAK,EAAE,OAAoB,EAAE,EAAE;IACrC,MAAM,UAAU,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,SAAS,EAAE,OAAO,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QAElC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QAE1E,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAElD,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACjC,OAAO;QACT,CAAC;QAED,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,UAAU,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const loginCommand: Command;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BpC,eAAO,MAAM,YAAY,SAsFrB,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import { resolveServerUrl } from '../lib/config.js';
4
+ import { CliError, runCommand } from '../lib/errors.js';
5
+ import { fetchCli, parseApiError } from '../lib/http.js';
6
+ import { ask } from '../lib/prompt.js';
7
+ import { storeAccessToken } from '../lib/token-store.js';
8
+ const OTP_REGEX = /^\d{6}$/;
9
+ function toShellLiteral(value) {
10
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
11
+ }
12
+ export const loginCommand = new Command('login')
13
+ .description('Sign in with email OTP and store access token')
14
+ .option('--email <email>', 'Email address')
15
+ .option('--server <url>', 'Server URL')
16
+ .option('--token-only', 'Print only the token to stdout')
17
+ .action(async (options) => {
18
+ await runCommand(async () => {
19
+ const serverUrl = resolveServerUrl(process.cwd(), options.server);
20
+ const emailInput = options.email?.trim().toLowerCase() || (await ask('Email: ')).trim().toLowerCase();
21
+ if (!emailInput) {
22
+ throw new CliError('Email is required.');
23
+ }
24
+ const sendSpinner = ora('Sending verification code...').start();
25
+ const sendOtpResponse = await fetchCli(`${serverUrl}/api/auth/email-otp/send-verification-otp`, {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ },
30
+ body: JSON.stringify({ email: emailInput, type: 'sign-in' }),
31
+ });
32
+ if (!sendOtpResponse.ok) {
33
+ sendSpinner.fail('Could not send verification code');
34
+ throw new CliError(await parseApiError(sendOtpResponse));
35
+ }
36
+ sendSpinner.succeed('Verification code sent');
37
+ const otp = (await ask('Verification code: ')).trim();
38
+ if (!OTP_REGEX.test(otp)) {
39
+ throw new CliError('Invalid verification code. Enter the 6-digit code.');
40
+ }
41
+ const verifySpinner = ora('Verifying code...').start();
42
+ const signInResponse = await fetchCli(`${serverUrl}/api/auth/sign-in/email-otp`, {
43
+ method: 'POST',
44
+ headers: {
45
+ 'Content-Type': 'application/json',
46
+ },
47
+ body: JSON.stringify({ email: emailInput, otp }),
48
+ });
49
+ if (!signInResponse.ok) {
50
+ verifySpinner.fail('Sign-in failed');
51
+ throw new CliError(await parseApiError(signInResponse));
52
+ }
53
+ const payload = (await signInResponse.json());
54
+ const token = typeof payload.token === 'string' ? payload.token.trim() : '';
55
+ if (!token) {
56
+ verifySpinner.fail('Sign-in failed');
57
+ throw new CliError('Server returned an invalid auth response.');
58
+ }
59
+ const storeResult = await storeAccessToken(serverUrl, token);
60
+ verifySpinner.succeed('Signed in');
61
+ if (options.tokenOnly) {
62
+ process.stdout.write(`${token}\n`);
63
+ if (!storeResult.ok) {
64
+ console.error(`Warning: could not store token locally (${storeResult.reason ?? 'unknown reason'}).`);
65
+ }
66
+ return;
67
+ }
68
+ if (storeResult.ok) {
69
+ const signedInAs = typeof payload.user?.email === 'string' ? ` as ${payload.user.email}` : '';
70
+ console.log(`Logged in${signedInAs}.`);
71
+ console.log(`Token stored locally for ${serverUrl}.`);
72
+ return;
73
+ }
74
+ console.warn(`Could not store token locally: ${storeResult.reason ?? 'unknown reason'}.`);
75
+ console.log('Use env fallback in this shell:');
76
+ console.log(`export OTAKIT_TOKEN=${toShellLiteral(token)}`);
77
+ });
78
+ });
79
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const logoutCommand: Command;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,aAAa,SAmBtB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { Command } from 'commander';
2
+ import { resolveServerUrl } from '../lib/config.js';
3
+ import { runCommand } from '../lib/errors.js';
4
+ import { clearStoredAccessToken } from '../lib/token-store.js';
5
+ export const logoutCommand = new Command('logout')
6
+ .description('Remove stored access token')
7
+ .option('--server <url>', 'Server URL')
8
+ .action(async (options) => {
9
+ await runCommand(async () => {
10
+ const serverUrl = resolveServerUrl(process.cwd(), options.server);
11
+ const result = await clearStoredAccessToken(serverUrl);
12
+ if (!result.ok) {
13
+ console.warn(`Could not update local token store: ${result.reason ?? 'unknown reason'}.`);
14
+ }
15
+ else if (result.deleted) {
16
+ console.log(`Removed stored token for ${serverUrl}.`);
17
+ }
18
+ else {
19
+ console.log(`No stored token found for ${serverUrl}.`);
20
+ }
21
+ console.log('If needed for this shell session, also run:');
22
+ console.log('unset OTAKIT_TOKEN');
23
+ });
24
+ });
25
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAM/D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,4BAA4B,CAAC;KACzC,MAAM,CAAC,gBAAgB,EAAE,YAAY,CAAC;KACtC,MAAM,CAAC,KAAK,EAAE,OAAsB,EAAE,EAAE;IACvC,MAAM,UAAU,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAEvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,uCAAuC,MAAM,CAAC,MAAM,IAAI,gBAAgB,GAAG,CAAC,CAAC;QAC5F,CAAC;aAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,4BAA4B,SAAS,GAAG,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,6BAA6B,SAAS,GAAG,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const registerCommand: Command;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/commands/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBpC,eAAO,MAAM,eAAe,SAmFxB,CAAC"}