@basis-theory-labs/cli 2.0.0 → 3.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.
- package/README.md +174 -36
- package/dist/base.js +22 -1
- package/dist/commands/proxies/create.d.ts +17 -1
- package/dist/commands/proxies/create.js +84 -8
- package/dist/commands/proxies/update.d.ts +17 -1
- package/dist/commands/proxies/update.js +66 -6
- package/dist/commands/reactors/create.d.ts +11 -1
- package/dist/commands/reactors/create.js +70 -8
- package/dist/commands/reactors/update.d.ts +11 -1
- package/dist/commands/reactors/update.js +45 -5
- package/dist/proxies/management.d.ts +2 -1
- package/dist/proxies/management.js +9 -3
- package/dist/proxies/runtime.d.ts +5 -0
- package/dist/proxies/runtime.js +66 -0
- package/dist/proxies/utils.d.ts +23 -2
- package/dist/proxies/utils.js +78 -7
- package/dist/reactors/management.d.ts +2 -1
- package/dist/reactors/management.js +9 -3
- package/dist/reactors/runtime.d.ts +3 -0
- package/dist/reactors/runtime.js +27 -0
- package/dist/reactors/utils.d.ts +13 -2
- package/dist/reactors/utils.js +4 -1
- package/dist/runtime/flags.d.ts +10 -0
- package/dist/runtime/flags.js +37 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.js +21 -0
- package/dist/runtime/state.d.ts +6 -0
- package/dist/runtime/state.js +105 -0
- package/dist/runtime/utils.d.ts +39 -0
- package/dist/runtime/utils.js +171 -0
- package/dist/utils.d.ts +7 -1
- package/dist/utils.js +41 -1
- package/oclif.manifest.json +351 -10
- package/package.json +2 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateReactorApplicationId = exports.validateReactorRuntimeFlags = void 0;
|
|
4
|
+
const runtime_1 = require("../runtime");
|
|
5
|
+
const validateReactorRuntimeFlags = (flags, image) => {
|
|
6
|
+
const setFlags = [];
|
|
7
|
+
for (const flag of runtime_1.CONFIGURABLE_RUNTIME_FLAGS) {
|
|
8
|
+
const value = flags[flag];
|
|
9
|
+
const isSet = value !== undefined &&
|
|
10
|
+
value !== false &&
|
|
11
|
+
!(Array.isArray(value) && value.length === 0);
|
|
12
|
+
if (isSet) {
|
|
13
|
+
setFlags.push(flag);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (setFlags.length && (0, runtime_1.isLegacyRuntimeImage)(image)) {
|
|
17
|
+
const flagNames = setFlags.map((f) => `--${f}`).join(', ');
|
|
18
|
+
throw new Error(`Configurable runtime flags (${flagNames}) require --image ${runtime_1.CONFIGURABLE_RUNTIME_IMAGES.join(' | ')}`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
exports.validateReactorRuntimeFlags = validateReactorRuntimeFlags;
|
|
22
|
+
const validateReactorApplicationId = (applicationId, image) => {
|
|
23
|
+
if (applicationId && !(0, runtime_1.isLegacyRuntimeImage)(image)) {
|
|
24
|
+
throw new Error(`--application-id is not allowed with configurable runtimes (${runtime_1.CONFIGURABLE_RUNTIME_IMAGES.join(' | ')}). Use --permissions to grant specific access instead.`);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.validateReactorApplicationId = validateReactorApplicationId;
|
package/dist/reactors/utils.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { BasisTheory } from '@basis-theory/node-sdk';
|
|
2
2
|
declare const REACTOR_FLAGS: {
|
|
3
|
+
image: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
4
|
+
'package-json': import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
5
|
+
timeout: import("@oclif/core/lib/interfaces/parser").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
6
|
+
'warm-concurrency': import("@oclif/core/lib/interfaces/parser").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
resources: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
permissions: import("@oclif/core/lib/interfaces/parser").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
9
|
+
async: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
3
10
|
name: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
4
11
|
configuration: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
5
12
|
'application-id': import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
@@ -18,9 +25,13 @@ interface ReactorFlagProps {
|
|
|
18
25
|
* Path to .env file
|
|
19
26
|
*/
|
|
20
27
|
configuration?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Runtime configuration
|
|
30
|
+
*/
|
|
31
|
+
runtime?: BasisTheory.Runtime;
|
|
21
32
|
}
|
|
22
|
-
type CreateReactor = ReactorFlagProps & Omit<BasisTheory.CreateReactorRequest, 'application' | 'configuration'>;
|
|
23
|
-
type PatchReactor = ReactorFlagProps & Omit<BasisTheory.PatchReactorRequest, 'application' | 'configuration'>;
|
|
33
|
+
type CreateReactor = ReactorFlagProps & Omit<BasisTheory.CreateReactorRequest, 'application' | 'configuration' | 'runtime'>;
|
|
34
|
+
type PatchReactor = ReactorFlagProps & Omit<BasisTheory.PatchReactorRequest, 'application' | 'configuration' | 'runtime'>;
|
|
24
35
|
declare function createModelFromFlags(payload: CreateReactor): BasisTheory.CreateReactorRequest;
|
|
25
36
|
declare function createModelFromFlags(payload: PatchReactor): BasisTheory.PatchReactorRequest;
|
|
26
37
|
export { REACTOR_FLAGS, createModelFromFlags };
|
package/dist/reactors/utils.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.createModelFromFlags = exports.REACTOR_FLAGS = void 0;
|
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
5
|
const dotenv_1 = require("dotenv");
|
|
6
6
|
const files_1 = require("../files");
|
|
7
|
+
const runtime_1 = require("../runtime");
|
|
7
8
|
const REACTOR_FLAGS = {
|
|
8
9
|
name: core_1.Flags.string({
|
|
9
10
|
char: 'n',
|
|
@@ -21,10 +22,11 @@ const REACTOR_FLAGS = {
|
|
|
21
22
|
char: 'r',
|
|
22
23
|
description: 'path to JavaScript file containing the Reactor code',
|
|
23
24
|
}),
|
|
25
|
+
...runtime_1.RUNTIME_FLAGS,
|
|
24
26
|
};
|
|
25
27
|
exports.REACTOR_FLAGS = REACTOR_FLAGS;
|
|
26
28
|
// eslint-disable-next-line get-off-my-lawn/prefer-arrow-functions
|
|
27
|
-
function createModelFromFlags({ name, applicationId, code, configuration, }) {
|
|
29
|
+
function createModelFromFlags({ name, applicationId, code, configuration, runtime, }) {
|
|
28
30
|
return {
|
|
29
31
|
name,
|
|
30
32
|
code: code ? (0, files_1.readFileContents)(code) : undefined,
|
|
@@ -32,6 +34,7 @@ function createModelFromFlags({ name, applicationId, code, configuration, }) {
|
|
|
32
34
|
configuration: configuration
|
|
33
35
|
? (0, dotenv_1.parse)((0, files_1.readFileContents)(configuration))
|
|
34
36
|
: undefined,
|
|
37
|
+
runtime,
|
|
35
38
|
};
|
|
36
39
|
}
|
|
37
40
|
exports.createModelFromFlags = createModelFromFlags;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
declare const RUNTIME_FLAGS: {
|
|
2
|
+
image: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
3
|
+
'package-json': import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
4
|
+
timeout: import("@oclif/core/lib/interfaces/parser").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
5
|
+
'warm-concurrency': import("@oclif/core/lib/interfaces/parser").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
6
|
+
resources: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
permissions: import("@oclif/core/lib/interfaces/parser").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
|
+
async: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
|
|
9
|
+
};
|
|
10
|
+
export { RUNTIME_FLAGS };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RUNTIME_FLAGS = void 0;
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const RUNTIME_FLAGS = {
|
|
7
|
+
image: core_1.Flags.string({
|
|
8
|
+
description: `runtime image (${utils_1.VALID_RUNTIME_IMAGES.join('|')})`,
|
|
9
|
+
options: [...utils_1.VALID_RUNTIME_IMAGES],
|
|
10
|
+
}),
|
|
11
|
+
'package-json': core_1.Flags.file({
|
|
12
|
+
description: 'path to runtime package.json JSON file (top-level dependencies required; supports resolutions or overrides fallback; pinned versions required) (node22 only)',
|
|
13
|
+
}),
|
|
14
|
+
timeout: core_1.Flags.integer({
|
|
15
|
+
description: 'timeout in seconds, 1-30 (node22 only, default: 10)',
|
|
16
|
+
min: 1,
|
|
17
|
+
max: 30,
|
|
18
|
+
}),
|
|
19
|
+
'warm-concurrency': core_1.Flags.integer({
|
|
20
|
+
description: 'number of warm instances, 0-1 (node22 only, default: 0)',
|
|
21
|
+
min: 0,
|
|
22
|
+
max: 1,
|
|
23
|
+
}),
|
|
24
|
+
resources: core_1.Flags.string({
|
|
25
|
+
description: 'resource tier (node22 only, default: standard)',
|
|
26
|
+
options: ['standard', 'large', 'xlarge'],
|
|
27
|
+
}),
|
|
28
|
+
permissions: core_1.Flags.string({
|
|
29
|
+
description: 'permission to grant, repeatable (node22 only)',
|
|
30
|
+
multiple: true,
|
|
31
|
+
}),
|
|
32
|
+
async: core_1.Flags.boolean({
|
|
33
|
+
description: 'do not wait for resource to be ready (node22 only)',
|
|
34
|
+
default: false,
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
exports.RUNTIME_FLAGS = RUNTIME_FLAGS;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { LEGACY_RUNTIME_IMAGE, CONFIGURABLE_RUNTIME_IMAGES, VALID_RUNTIME_IMAGES, CONFIGURABLE_RUNTIME_FLAGS, isLegacyRuntimeImage, validateRuntimeImage, parseRuntimePackageJsonFile, buildRuntime, promptRuntimeOptions, promptRuntimeImage, type ConfigurableRuntimeOptions, type RuntimeFlagProps, type RuntimeFlags, } from './utils';
|
|
2
|
+
export { RUNTIME_FLAGS } from './flags';
|
|
3
|
+
export { waitForResourceState, needsPolling, POLL_INTERVAL, POLL_TIMEOUT, } from './state';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POLL_TIMEOUT = exports.POLL_INTERVAL = exports.needsPolling = exports.waitForResourceState = exports.RUNTIME_FLAGS = exports.promptRuntimeImage = exports.promptRuntimeOptions = exports.buildRuntime = exports.parseRuntimePackageJsonFile = exports.validateRuntimeImage = exports.isLegacyRuntimeImage = exports.CONFIGURABLE_RUNTIME_FLAGS = exports.VALID_RUNTIME_IMAGES = exports.CONFIGURABLE_RUNTIME_IMAGES = exports.LEGACY_RUNTIME_IMAGE = void 0;
|
|
4
|
+
var utils_1 = require("./utils");
|
|
5
|
+
Object.defineProperty(exports, "LEGACY_RUNTIME_IMAGE", { enumerable: true, get: function () { return utils_1.LEGACY_RUNTIME_IMAGE; } });
|
|
6
|
+
Object.defineProperty(exports, "CONFIGURABLE_RUNTIME_IMAGES", { enumerable: true, get: function () { return utils_1.CONFIGURABLE_RUNTIME_IMAGES; } });
|
|
7
|
+
Object.defineProperty(exports, "VALID_RUNTIME_IMAGES", { enumerable: true, get: function () { return utils_1.VALID_RUNTIME_IMAGES; } });
|
|
8
|
+
Object.defineProperty(exports, "CONFIGURABLE_RUNTIME_FLAGS", { enumerable: true, get: function () { return utils_1.CONFIGURABLE_RUNTIME_FLAGS; } });
|
|
9
|
+
Object.defineProperty(exports, "isLegacyRuntimeImage", { enumerable: true, get: function () { return utils_1.isLegacyRuntimeImage; } });
|
|
10
|
+
Object.defineProperty(exports, "validateRuntimeImage", { enumerable: true, get: function () { return utils_1.validateRuntimeImage; } });
|
|
11
|
+
Object.defineProperty(exports, "parseRuntimePackageJsonFile", { enumerable: true, get: function () { return utils_1.parseRuntimePackageJsonFile; } });
|
|
12
|
+
Object.defineProperty(exports, "buildRuntime", { enumerable: true, get: function () { return utils_1.buildRuntime; } });
|
|
13
|
+
Object.defineProperty(exports, "promptRuntimeOptions", { enumerable: true, get: function () { return utils_1.promptRuntimeOptions; } });
|
|
14
|
+
Object.defineProperty(exports, "promptRuntimeImage", { enumerable: true, get: function () { return utils_1.promptRuntimeImage; } });
|
|
15
|
+
var flags_1 = require("./flags");
|
|
16
|
+
Object.defineProperty(exports, "RUNTIME_FLAGS", { enumerable: true, get: function () { return flags_1.RUNTIME_FLAGS; } });
|
|
17
|
+
var state_1 = require("./state");
|
|
18
|
+
Object.defineProperty(exports, "waitForResourceState", { enumerable: true, get: function () { return state_1.waitForResourceState; } });
|
|
19
|
+
Object.defineProperty(exports, "needsPolling", { enumerable: true, get: function () { return state_1.needsPolling; } });
|
|
20
|
+
Object.defineProperty(exports, "POLL_INTERVAL", { enumerable: true, get: function () { return state_1.POLL_INTERVAL; } });
|
|
21
|
+
Object.defineProperty(exports, "POLL_TIMEOUT", { enumerable: true, get: function () { return state_1.POLL_TIMEOUT; } });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BasisTheoryClient } from '@basis-theory/node-sdk';
|
|
2
|
+
declare const POLL_INTERVAL = 2000;
|
|
3
|
+
declare const POLL_TIMEOUT = 600000;
|
|
4
|
+
declare const needsPolling: (state: string | undefined) => boolean;
|
|
5
|
+
declare const waitForResourceState: (bt: BasisTheoryClient, resourceType: 'reactor' | 'proxy', id: string, initialState?: string) => Promise<void>;
|
|
6
|
+
export { waitForResourceState, needsPolling, POLL_INTERVAL, POLL_TIMEOUT };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POLL_TIMEOUT = exports.POLL_INTERVAL = exports.needsPolling = exports.waitForResourceState = void 0;
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const POLL_INTERVAL = 2000; // 2 seconds
|
|
6
|
+
exports.POLL_INTERVAL = POLL_INTERVAL;
|
|
7
|
+
const POLL_TIMEOUT = 600000; // 10 minutes
|
|
8
|
+
exports.POLL_TIMEOUT = POLL_TIMEOUT;
|
|
9
|
+
const formatErrorDetails = (value) => {
|
|
10
|
+
if (typeof value === 'string') {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.stringify(JSON.parse(value), undefined, 2);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === 'object' && Boolean(value)) {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.stringify(value, undefined, 2);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return String(value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return String(value);
|
|
27
|
+
};
|
|
28
|
+
const formatErrorMessage = (resource, resourceType) => {
|
|
29
|
+
const { state, requested } = resource;
|
|
30
|
+
const resourceName = resourceType === 'reactor' ? 'Reactor' : 'Proxy';
|
|
31
|
+
const parts = [`${resourceName} reached ${state} state`];
|
|
32
|
+
if (requested === null || requested === void 0 ? void 0 : requested.errorCode) {
|
|
33
|
+
parts.push(`errorCode: ${requested.errorCode}`);
|
|
34
|
+
}
|
|
35
|
+
if (requested === null || requested === void 0 ? void 0 : requested.errorMessage) {
|
|
36
|
+
parts.push(`errorMessage: ${requested.errorMessage}`);
|
|
37
|
+
}
|
|
38
|
+
if (requested === null || requested === void 0 ? void 0 : requested.errorDetails) {
|
|
39
|
+
parts.push(`errorDetails: ${formatErrorDetails(requested.errorDetails)}`);
|
|
40
|
+
}
|
|
41
|
+
return parts.join('\n');
|
|
42
|
+
};
|
|
43
|
+
const needsPolling = (state) => state === 'creating' || state === 'updating';
|
|
44
|
+
exports.needsPolling = needsPolling;
|
|
45
|
+
const formatElapsedTime = (startTime) => {
|
|
46
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
47
|
+
const minutes = Math.floor(elapsed / 60);
|
|
48
|
+
const seconds = elapsed % 60;
|
|
49
|
+
if (minutes > 0) {
|
|
50
|
+
return `${minutes}m ${seconds}s`;
|
|
51
|
+
}
|
|
52
|
+
return `${seconds}s`;
|
|
53
|
+
};
|
|
54
|
+
const createTimer = (startTime, getState) => setInterval(() => {
|
|
55
|
+
const state = getState();
|
|
56
|
+
if (state) {
|
|
57
|
+
core_1.ux.action.status = `${state} (${formatElapsedTime(startTime)})`;
|
|
58
|
+
}
|
|
59
|
+
}, 1000);
|
|
60
|
+
const waitForResourceState = async (bt, resourceType, id, initialState) => {
|
|
61
|
+
// If initial state is provided and doesn't need polling, return immediately
|
|
62
|
+
if (initialState !== undefined && !needsPolling(initialState)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const deadline = Date.now() + POLL_TIMEOUT;
|
|
66
|
+
const startTime = Date.now();
|
|
67
|
+
let currentState;
|
|
68
|
+
const timer = createTimer(startTime, () => currentState);
|
|
69
|
+
core_1.ux.action.start('Status');
|
|
70
|
+
/* eslint-disable no-await-in-loop */
|
|
71
|
+
try {
|
|
72
|
+
while (Date.now() < deadline) {
|
|
73
|
+
let resource;
|
|
74
|
+
try {
|
|
75
|
+
resource = await (resourceType === 'reactor'
|
|
76
|
+
? bt.reactors.get(id)
|
|
77
|
+
: bt.proxies.get(id));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
core_1.ux.action.stop(`error (${formatElapsedTime(startTime)})`);
|
|
81
|
+
throw new Error(`Failed to check ${resourceType} state: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
currentState = resource.state;
|
|
84
|
+
core_1.ux.action.status = `${currentState} (${formatElapsedTime(startTime)})`;
|
|
85
|
+
if (currentState === 'active') {
|
|
86
|
+
core_1.ux.action.stop(`ready (${formatElapsedTime(startTime)})`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (currentState === 'failed' || currentState === 'outdated') {
|
|
90
|
+
core_1.ux.action.stop(`failed (${formatElapsedTime(startTime)})`);
|
|
91
|
+
throw new Error(formatErrorMessage(resource, resourceType));
|
|
92
|
+
}
|
|
93
|
+
await new Promise((resolve) => {
|
|
94
|
+
setTimeout(resolve, POLL_INTERVAL);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
core_1.ux.action.stop(`timeout (${formatElapsedTime(startTime)})`);
|
|
98
|
+
throw new Error(`Timeout waiting for ${resourceType} to reach final state`);
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
clearInterval(timer);
|
|
102
|
+
}
|
|
103
|
+
/* eslint-enable no-await-in-loop */
|
|
104
|
+
};
|
|
105
|
+
exports.waitForResourceState = waitForResourceState;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { BasisTheory } from '@basis-theory/node-sdk';
|
|
2
|
+
declare const LEGACY_RUNTIME_IMAGE = "node-bt";
|
|
3
|
+
declare const CONFIGURABLE_RUNTIME_IMAGES: readonly ["node22"];
|
|
4
|
+
declare const VALID_RUNTIME_IMAGES: readonly ["node-bt", "node22"];
|
|
5
|
+
declare const isLegacyRuntimeImage: (image: string | undefined) => boolean;
|
|
6
|
+
declare const validateRuntimeImage: (image: string | undefined) => void;
|
|
7
|
+
declare const CONFIGURABLE_RUNTIME_FLAGS: readonly ["timeout", "resources", "warm-concurrency", "permissions", "package-json"];
|
|
8
|
+
interface RuntimeFlagProps {
|
|
9
|
+
image?: string;
|
|
10
|
+
packageJson?: string;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
warmConcurrency?: number;
|
|
13
|
+
resources?: string;
|
|
14
|
+
permissions?: string[];
|
|
15
|
+
}
|
|
16
|
+
interface RuntimeFlags {
|
|
17
|
+
image?: string;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
'warm-concurrency'?: number;
|
|
20
|
+
resources?: string;
|
|
21
|
+
'package-json'?: string;
|
|
22
|
+
permissions?: string[];
|
|
23
|
+
}
|
|
24
|
+
interface ConfigurableRuntimeOptions {
|
|
25
|
+
timeout?: number;
|
|
26
|
+
warmConcurrency?: number;
|
|
27
|
+
resources?: string;
|
|
28
|
+
packageJson?: string;
|
|
29
|
+
permissions?: string[];
|
|
30
|
+
}
|
|
31
|
+
interface ParsedRuntimePackageFile {
|
|
32
|
+
dependencies: Record<string, string>;
|
|
33
|
+
resolutions?: Record<string, string>;
|
|
34
|
+
}
|
|
35
|
+
declare const parseRuntimePackageJsonFile: (packageJsonPath: string) => ParsedRuntimePackageFile;
|
|
36
|
+
declare const buildRuntime: (props: RuntimeFlagProps) => BasisTheory.Runtime | undefined;
|
|
37
|
+
declare const promptRuntimeOptions: (flags: RuntimeFlags, labelPrefix?: string) => Promise<ConfigurableRuntimeOptions>;
|
|
38
|
+
declare const promptRuntimeImage: (image: string | undefined, message?: string) => Promise<string>;
|
|
39
|
+
export { LEGACY_RUNTIME_IMAGE, CONFIGURABLE_RUNTIME_IMAGES, VALID_RUNTIME_IMAGES, CONFIGURABLE_RUNTIME_FLAGS, isLegacyRuntimeImage, validateRuntimeImage, parseRuntimePackageJsonFile, buildRuntime, promptRuntimeOptions, promptRuntimeImage, type RuntimeFlagProps, type RuntimeFlags, type ConfigurableRuntimeOptions, };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptRuntimeImage = exports.promptRuntimeOptions = exports.buildRuntime = exports.parseRuntimePackageJsonFile = exports.validateRuntimeImage = exports.isLegacyRuntimeImage = exports.CONFIGURABLE_RUNTIME_FLAGS = exports.VALID_RUNTIME_IMAGES = exports.CONFIGURABLE_RUNTIME_IMAGES = exports.LEGACY_RUNTIME_IMAGE = void 0;
|
|
4
|
+
const files_1 = require("../files");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const LEGACY_RUNTIME_IMAGE = 'node-bt';
|
|
7
|
+
exports.LEGACY_RUNTIME_IMAGE = LEGACY_RUNTIME_IMAGE;
|
|
8
|
+
const CONFIGURABLE_RUNTIME_IMAGES = ['node22'];
|
|
9
|
+
exports.CONFIGURABLE_RUNTIME_IMAGES = CONFIGURABLE_RUNTIME_IMAGES;
|
|
10
|
+
const VALID_RUNTIME_IMAGES = [
|
|
11
|
+
LEGACY_RUNTIME_IMAGE,
|
|
12
|
+
...CONFIGURABLE_RUNTIME_IMAGES,
|
|
13
|
+
];
|
|
14
|
+
exports.VALID_RUNTIME_IMAGES = VALID_RUNTIME_IMAGES;
|
|
15
|
+
const isLegacyRuntimeImage = (image) => image === undefined || image === LEGACY_RUNTIME_IMAGE;
|
|
16
|
+
exports.isLegacyRuntimeImage = isLegacyRuntimeImage;
|
|
17
|
+
const validateRuntimeImage = (image) => {
|
|
18
|
+
if (image === undefined) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!VALID_RUNTIME_IMAGES.includes(image)) {
|
|
22
|
+
throw new Error(`Invalid runtime image "${image}". Valid options: ${VALID_RUNTIME_IMAGES.join(', ')}`);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
exports.validateRuntimeImage = validateRuntimeImage;
|
|
26
|
+
const CONFIGURABLE_RUNTIME_FLAGS = [
|
|
27
|
+
'timeout',
|
|
28
|
+
'resources',
|
|
29
|
+
'warm-concurrency',
|
|
30
|
+
'permissions',
|
|
31
|
+
'package-json',
|
|
32
|
+
];
|
|
33
|
+
exports.CONFIGURABLE_RUNTIME_FLAGS = CONFIGURABLE_RUNTIME_FLAGS;
|
|
34
|
+
const isStringRecord = (value) => typeof value === 'object' &&
|
|
35
|
+
Boolean(value) &&
|
|
36
|
+
!Array.isArray(value) &&
|
|
37
|
+
Object.values(value).every((item) => typeof item === 'string');
|
|
38
|
+
const parseRuntimePackageJsonFile = (packageJsonPath) => {
|
|
39
|
+
let parsedFile;
|
|
40
|
+
try {
|
|
41
|
+
parsedFile = JSON.parse((0, files_1.readFileContents)(packageJsonPath));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new Error(`Failed to parse package.json file "${packageJsonPath}": ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
if (!parsedFile ||
|
|
47
|
+
typeof parsedFile !== 'object' ||
|
|
48
|
+
Array.isArray(parsedFile)) {
|
|
49
|
+
throw new Error(`Runtime package file "${packageJsonPath}" must include a top-level "dependencies" object.`);
|
|
50
|
+
}
|
|
51
|
+
const file = parsedFile;
|
|
52
|
+
const dependencies = file.dependencies;
|
|
53
|
+
if (!isStringRecord(dependencies)) {
|
|
54
|
+
throw new Error(`Runtime package file "${packageJsonPath}" has invalid "dependencies": expected an object of package names to pinned version strings.`);
|
|
55
|
+
}
|
|
56
|
+
let resolutions;
|
|
57
|
+
if (file.resolutions !== undefined) {
|
|
58
|
+
if (!isStringRecord(file.resolutions)) {
|
|
59
|
+
throw new Error(`Runtime package file "${packageJsonPath}" has invalid "resolutions": expected an object of package names to pinned version strings.`);
|
|
60
|
+
}
|
|
61
|
+
resolutions = file.resolutions;
|
|
62
|
+
}
|
|
63
|
+
else if (file.overrides !== undefined) {
|
|
64
|
+
if (!isStringRecord(file.overrides)) {
|
|
65
|
+
throw new Error(`Runtime package file "${packageJsonPath}" has unsupported "overrides" values for runtime resolutions; only string values are supported.`);
|
|
66
|
+
}
|
|
67
|
+
resolutions = file.overrides;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
dependencies,
|
|
71
|
+
resolutions,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
exports.parseRuntimePackageJsonFile = parseRuntimePackageJsonFile;
|
|
75
|
+
const buildRuntime = (props) => {
|
|
76
|
+
const { image, packageJson, timeout, warmConcurrency, resources, permissions, } = props;
|
|
77
|
+
if (!image &&
|
|
78
|
+
!packageJson &&
|
|
79
|
+
!timeout &&
|
|
80
|
+
!warmConcurrency &&
|
|
81
|
+
!resources &&
|
|
82
|
+
!(permissions === null || permissions === void 0 ? void 0 : permissions.length)) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
let parsedPackageFile;
|
|
86
|
+
if (packageJson) {
|
|
87
|
+
parsedPackageFile = parseRuntimePackageJsonFile(packageJson);
|
|
88
|
+
}
|
|
89
|
+
const runtime = {};
|
|
90
|
+
if (image) {
|
|
91
|
+
runtime.image = image;
|
|
92
|
+
}
|
|
93
|
+
if (parsedPackageFile) {
|
|
94
|
+
runtime.dependencies = parsedPackageFile.dependencies;
|
|
95
|
+
}
|
|
96
|
+
if (parsedPackageFile === null || parsedPackageFile === void 0 ? void 0 : parsedPackageFile.resolutions) {
|
|
97
|
+
runtime.resolutions = parsedPackageFile.resolutions;
|
|
98
|
+
}
|
|
99
|
+
if (timeout !== undefined) {
|
|
100
|
+
runtime.timeout = timeout;
|
|
101
|
+
}
|
|
102
|
+
if (warmConcurrency !== undefined) {
|
|
103
|
+
runtime.warmConcurrency = warmConcurrency;
|
|
104
|
+
}
|
|
105
|
+
if (resources) {
|
|
106
|
+
runtime.resources = resources;
|
|
107
|
+
}
|
|
108
|
+
if (permissions === null || permissions === void 0 ? void 0 : permissions.length) {
|
|
109
|
+
runtime.permissions = permissions;
|
|
110
|
+
}
|
|
111
|
+
return runtime;
|
|
112
|
+
};
|
|
113
|
+
exports.buildRuntime = buildRuntime;
|
|
114
|
+
const promptRuntimeOptions = async (flags, labelPrefix) => {
|
|
115
|
+
const prefix = labelPrefix ? `${labelPrefix}: ` : '';
|
|
116
|
+
const timeout = await (0, utils_1.promptIntegerIfUndefined)(flags.timeout, {
|
|
117
|
+
message: `${prefix}Timeout in seconds (1-30, press Enter for default: 10):`,
|
|
118
|
+
min: 1,
|
|
119
|
+
max: 30,
|
|
120
|
+
});
|
|
121
|
+
const warmConcurrency = await (0, utils_1.promptIntegerIfUndefined)(flags['warm-concurrency'], {
|
|
122
|
+
message: `${prefix}Warm concurrency (0-1, press Enter for default: 0):`,
|
|
123
|
+
min: 0,
|
|
124
|
+
max: 1,
|
|
125
|
+
});
|
|
126
|
+
const resources = await (0, utils_1.promptSelectIfUndefined)(flags.resources, {
|
|
127
|
+
message: `${prefix}Resource tier:`,
|
|
128
|
+
choices: [
|
|
129
|
+
{
|
|
130
|
+
value: 'standard',
|
|
131
|
+
name: 'standard (default)',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
value: 'large',
|
|
135
|
+
name: 'large',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
value: 'xlarge',
|
|
139
|
+
name: 'xlarge',
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
const packageJson = await (0, utils_1.promptStringIfUndefined)(flags['package-json'], {
|
|
144
|
+
message: `${prefix}(Optional) Runtime package.json file path (JSON format):`,
|
|
145
|
+
});
|
|
146
|
+
const permissions = await (0, utils_1.promptCommaSeparatedIfUndefined)(flags.permissions, {
|
|
147
|
+
message: `${prefix}(Optional) Permissions (comma-separated, e.g. token:read, token:create):`,
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
timeout,
|
|
151
|
+
warmConcurrency,
|
|
152
|
+
resources,
|
|
153
|
+
packageJson: packageJson || undefined,
|
|
154
|
+
permissions,
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
exports.promptRuntimeOptions = promptRuntimeOptions;
|
|
158
|
+
const promptRuntimeImage = (image, message = 'Which runtime do you want to use?') => (0, utils_1.promptSelectIfUndefined)(image, {
|
|
159
|
+
message,
|
|
160
|
+
choices: [
|
|
161
|
+
{
|
|
162
|
+
value: LEGACY_RUNTIME_IMAGE,
|
|
163
|
+
name: `${LEGACY_RUNTIME_IMAGE} (legacy)`,
|
|
164
|
+
},
|
|
165
|
+
...CONFIGURABLE_RUNTIME_IMAGES.map((runtime) => ({
|
|
166
|
+
value: runtime,
|
|
167
|
+
name: `${runtime} (configurable)`,
|
|
168
|
+
})),
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
exports.promptRuntimeImage = promptRuntimeImage;
|
package/dist/utils.d.ts
CHANGED
|
@@ -15,5 +15,11 @@ declare const promptSelectIfUndefined: (value: string | undefined, options: Para
|
|
|
15
15
|
declare const promptCheckboxIfUndefined: (value: string[] | undefined, options: Parameters<typeof checkbox>[0]) => Promise<string[]>;
|
|
16
16
|
declare const promptUrlIfUndefined: (value: URL | undefined, options: Parameters<typeof input>[0]) => Promise<URL>;
|
|
17
17
|
declare const promptBooleanIfUndefined: (value: boolean | undefined, options: Parameters<typeof confirm>[0]) => Promise<boolean>;
|
|
18
|
+
declare const promptIntegerIfUndefined: (value: number | undefined, options: {
|
|
19
|
+
message: string;
|
|
20
|
+
min?: number;
|
|
21
|
+
max?: number;
|
|
22
|
+
}) => Promise<number | undefined>;
|
|
23
|
+
declare const promptCommaSeparatedIfUndefined: (value: string[] | undefined, options: Parameters<typeof input>[0]) => Promise<string[] | undefined>;
|
|
18
24
|
declare const cleanUpOnExit: (action: () => unknown) => typeof process;
|
|
19
|
-
export { selectOrNavigate, promptStringIfUndefined, promptSelectIfUndefined, promptCheckboxIfUndefined, promptUrlIfUndefined, promptBooleanIfUndefined, cleanUpOnExit, PaginatedList, };
|
|
25
|
+
export { selectOrNavigate, promptStringIfUndefined, promptSelectIfUndefined, promptCheckboxIfUndefined, promptUrlIfUndefined, promptBooleanIfUndefined, promptIntegerIfUndefined, promptCommaSeparatedIfUndefined, cleanUpOnExit, PaginatedList, };
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cleanUpOnExit = exports.promptBooleanIfUndefined = exports.promptUrlIfUndefined = exports.promptCheckboxIfUndefined = exports.promptSelectIfUndefined = exports.promptStringIfUndefined = exports.selectOrNavigate = void 0;
|
|
3
|
+
exports.cleanUpOnExit = exports.promptCommaSeparatedIfUndefined = exports.promptIntegerIfUndefined = exports.promptBooleanIfUndefined = exports.promptUrlIfUndefined = exports.promptCheckboxIfUndefined = exports.promptSelectIfUndefined = exports.promptStringIfUndefined = exports.selectOrNavigate = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const checkbox_1 = tslib_1.__importDefault(require("@inquirer/checkbox"));
|
|
6
6
|
const confirm_1 = tslib_1.__importDefault(require("@inquirer/confirm"));
|
|
@@ -82,6 +82,46 @@ const promptBooleanIfUndefined = (value, options) => {
|
|
|
82
82
|
return (0, confirm_1.default)(options);
|
|
83
83
|
};
|
|
84
84
|
exports.promptBooleanIfUndefined = promptBooleanIfUndefined;
|
|
85
|
+
const promptIntegerIfUndefined = async (value, options) => {
|
|
86
|
+
if (value !== undefined) {
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
const result = await (0, input_1.default)({
|
|
90
|
+
message: options.message,
|
|
91
|
+
validate: (val) => {
|
|
92
|
+
if (!val.trim()) {
|
|
93
|
+
return true;
|
|
94
|
+
} // Allow empty for optional
|
|
95
|
+
const num = Number(val);
|
|
96
|
+
if (Number.isNaN(num) || !Number.isInteger(num)) {
|
|
97
|
+
return 'Please enter a valid integer';
|
|
98
|
+
}
|
|
99
|
+
if (options.min !== undefined && num < options.min) {
|
|
100
|
+
return `Value must be at least ${options.min}`;
|
|
101
|
+
}
|
|
102
|
+
if (options.max !== undefined && num > options.max) {
|
|
103
|
+
return `Value must be at most ${options.max}`;
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
return result.trim() ? Number(result) : undefined;
|
|
109
|
+
};
|
|
110
|
+
exports.promptIntegerIfUndefined = promptIntegerIfUndefined;
|
|
111
|
+
const promptCommaSeparatedIfUndefined = async (value, options) => {
|
|
112
|
+
if (value && value.length > 0) {
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
const result = await (0, input_1.default)(options);
|
|
116
|
+
if (!result.trim()) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
return result
|
|
120
|
+
.split(',')
|
|
121
|
+
.map((item) => item.trim())
|
|
122
|
+
.filter((item) => item.length > 0);
|
|
123
|
+
};
|
|
124
|
+
exports.promptCommaSeparatedIfUndefined = promptCommaSeparatedIfUndefined;
|
|
85
125
|
const cleanUpOnExit = (action) => process.on('SIGINT', async () => {
|
|
86
126
|
await action();
|
|
87
127
|
process.exit(1);
|