@scalebun/cli 0.1.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/bin/scalebun.js +2 -0
- package/lib/api/client.d.ts +21 -0
- package/lib/api/client.d.ts.map +1 -0
- package/lib/api/client.js +151 -0
- package/lib/api/client.js.map +1 -0
- package/lib/commands/ci-init.d.ts +9 -0
- package/lib/commands/ci-init.d.ts.map +1 -0
- package/lib/commands/ci-init.js +100 -0
- package/lib/commands/ci-init.js.map +1 -0
- package/lib/commands/launch.d.ts +3 -0
- package/lib/commands/launch.d.ts.map +1 -0
- package/lib/commands/launch.js +23 -0
- package/lib/commands/launch.js.map +1 -0
- package/lib/commands/login.d.ts +10 -0
- package/lib/commands/login.d.ts.map +1 -0
- package/lib/commands/login.js +110 -0
- package/lib/commands/login.js.map +1 -0
- package/lib/commands/migrate-codepush.d.ts +13 -0
- package/lib/commands/migrate-codepush.d.ts.map +1 -0
- package/lib/commands/migrate-codepush.js +98 -0
- package/lib/commands/migrate-codepush.js.map +1 -0
- package/lib/commands/ota-bundle.d.ts +9 -0
- package/lib/commands/ota-bundle.d.ts.map +1 -0
- package/lib/commands/ota-bundle.js +87 -0
- package/lib/commands/ota-bundle.js.map +1 -0
- package/lib/commands/ota-channels.d.ts +3 -0
- package/lib/commands/ota-channels.d.ts.map +1 -0
- package/lib/commands/ota-channels.js +39 -0
- package/lib/commands/ota-channels.js.map +1 -0
- package/lib/commands/ota-delete-bundle.d.ts +3 -0
- package/lib/commands/ota-delete-bundle.d.ts.map +1 -0
- package/lib/commands/ota-delete-bundle.js +31 -0
- package/lib/commands/ota-delete-bundle.js.map +1 -0
- package/lib/commands/ota-publish.d.ts +16 -0
- package/lib/commands/ota-publish.d.ts.map +1 -0
- package/lib/commands/ota-publish.js +223 -0
- package/lib/commands/ota-publish.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +39 -0
- package/lib/index.js.map +1 -0
- package/lib/utils/bundle.d.ts +37 -0
- package/lib/utils/bundle.d.ts.map +1 -0
- package/lib/utils/bundle.js +94 -0
- package/lib/utils/bundle.js.map +1 -0
- package/lib/utils/credentials.d.ts +15 -0
- package/lib/utils/credentials.d.ts.map +1 -0
- package/lib/utils/credentials.js +83 -0
- package/lib/utils/credentials.js.map +1 -0
- package/lib/utils/hash.d.ts +3 -0
- package/lib/utils/hash.d.ts.map +1 -0
- package/lib/utils/hash.js +44 -0
- package/lib/utils/hash.js.map +1 -0
- package/lib/utils/ui.d.ts +4 -0
- package/lib/utils/ui.d.ts.map +1 -0
- package/lib/utils/ui.js +51 -0
- package/lib/utils/ui.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,87 @@
|
|
|
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.registerOtaBundleCommand = registerOtaBundleCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const bundle_1 = require("../utils/bundle");
|
|
40
|
+
/**
|
|
41
|
+
* `scalebun ota bundle` — package a standalone bundle file for Dashboard upload.
|
|
42
|
+
*
|
|
43
|
+
* Usage:
|
|
44
|
+
* npx scalebun ota bundle --platform android --output ./my-app.bundle
|
|
45
|
+
*/
|
|
46
|
+
function registerOtaBundleCommand(ota) {
|
|
47
|
+
ota
|
|
48
|
+
.command('bundle')
|
|
49
|
+
.description('Build a standalone OTA bundle file for manual upload in the Scalebun Dashboard')
|
|
50
|
+
.option('--platform <platform>', 'Target platform: android | ios', 'android')
|
|
51
|
+
.option('--entry-file <path>', 'JS entry file', 'index.js')
|
|
52
|
+
.option('--output <path>', 'Output bundle destination path', './index.android.bundle')
|
|
53
|
+
.option('--hermes', 'Compile to Hermes bytecode (recommended for production)')
|
|
54
|
+
.option('--hermes-disabled', 'Explicitly disable Hermes bytecode compilation')
|
|
55
|
+
.option('--sourcemap', 'Generate sourcemap alongside the bundle')
|
|
56
|
+
.action(async (opts) => {
|
|
57
|
+
const platform = opts.platform;
|
|
58
|
+
const useHermes = opts.hermesDisabled ? false : opts.hermes;
|
|
59
|
+
console.log(`📦 Bundling ${platform} application${useHermes ? ' (Hermes bytecode)' : ''}…`);
|
|
60
|
+
try {
|
|
61
|
+
const result = (0, bundle_1.buildBundle)({
|
|
62
|
+
platform,
|
|
63
|
+
entryFile: opts.entryFile,
|
|
64
|
+
dev: false,
|
|
65
|
+
hermes: useHermes,
|
|
66
|
+
sourcemap: opts.sourcemap,
|
|
67
|
+
});
|
|
68
|
+
const destPath = path.resolve(opts.output);
|
|
69
|
+
const destDir = path.dirname(destPath);
|
|
70
|
+
if (!fs.existsSync(destDir)) {
|
|
71
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
fs.copyFileSync(result.bundlePath, destPath);
|
|
74
|
+
const stats = fs.statSync(destPath);
|
|
75
|
+
const sizeMb = (stats.size / (1024 * 1024)).toFixed(2);
|
|
76
|
+
console.log(`\n✅ Bundle successfully created!`);
|
|
77
|
+
console.log(` Output Path: ${destPath}`);
|
|
78
|
+
console.log(` Size: ${sizeMb} MB (${stats.size} bytes)`);
|
|
79
|
+
console.log(`\n👉 You can now drag & drop this file into the Scalebun Dashboard at http://localhost:3000/ota`);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
console.error(`❌ Bundling failed: ${err?.message || err}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=ota-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-bundle.js","sourceRoot":"","sources":["../../src/commands/ota-bundle.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,4DAqDC;AAhED,uCAAyB;AACzB,2CAA6B;AAE7B,4CAA8C;AAE9C;;;;;GAKG;AACH,SAAgB,wBAAwB,CAAC,GAAY;IACnD,GAAG;SACA,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,gFAAgF,CAAC;SAC7F,MAAM,CAAC,uBAAuB,EAAE,gCAAgC,EAAE,SAAS,CAAC;SAC5E,MAAM,CAAC,qBAAqB,EAAE,eAAe,EAAE,UAAU,CAAC;SAC1D,MAAM,CAAC,iBAAiB,EAAE,gCAAgC,EAAE,wBAAwB,CAAC;SACrF,MAAM,CAAC,UAAU,EAAE,yDAAyD,CAAC;SAC7E,MAAM,CAAC,mBAAmB,EAAE,gDAAgD,CAAC;SAC7E,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;SAChE,MAAM,CACL,KAAK,EAAE,IAON,EAAE,EAAE;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAA6B,CAAC;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAE5D,OAAO,CAAC,GAAG,CAAC,eAAe,QAAQ,eAAe,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAE5F,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAA,oBAAW,EAAC;gBACzB,QAAQ;gBACR,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,EAAE,KAAK;gBACV,MAAM,EAAE,SAAS;gBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC7C,CAAC;YAED,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAEvD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,mBAAmB,MAAM,QAAQ,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC;YAClE,OAAO,CAAC,GAAG,CAAC,iGAAiG,CAAC,CAAC;QACjH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,sBAAsB,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CACF,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-channels.d.ts","sourceRoot":"","sources":["../../src/commands/ota-channels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA+B7D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerOtaChannelsCommand = registerOtaChannelsCommand;
|
|
4
|
+
const credentials_1 = require("../utils/credentials");
|
|
5
|
+
const client_1 = require("../api/client");
|
|
6
|
+
function registerOtaChannelsCommand(ota) {
|
|
7
|
+
ota
|
|
8
|
+
.command('channels')
|
|
9
|
+
.alias('ota channel list')
|
|
10
|
+
.description('List all OTA channels for an app')
|
|
11
|
+
.requiredOption('--app-id <id>', 'Scalebun app ID')
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const creds = (0, credentials_1.readCredentials)();
|
|
14
|
+
if (!creds) {
|
|
15
|
+
console.error('❌ Not logged in. Run `scalebun login` first.');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const client = new client_1.ApiClient(creds);
|
|
19
|
+
try {
|
|
20
|
+
const channels = await client.get(`/saas/apps/${opts.appId}/ota/channels`);
|
|
21
|
+
console.log(`\n📋 OTA Channels for App (${opts.appId}):\n`);
|
|
22
|
+
if (!channels || channels.length === 0) {
|
|
23
|
+
console.log(' (No channels found yet. Running `scalebun ota publish` will automatically create the `default` channel.)');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
channels.forEach((c) => {
|
|
27
|
+
const envName = c.environment?.name ? ` [Env: ${c.environment.name}]` : '';
|
|
28
|
+
console.log(` • Name: ${c.name.padEnd(16)} ID: ${c.id}${envName}`);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
console.log('');
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
console.error(`❌ Failed to list channels: ${err.message}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=ota-channels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-channels.js","sourceRoot":"","sources":["../../src/commands/ota-channels.ts"],"names":[],"mappings":";;AAaA,gEA+BC;AA3CD,sDAAuD;AACvD,0CAA0C;AAW1C,SAAgB,0BAA0B,CAAC,GAAY;IACrD,GAAG;SACA,OAAO,CAAC,UAAU,CAAC;SACnB,KAAK,CAAC,kBAAkB,CAAC;SACzB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,cAAc,CAAC,eAAe,EAAE,iBAAiB,CAAC;SAClD,MAAM,CAAC,KAAK,EAAE,IAAuB,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,IAAA,6BAAe,GAAE,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAgB,cAAc,IAAI,CAAC,KAAK,eAAe,CAAC,CAAC;YAC1F,OAAO,CAAC,GAAG,CAAC,8BAA8B,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvC,OAAO,CAAC,GAAG,CAAC,4GAA4G,CAAC,CAAC;YAC5H,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;oBACrB,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3E,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;gBACtE,CAAC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-delete-bundle.d.ts","sourceRoot":"","sources":["../../src/commands/ota-delete-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAwBjE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerOtaDeleteBundleCommand = registerOtaDeleteBundleCommand;
|
|
4
|
+
const credentials_1 = require("../utils/credentials");
|
|
5
|
+
const client_1 = require("../api/client");
|
|
6
|
+
function registerOtaDeleteBundleCommand(ota) {
|
|
7
|
+
ota
|
|
8
|
+
.command('delete-bundle')
|
|
9
|
+
.alias('delete')
|
|
10
|
+
.description('Delete an OTA bundle permanently')
|
|
11
|
+
.requiredOption('--app-id <id>', 'Scalebun app ID')
|
|
12
|
+
.requiredOption('--bundle-id <id>', 'OTA bundle ID to delete')
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const creds = (0, credentials_1.readCredentials)();
|
|
15
|
+
if (!creds) {
|
|
16
|
+
console.error('❌ Not logged in. Run `scalebun login` first.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const client = new client_1.ApiClient(creds);
|
|
20
|
+
try {
|
|
21
|
+
console.log(`🗑️ Deleting bundle ${opts.bundleId} from App ${opts.appId}…`);
|
|
22
|
+
await client.delete(`/saas/apps/${opts.appId}/ota/bundles/${opts.bundleId}`);
|
|
23
|
+
console.log(`✅ Bundle ${opts.bundleId} deleted successfully.`);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.error(`❌ Failed to delete bundle: ${err.message}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ota-delete-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-delete-bundle.js","sourceRoot":"","sources":["../../src/commands/ota-delete-bundle.ts"],"names":[],"mappings":";;AAIA,wEAwBC;AA3BD,sDAAuD;AACvD,0CAA0C;AAE1C,SAAgB,8BAA8B,CAAC,GAAY;IACzD,GAAG;SACA,OAAO,CAAC,eAAe,CAAC;SACxB,KAAK,CAAC,QAAQ,CAAC;SACf,WAAW,CAAC,kCAAkC,CAAC;SAC/C,cAAc,CAAC,eAAe,EAAE,iBAAiB,CAAC;SAClD,cAAc,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;SAC7D,MAAM,CAAC,KAAK,EAAE,IAAyC,EAAE,EAAE;QAC1D,MAAM,KAAK,GAAG,IAAA,6BAAe,GAAE,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,CAAC,QAAQ,aAAa,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;YAC5E,MAAM,MAAM,CAAC,MAAM,CAAM,cAAc,IAAI,CAAC,KAAK,gBAAgB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAClF,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,QAAQ,wBAAwB,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export type InstallMode = 'IMMEDIATE' | 'ON_NEXT_RESTART' | 'ON_NEXT_RESUME';
|
|
3
|
+
/**
|
|
4
|
+
* `scalebun ota publish` — the flagship CLI command.
|
|
5
|
+
*
|
|
6
|
+
* Flow:
|
|
7
|
+
* 1. Build the RN JS bundle (npx react-native bundle, Hermes default)
|
|
8
|
+
* 2. Compute SHA-256 of the output
|
|
9
|
+
* 3. POST /saas/apps/:appId/ota/bundles/presign → presigned PUT URL
|
|
10
|
+
* 4. PUT the bytes directly to storage (R2/S3)
|
|
11
|
+
* 5. POST /saas/apps/:appId/ota/bundles/:id/finalize → version assigned
|
|
12
|
+
* 6. POST /saas/apps/:appId/ota/bundles/:id/promote → configure installMode & rollout
|
|
13
|
+
* 7. Print success
|
|
14
|
+
*/
|
|
15
|
+
export declare function registerOtaPublishCommand(ota: Command): void;
|
|
16
|
+
//# sourceMappingURL=ota-publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-publish.d.ts","sourceRoot":"","sources":["../../src/commands/ota-publish.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsBpC,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAE7E;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAwN5D"}
|
|
@@ -0,0 +1,223 @@
|
|
|
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.registerOtaPublishCommand = registerOtaPublishCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const credentials_1 = require("../utils/credentials");
|
|
39
|
+
const client_1 = require("../api/client");
|
|
40
|
+
const bundle_1 = require("../utils/bundle");
|
|
41
|
+
const hash_1 = require("../utils/hash");
|
|
42
|
+
/**
|
|
43
|
+
* `scalebun ota publish` — the flagship CLI command.
|
|
44
|
+
*
|
|
45
|
+
* Flow:
|
|
46
|
+
* 1. Build the RN JS bundle (npx react-native bundle, Hermes default)
|
|
47
|
+
* 2. Compute SHA-256 of the output
|
|
48
|
+
* 3. POST /saas/apps/:appId/ota/bundles/presign → presigned PUT URL
|
|
49
|
+
* 4. PUT the bytes directly to storage (R2/S3)
|
|
50
|
+
* 5. POST /saas/apps/:appId/ota/bundles/:id/finalize → version assigned
|
|
51
|
+
* 6. POST /saas/apps/:appId/ota/bundles/:id/promote → configure installMode & rollout
|
|
52
|
+
* 7. Print success
|
|
53
|
+
*/
|
|
54
|
+
function registerOtaPublishCommand(ota) {
|
|
55
|
+
ota
|
|
56
|
+
.command('publish')
|
|
57
|
+
.description('Bundle, hash, upload, and finalize an OTA update release')
|
|
58
|
+
.requiredOption('--app-id <id>', 'Scalebun application ID')
|
|
59
|
+
.option('--channel <nameOrId>', 'OTA channel name (e.g. default, beta, production) or channel ID', 'default')
|
|
60
|
+
.option('--channel-id <id>', 'OTA channel ID (legacy alias)')
|
|
61
|
+
.option('--platform <platform>', 'Target platform: android | ios', 'android')
|
|
62
|
+
.option('--install-mode <mode>', 'Install & execution behavior: IMMEDIATE (forces instant app restart on download), ON_NEXT_RESTART (applies silently on next cold boot - default), ON_NEXT_RESUME (applies when app resumes)', 'ON_NEXT_RESTART')
|
|
63
|
+
.option('--target-version <semver>', 'Target app native semver range (e.g. ">=1.0.0", "1.0.0")', '>=1.0.0')
|
|
64
|
+
.option('--rollout <percent>', 'Target rollout percentage (1-100)', '100')
|
|
65
|
+
.option('--entry-file <path>', 'JS entry file', 'index.js')
|
|
66
|
+
.option('--release-note <text>', 'Release note for dashboard display and device changelog')
|
|
67
|
+
.option('--hermes', 'Compile to Hermes bytecode (recommended for production)')
|
|
68
|
+
.option('--hermes-disabled', 'Explicitly disable Hermes bytecode compilation')
|
|
69
|
+
.option('--skip-bundle', 'Skip react-native bundle (provide --bundle-path instead)')
|
|
70
|
+
.option('--bundle-path <path>', 'Path to a pre-built bundle file')
|
|
71
|
+
.option('--custom-bundle-path <path>', 'Alias for --bundle-path (explicit naming)')
|
|
72
|
+
.option('--sourcemap', 'Generate and upload sourcemap for crash symbolication')
|
|
73
|
+
.option('--keep-artifacts', 'Keep build artifacts (bundle + sourcemap) after upload')
|
|
74
|
+
.action(async (opts) => {
|
|
75
|
+
const creds = (0, credentials_1.readCredentials)();
|
|
76
|
+
if (!creds) {
|
|
77
|
+
console.error('❌ Not logged in. Run `scalebun login` first.');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
const rawInstallMode = (opts.installMode || 'ON_NEXT_RESTART').toUpperCase();
|
|
81
|
+
const validModes = ['IMMEDIATE', 'ON_NEXT_RESTART', 'ON_NEXT_RESUME'];
|
|
82
|
+
if (!validModes.includes(rawInstallMode)) {
|
|
83
|
+
console.error(`❌ Invalid --install-mode "${opts.installMode}". Valid options: IMMEDIATE, ON_NEXT_RESTART, ON_NEXT_RESUME`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const installMode = rawInstallMode;
|
|
87
|
+
const targetChannel = opts.channelId || opts.channel || 'default';
|
|
88
|
+
const client = new client_1.ApiClient(creds);
|
|
89
|
+
const platform = opts.platform;
|
|
90
|
+
// Step 1: Build the bundle (or use pre-built)
|
|
91
|
+
let bundlePath;
|
|
92
|
+
if (opts.skipBundle && (opts.bundlePath || opts.customBundlePath)) {
|
|
93
|
+
bundlePath = opts.bundlePath || opts.customBundlePath;
|
|
94
|
+
if (!fs.existsSync(bundlePath)) {
|
|
95
|
+
console.error(`❌ Bundle file not found: ${bundlePath}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
console.log(`📦 Using pre-built bundle: ${bundlePath}`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Resolve Hermes: --hermes-disabled takes precedence
|
|
102
|
+
const useHermes = opts.hermesDisabled ? false : opts.hermes;
|
|
103
|
+
console.log(`📦 Building ${platform} bundle${useHermes ? ' (Hermes bytecode)' : ''}…`);
|
|
104
|
+
const result = (0, bundle_1.buildBundle)({
|
|
105
|
+
platform,
|
|
106
|
+
entryFile: opts.entryFile,
|
|
107
|
+
dev: false,
|
|
108
|
+
hermes: useHermes,
|
|
109
|
+
sourcemap: opts.sourcemap,
|
|
110
|
+
});
|
|
111
|
+
bundlePath = result.bundlePath;
|
|
112
|
+
console.log(` ✅ Bundle built: ${bundlePath}`);
|
|
113
|
+
}
|
|
114
|
+
// Step 2: Hash the bundle
|
|
115
|
+
console.log('🔒 Computing SHA-256…');
|
|
116
|
+
const sha256 = (0, hash_1.sha256File)(bundlePath);
|
|
117
|
+
const sizeBytes = fs.statSync(bundlePath).size;
|
|
118
|
+
console.log(` Hash: ${sha256}`);
|
|
119
|
+
console.log(` Size: ${(sizeBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
120
|
+
if (sizeBytes > 50000000) {
|
|
121
|
+
console.error(`❌ Bundle is ${(sizeBytes / 1024 / 1024).toFixed(1)} MB — exceeds 50 MB limit`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
// Step 3: Get presigned upload URL
|
|
125
|
+
console.log('🔗 Requesting presigned upload URL…');
|
|
126
|
+
let presigned;
|
|
127
|
+
try {
|
|
128
|
+
presigned = await client.post(`/saas/apps/${opts.appId}/ota/bundles/presign`, {
|
|
129
|
+
channelId: targetChannel,
|
|
130
|
+
platform,
|
|
131
|
+
sha256,
|
|
132
|
+
sizeBytes,
|
|
133
|
+
releaseNote: opts.releaseNote,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
console.error(`❌ Presign failed: ${err.message}`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
console.log(` Bundle ID: ${presigned.bundleId}`);
|
|
141
|
+
console.log(` Upload URL expires in ${presigned.expiresIn}s`);
|
|
142
|
+
// Step 4: Upload to R2/S3
|
|
143
|
+
console.log('⬆️ Uploading bundle to storage…');
|
|
144
|
+
const bundleData = fs.readFileSync(bundlePath);
|
|
145
|
+
try {
|
|
146
|
+
await client.putBytes(presigned.uploadUrl, bundleData, 'application/octet-stream');
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.error(`❌ Upload failed: ${err.message}`);
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
console.log(' ✅ Upload complete');
|
|
153
|
+
// Step 5: Finalize — server-side SHA-256 verification + version assignment
|
|
154
|
+
console.log('🔍 Finalizing (server-side hash verification)…');
|
|
155
|
+
let finalized;
|
|
156
|
+
try {
|
|
157
|
+
finalized = await client.post(`/saas/apps/${opts.appId}/ota/bundles/${presigned.bundleId}/finalize`);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
console.error(`❌ Finalize failed: ${err.message}`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
// Step 6: Promote release to ACTIVE status with installMode
|
|
164
|
+
console.log('🚀 Promoting release to active target channel…');
|
|
165
|
+
try {
|
|
166
|
+
const rolloutPercent = parseInt(opts.rollout, 10) || 100;
|
|
167
|
+
await client.post(`/saas/apps/${opts.appId}/ota/bundles/${presigned.bundleId}/promote`, {
|
|
168
|
+
targetAppVersion: opts.targetVersion || '>=1.0.0',
|
|
169
|
+
rolloutPercent,
|
|
170
|
+
isMandatory: installMode === 'IMMEDIATE',
|
|
171
|
+
installMode,
|
|
172
|
+
releaseNote: opts.releaseNote,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
console.warn(` ⚠️ Promotion notice: ${err.message}`);
|
|
177
|
+
}
|
|
178
|
+
// Step 7: Upload sourcemap if generated
|
|
179
|
+
if (opts.sourcemap) {
|
|
180
|
+
const sourcemapPath = bundlePath + '.map';
|
|
181
|
+
if (fs.existsSync(sourcemapPath)) {
|
|
182
|
+
console.log('🗺️ Uploading sourcemap for crash symbolication…');
|
|
183
|
+
try {
|
|
184
|
+
const mapData = fs.readFileSync(sourcemapPath);
|
|
185
|
+
await client.post(`/saas/apps/${opts.appId}/ota/bundles/${presigned.bundleId}/sourcemap`, { sourcemap: mapData.toString('base64'), encoding: 'base64' });
|
|
186
|
+
console.log(' ✅ Sourcemap uploaded');
|
|
187
|
+
if (!opts.keepArtifacts) {
|
|
188
|
+
fs.unlinkSync(sourcemapPath);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
console.warn(` ⚠️ Sourcemap upload failed (non-fatal): ${err.message}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Step 8: Print detailed success summary
|
|
197
|
+
const installModeLabel = installMode === 'IMMEDIATE'
|
|
198
|
+
? '⚡ IMMEDIATE (App restarts right after download)'
|
|
199
|
+
: installMode === 'ON_NEXT_RESUME'
|
|
200
|
+
? '🔄 ON_NEXT_RESUME (Applies when app resumes)'
|
|
201
|
+
: '🌙 ON_NEXT_RESTART (Applies silently on next launch)';
|
|
202
|
+
console.log('');
|
|
203
|
+
console.log(`✅ Bundle v${finalized.version} published successfully!`);
|
|
204
|
+
console.log(` Channel: ${finalized.channelName} (${finalized.environmentName})`);
|
|
205
|
+
console.log(` Platform: ${finalized.platform}`);
|
|
206
|
+
console.log(` Install Mode: ${installModeLabel}`);
|
|
207
|
+
console.log(` SHA-256: ${finalized.sha256}`);
|
|
208
|
+
console.log(` Size: ${(finalized.sizeBytes / 1024).toFixed(1)} KB`);
|
|
209
|
+
if (opts.sourcemap) {
|
|
210
|
+
console.log(` Sourcemap: Uploaded ✓ (Stack traces will auto-symbolicate)`);
|
|
211
|
+
}
|
|
212
|
+
// Clean up bundle unless --keep-artifacts or using pre-built
|
|
213
|
+
if (!opts.keepArtifacts && !opts.skipBundle) {
|
|
214
|
+
try {
|
|
215
|
+
fs.unlinkSync(bundlePath);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// non-fatal
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=ota-publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ota-publish.js","sourceRoot":"","sources":["../../src/commands/ota-publish.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const commander_1 = require("commander");
|
|
4
|
+
const ota_publish_1 = require("./commands/ota-publish");
|
|
5
|
+
const ota_bundle_1 = require("./commands/ota-bundle");
|
|
6
|
+
const ota_channels_1 = require("./commands/ota-channels");
|
|
7
|
+
const ota_delete_bundle_1 = require("./commands/ota-delete-bundle");
|
|
8
|
+
const launch_1 = require("./commands/launch");
|
|
9
|
+
const migrate_codepush_1 = require("./commands/migrate-codepush");
|
|
10
|
+
const ci_init_1 = require("./commands/ci-init");
|
|
11
|
+
const ui_1 = require("./utils/ui");
|
|
12
|
+
const program = new commander_1.Command();
|
|
13
|
+
program
|
|
14
|
+
.name('scalebun')
|
|
15
|
+
.description('Scalebun CLI — OTA bundle publishing and management')
|
|
16
|
+
.version('0.1.0')
|
|
17
|
+
.action(() => {
|
|
18
|
+
(0, ui_1.renderBanner)();
|
|
19
|
+
(0, ui_1.renderStatus)();
|
|
20
|
+
(0, ui_1.renderCommands)();
|
|
21
|
+
});
|
|
22
|
+
const ota = program.command('ota').description('OTA update management');
|
|
23
|
+
(0, ota_publish_1.registerOtaPublishCommand)(ota);
|
|
24
|
+
(0, ota_bundle_1.registerOtaBundleCommand)(ota);
|
|
25
|
+
(0, ota_channels_1.registerOtaChannelsCommand)(ota);
|
|
26
|
+
(0, ota_delete_bundle_1.registerOtaDeleteBundleCommand)(ota);
|
|
27
|
+
(0, launch_1.registerLaunchCommand)(program);
|
|
28
|
+
const migrate = program.command('migrate').description('Migration utilities from other platforms');
|
|
29
|
+
(0, migrate_codepush_1.registerMigrateCodepushCommand)(migrate);
|
|
30
|
+
(0, ci_init_1.registerCiInitCommand)(program);
|
|
31
|
+
if (process.argv.length <= 2) {
|
|
32
|
+
(0, ui_1.renderBanner)();
|
|
33
|
+
(0, ui_1.renderStatus)();
|
|
34
|
+
(0, ui_1.renderCommands)();
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
program.parse(process.argv);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yCAAoC;AAEpC,wDAAmE;AACnE,sDAAiE;AACjE,0DAAqE;AACrE,oEAA8E;AAC9E,8CAA0D;AAC1D,kEAA6E;AAC7E,gDAA2D;AAC3D,mCAAwE;AAExE,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,qDAAqD,CAAC;KAClE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,GAAG,EAAE;IACX,IAAA,iBAAY,GAAE,CAAC;IACf,IAAA,iBAAY,GAAE,CAAC;IACf,IAAA,mBAAc,GAAE,CAAC;AACnB,CAAC,CAAC,CAAC;AAEL,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC;AACxE,IAAA,uCAAyB,EAAC,GAAG,CAAC,CAAC;AAC/B,IAAA,qCAAwB,EAAC,GAAG,CAAC,CAAC;AAC9B,IAAA,yCAA0B,EAAC,GAAG,CAAC,CAAC;AAChC,IAAA,kDAA8B,EAAC,GAAG,CAAC,CAAC;AACpC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AAE/B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,0CAA0C,CAAC,CAAC;AACnG,IAAA,iDAA8B,EAAC,OAAO,CAAC,CAAC;AACxC,IAAA,+BAAqB,EAAC,OAAO,CAAC,CAAC;AAE/B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;IAC7B,IAAA,iBAAY,GAAE,CAAC;IACf,IAAA,iBAAY,GAAE,CAAC;IACf,IAAA,mBAAc,GAAE,CAAC;AACnB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface BundleOptions {
|
|
2
|
+
platform: 'android' | 'ios';
|
|
3
|
+
entryFile: string;
|
|
4
|
+
dev: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* If true, run hermesc to compile the JS bundle to Hermes bytecode (.hbc).
|
|
7
|
+
* Default: false (Sprint 2). Sprint 7 patch engine requires .hbc for
|
|
8
|
+
* correct diffing — enable this flag when binary patching ships.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: `react-native bundle` in RN 0.74+ with Hermes enabled in the
|
|
11
|
+
* project config (build.gradle / Podfile) outputs plain JS that gets
|
|
12
|
+
* compiled to Hermes bytecode during the native build step, NOT during
|
|
13
|
+
* `react-native bundle`. For OTA bundles that skip the native build,
|
|
14
|
+
* we must explicitly run hermesc to produce the .hbc artifact.
|
|
15
|
+
*
|
|
16
|
+
* CAVEAT (Sprint 2): Without hermesc, OTA bundles are plain JS interpreted
|
|
17
|
+
* by Hermes (works correctly, but ~20-30% slower cold startup compared to
|
|
18
|
+
* pre-compiled bytecode). This is acceptable for Sprint 2; the hermesc
|
|
19
|
+
* step will be mandatory when the patch engine ships.
|
|
20
|
+
*/
|
|
21
|
+
hermes?: boolean;
|
|
22
|
+
/** If true, generate a sourcemap alongside the bundle. */
|
|
23
|
+
sourcemap?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface BundleResult {
|
|
26
|
+
bundlePath: string;
|
|
27
|
+
assetsPath: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Shell out to `npx react-native bundle` to produce a JS bundle.
|
|
31
|
+
*
|
|
32
|
+
* When opts.hermes is true, also runs hermesc to compile to bytecode.
|
|
33
|
+
* The native runtime detects the format from magic bytes (\x1f\x\xbc —
|
|
34
|
+
* Hermes bytecode header), so the same .jsbundle extension works for both.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildBundle(opts: BundleOptions): BundleResult;
|
|
37
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../src/utils/bundle.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,SAAS,GAAG,KAAK,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,OAAO,CAAC;IACb;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,YAAY,CA+D7D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
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.buildBundle = buildBundle;
|
|
37
|
+
const childProcess = __importStar(require("child_process"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const os = __importStar(require("os"));
|
|
41
|
+
/**
|
|
42
|
+
* Shell out to `npx react-native bundle` to produce a JS bundle.
|
|
43
|
+
*
|
|
44
|
+
* When opts.hermes is true, also runs hermesc to compile to bytecode.
|
|
45
|
+
* The native runtime detects the format from magic bytes (\x1f\x\xbc —
|
|
46
|
+
* Hermes bytecode header), so the same .jsbundle extension works for both.
|
|
47
|
+
*/
|
|
48
|
+
function buildBundle(opts) {
|
|
49
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'scalebun-bundle-'));
|
|
50
|
+
const bundlePath = path.join(tmpDir, 'bundle.jsbundle');
|
|
51
|
+
const assetsPath = path.join(tmpDir, 'assets');
|
|
52
|
+
fs.mkdirSync(assetsPath, { recursive: true });
|
|
53
|
+
const args = [
|
|
54
|
+
'react-native', 'bundle',
|
|
55
|
+
'--platform', opts.platform,
|
|
56
|
+
'--dev', String(opts.dev),
|
|
57
|
+
'--entry-file', opts.entryFile,
|
|
58
|
+
'--bundle-output', bundlePath,
|
|
59
|
+
'--assets-dest', assetsPath,
|
|
60
|
+
];
|
|
61
|
+
// Sprint 8: Generate sourcemap if requested
|
|
62
|
+
if (opts.sourcemap) {
|
|
63
|
+
args.push('--sourcemap-output', bundlePath + '.map');
|
|
64
|
+
}
|
|
65
|
+
console.log(` Running: npx ${args.join(' ')}`);
|
|
66
|
+
const result = childProcess.spawnSync('npx', args, {
|
|
67
|
+
stdio: 'inherit',
|
|
68
|
+
shell: true,
|
|
69
|
+
timeout: 300000, // 5 minutes
|
|
70
|
+
});
|
|
71
|
+
if (result.status !== 0) {
|
|
72
|
+
throw new Error(`react-native bundle failed with exit code ${result.status}`);
|
|
73
|
+
}
|
|
74
|
+
if (!fs.existsSync(bundlePath)) {
|
|
75
|
+
throw new Error(`Bundle file not found at ${bundlePath}`);
|
|
76
|
+
}
|
|
77
|
+
// Hermes bytecode compilation (opt-in)
|
|
78
|
+
if (opts.hermes) {
|
|
79
|
+
console.log(' Compiling to Hermes bytecode…');
|
|
80
|
+
const hbcPath = bundlePath; // overwrite in-place — same extension
|
|
81
|
+
const hermescResult = childProcess.spawnSync('npx', ['hermesc', '-emit-binary', '-out', hbcPath, bundlePath], { stdio: 'inherit', shell: true, timeout: 120000 });
|
|
82
|
+
if (hermescResult.status !== 0) {
|
|
83
|
+
console.warn(` ⚠️ hermesc failed (exit ${hermescResult.status}) — shipping plain JS bundle`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.log(' ✅ Hermes bytecode compiled');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(' ℹ️ Shipping plain JS (no hermesc). Use --hermes for bytecode compilation.');
|
|
91
|
+
}
|
|
92
|
+
return { bundlePath, assetsPath };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/utils/bundle.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,kCA+DC;AAzGD,4DAA8C;AAC9C,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAgCzB;;;;;;GAMG;AACH,SAAgB,WAAW,CAAC,IAAmB;IAC7C,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAC1E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE/C,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,MAAM,IAAI,GAAG;QACX,cAAc,EAAE,QAAQ;QACxB,YAAY,EAAE,IAAI,CAAC,QAAQ;QAC3B,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACzB,cAAc,EAAE,IAAI,CAAC,SAAS;QAC9B,iBAAiB,EAAE,UAAU;QAC7B,eAAe,EAAE,UAAU;KAC5B,CAAC;IAEF,4CAA4C;IAC5C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,MAAM,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;QACjD,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,MAAO,EAAE,YAAY;KAC/B,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,6CAA6C,MAAM,CAAC,MAAM,EAAE,CAC7D,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,uCAAuC;IACvC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,sCAAsC;QAClE,MAAM,aAAa,GAAG,YAAY,CAAC,SAAS,CAC1C,KAAK,EACL,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,EACxD,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAO,EAAE,CACpD,CAAC;QAEF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CACV,8BAA8B,aAAa,CAAC,MAAM,8BAA8B,CACjF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CACT,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AACpC,CAAC"}
|