@rcrsr/rill-cli 0.16.0 → 0.17.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/dist/cli-run.js +47 -13
- package/dist/run/runner.d.ts +8 -8
- package/dist/run/runner.js +22 -68
- package/dist/run/types.d.ts +1 -1
- package/package.json +3 -3
package/dist/cli-run.js
CHANGED
|
@@ -26,7 +26,7 @@ Options:
|
|
|
26
26
|
--format <mode> Output format: human, json, compact (default: human)
|
|
27
27
|
--verbose Show full error details (default: false)
|
|
28
28
|
--max-stack-depth <n> Error stack frame limit (default: 10)
|
|
29
|
-
--create-bindings
|
|
29
|
+
--create-bindings [dir] Write bindings source to dir and exit (default: ./bindings)
|
|
30
30
|
--explain <code> Print error code documentation
|
|
31
31
|
--help Print this help message and exit
|
|
32
32
|
--version Print version and exit`.trimEnd();
|
|
@@ -38,17 +38,42 @@ const BASE_OPTIONS = {
|
|
|
38
38
|
format: { type: 'string' },
|
|
39
39
|
verbose: { type: 'boolean' },
|
|
40
40
|
'max-stack-depth': { type: 'string' },
|
|
41
|
-
'create-bindings': { type: 'boolean' },
|
|
42
41
|
help: { type: 'boolean' },
|
|
43
42
|
version: { type: 'boolean' },
|
|
44
43
|
explain: { type: 'string' },
|
|
45
44
|
};
|
|
46
45
|
// ============================================================
|
|
46
|
+
// CREATE-BINDINGS EXTRACTION
|
|
47
|
+
// ============================================================
|
|
48
|
+
/**
|
|
49
|
+
* Extract --create-bindings [dir] from argv before parseArgs.
|
|
50
|
+
* Handles the optional dir argument that parseArgs cannot natively support.
|
|
51
|
+
* Returns the filtered argv (with --create-bindings removed) and the resolved dir.
|
|
52
|
+
*/
|
|
53
|
+
function extractCreateBindings(argv) {
|
|
54
|
+
const idx = argv.indexOf('--create-bindings');
|
|
55
|
+
if (idx === -1) {
|
|
56
|
+
return { filteredArgv: argv, createBindings: undefined };
|
|
57
|
+
}
|
|
58
|
+
const next = argv[idx + 1];
|
|
59
|
+
if (next !== undefined && !next.startsWith('-')) {
|
|
60
|
+
return {
|
|
61
|
+
filteredArgv: [...argv.slice(0, idx), ...argv.slice(idx + 2)],
|
|
62
|
+
createBindings: next,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
filteredArgv: [...argv.slice(0, idx), ...argv.slice(idx + 1)],
|
|
67
|
+
createBindings: './bindings',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// ============================================================
|
|
47
71
|
// PARSE ARGS
|
|
48
72
|
// ============================================================
|
|
49
73
|
export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
74
|
+
const { filteredArgv, createBindings } = extractCreateBindings(argv);
|
|
50
75
|
const { values, positionals } = parseArgs({
|
|
51
|
-
args:
|
|
76
|
+
args: filteredArgv,
|
|
52
77
|
options: BASE_OPTIONS,
|
|
53
78
|
allowPositionals: true,
|
|
54
79
|
strict: false,
|
|
@@ -77,7 +102,7 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
|
77
102
|
verbose: values['verbose'] === true,
|
|
78
103
|
maxStackDepth,
|
|
79
104
|
explain: values['explain'],
|
|
80
|
-
createBindings
|
|
105
|
+
createBindings,
|
|
81
106
|
};
|
|
82
107
|
}
|
|
83
108
|
// ============================================================
|
|
@@ -96,8 +121,9 @@ function extractHandlerArgs(argv, params) {
|
|
|
96
121
|
type: param.type === 'bool' ? 'boolean' : 'string',
|
|
97
122
|
};
|
|
98
123
|
}
|
|
124
|
+
const { filteredArgv } = extractCreateBindings(argv);
|
|
99
125
|
const { values } = parseArgs({
|
|
100
|
-
args:
|
|
126
|
+
args: filteredArgv,
|
|
101
127
|
options: handlerOptions,
|
|
102
128
|
allowPositionals: true,
|
|
103
129
|
strict: false,
|
|
@@ -165,14 +191,20 @@ export async function main() {
|
|
|
165
191
|
throw err;
|
|
166
192
|
}
|
|
167
193
|
// Create bindings and exit early if --create-bindings was set
|
|
168
|
-
if (opts.createBindings
|
|
169
|
-
const
|
|
170
|
-
mkdirSync(
|
|
171
|
-
writeFileSync(
|
|
194
|
+
if (opts.createBindings !== undefined) {
|
|
195
|
+
const bindingsDir = resolve(dirname(configPath), opts.createBindings);
|
|
196
|
+
mkdirSync(bindingsDir, { recursive: true });
|
|
197
|
+
writeFileSync(resolve(bindingsDir, 'ext.rill'), project.extensionBindings + '\n');
|
|
172
198
|
if (project.config.context !== undefined) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
199
|
+
writeFileSync(resolve(bindingsDir, 'context.rill'), project.contextBindings + '\n');
|
|
200
|
+
}
|
|
201
|
+
for (const dispose of project.disposes) {
|
|
202
|
+
try {
|
|
203
|
+
await dispose();
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Ignore dispose errors during cleanup
|
|
207
|
+
}
|
|
176
208
|
}
|
|
177
209
|
process.exit(0);
|
|
178
210
|
}
|
|
@@ -272,7 +304,9 @@ export async function main() {
|
|
|
272
304
|
...opts,
|
|
273
305
|
scriptPath,
|
|
274
306
|
};
|
|
275
|
-
const runResult = await runScript(runOpts, project.config, project.extTree,
|
|
307
|
+
const runResult = await runScript(runOpts, project.config, project.extTree, [
|
|
308
|
+
...project.disposes,
|
|
309
|
+
]);
|
|
276
310
|
if (runResult.output !== undefined) {
|
|
277
311
|
process.stdout.write(runResult.output + '\n');
|
|
278
312
|
}
|
package/dist/run/runner.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Script runner for rill-run.
|
|
3
3
|
* Builds runtime options, executes rill scripts, and maps results to exit codes.
|
|
4
4
|
*/
|
|
5
|
-
import { type SchemeResolver } from '@rcrsr/rill';
|
|
6
|
-
import type {
|
|
5
|
+
import { type RillValue, type SchemeResolver } from '@rcrsr/rill';
|
|
6
|
+
import type { RillConfigFile } from '@rcrsr/rill-config';
|
|
7
7
|
import type { RunCliOptions } from './types.js';
|
|
8
8
|
export interface RunResult {
|
|
9
9
|
readonly exitCode: number;
|
|
@@ -11,13 +11,13 @@ export interface RunResult {
|
|
|
11
11
|
readonly errorOutput?: string | undefined;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Build a custom module scheme resolver.
|
|
15
|
-
*
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
14
|
+
* Build a custom module scheme resolver using folder aliasing.
|
|
15
|
+
* Each config key maps to a directory. Dot-paths resolve to files within:
|
|
16
|
+
* - `module:alias.sub.path` → `{dir}/sub/path.rill`
|
|
17
|
+
* - `module:alias` → `{dir}/index.rill`
|
|
18
18
|
*/
|
|
19
|
-
export declare function buildModuleResolver(
|
|
19
|
+
export declare function buildModuleResolver(modulesConfig: Record<string, string>, configDir: string): SchemeResolver;
|
|
20
20
|
/**
|
|
21
21
|
* Run a rill script file with the given extension tree and config.
|
|
22
22
|
*/
|
|
23
|
-
export declare function runScript(opts: RunCliOptions, config: RillConfigFile, extTree:
|
|
23
|
+
export declare function runScript(opts: RunCliOptions, config: RillConfigFile, extTree: Record<string, RillValue>, disposes: Array<() => void | Promise<void>>): Promise<RunResult>;
|
package/dist/run/runner.js
CHANGED
|
@@ -6,78 +6,33 @@ import { readFileSync } from 'node:fs';
|
|
|
6
6
|
import { dirname, resolve } from 'node:path';
|
|
7
7
|
import { parse, execute, createRuntimeContext, extResolver, moduleResolver, toNative, isTuple, } from '@rcrsr/rill';
|
|
8
8
|
import { ParseError, RillError, formatRillError, formatRillErrorJson, } from '@rcrsr/rill';
|
|
9
|
-
import { buildExtensionBindings, isLeafFunction } from '@rcrsr/rill-config';
|
|
10
|
-
// ============================================================
|
|
11
|
-
// TREE CONVERSION
|
|
12
|
-
// ============================================================
|
|
13
|
-
function convertTreeToRillValues(tree) {
|
|
14
|
-
const result = {};
|
|
15
|
-
for (const [key, value] of Object.entries(tree)) {
|
|
16
|
-
if (typeof value === 'object' &&
|
|
17
|
-
value !== null &&
|
|
18
|
-
'fn' in value &&
|
|
19
|
-
typeof value.fn === 'function' &&
|
|
20
|
-
'params' in value) {
|
|
21
|
-
const rillFn = value;
|
|
22
|
-
result[key] = {
|
|
23
|
-
__type: 'callable',
|
|
24
|
-
kind: 'application',
|
|
25
|
-
isProperty: false,
|
|
26
|
-
fn: rillFn.fn,
|
|
27
|
-
params: rillFn.params,
|
|
28
|
-
returnType: rillFn.returnType,
|
|
29
|
-
annotations: rillFn.annotations ?? {},
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
result[key] = convertTreeToRillValues(value);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
9
|
// ============================================================
|
|
39
10
|
// MODULE RESOLVER
|
|
40
11
|
// ============================================================
|
|
41
12
|
/**
|
|
42
|
-
* Build a custom module scheme resolver.
|
|
43
|
-
*
|
|
44
|
-
* -
|
|
45
|
-
* -
|
|
13
|
+
* Build a custom module scheme resolver using folder aliasing.
|
|
14
|
+
* Each config key maps to a directory. Dot-paths resolve to files within:
|
|
15
|
+
* - `module:alias.sub.path` → `{dir}/sub/path.rill`
|
|
16
|
+
* - `module:alias` → `{dir}/index.rill`
|
|
46
17
|
*/
|
|
47
|
-
export function buildModuleResolver(
|
|
48
|
-
const
|
|
18
|
+
export function buildModuleResolver(modulesConfig, configDir) {
|
|
19
|
+
const moduleDirs = {};
|
|
49
20
|
for (const [id, value] of Object.entries(modulesConfig)) {
|
|
50
|
-
|
|
51
|
-
moduleConfig[id] = resolve(configDir, value);
|
|
52
|
-
}
|
|
21
|
+
moduleDirs[id] = resolve(configDir, value);
|
|
53
22
|
}
|
|
54
23
|
const resolver = (resource) => {
|
|
55
|
-
|
|
56
|
-
|
|
24
|
+
const dotIndex = resource.indexOf('.');
|
|
25
|
+
const alias = dotIndex === -1 ? resource : resource.slice(0, dotIndex);
|
|
26
|
+
const dirPath = moduleDirs[alias];
|
|
27
|
+
if (dirPath === undefined) {
|
|
28
|
+
return moduleResolver(resource, {});
|
|
57
29
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const child = node[segment];
|
|
65
|
-
if (child === undefined) {
|
|
66
|
-
fullyResolved = false;
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
if (isLeafFunction(child)) {
|
|
70
|
-
fullyResolved = false;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
node = child;
|
|
74
|
-
}
|
|
75
|
-
if (fullyResolved && node !== extTree) {
|
|
76
|
-
const subtreeSource = buildExtensionBindings(node, suffix);
|
|
77
|
-
return { kind: 'source', text: subtreeSource };
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return moduleResolver(resource, moduleConfig);
|
|
30
|
+
const subPath = dotIndex === -1 ? '' : resource.slice(dotIndex + 1);
|
|
31
|
+
const relPath = subPath.length > 0
|
|
32
|
+
? subPath.replaceAll('.', '/') + '.rill'
|
|
33
|
+
: 'index.rill';
|
|
34
|
+
const filePath = resolve(dirPath, relPath);
|
|
35
|
+
return moduleResolver(resource, { [resource]: filePath });
|
|
81
36
|
};
|
|
82
37
|
return resolver;
|
|
83
38
|
}
|
|
@@ -120,7 +75,7 @@ function formatOutput(value, format) {
|
|
|
120
75
|
/**
|
|
121
76
|
* Run a rill script file with the given extension tree and config.
|
|
122
77
|
*/
|
|
123
|
-
export async function runScript(opts, config, extTree,
|
|
78
|
+
export async function runScript(opts, config, extTree, disposes) {
|
|
124
79
|
if (!opts.scriptPath) {
|
|
125
80
|
return { exitCode: 1, errorOutput: 'no script path provided' };
|
|
126
81
|
}
|
|
@@ -132,10 +87,9 @@ export async function runScript(opts, config, extTree, bindingsSrc, disposes) {
|
|
|
132
87
|
const message = err instanceof Error ? err.message : String(err);
|
|
133
88
|
return { exitCode: 1, errorOutput: message };
|
|
134
89
|
}
|
|
135
|
-
const extConfig = convertTreeToRillValues(extTree);
|
|
136
90
|
const modulesConfig = config.modules ?? {};
|
|
137
91
|
const configDir = dirname(resolve(opts.config));
|
|
138
|
-
const customModuleResolver = buildModuleResolver(
|
|
92
|
+
const customModuleResolver = buildModuleResolver(modulesConfig, configDir);
|
|
139
93
|
const runtimeOptions = {
|
|
140
94
|
resolvers: {
|
|
141
95
|
ext: extResolver,
|
|
@@ -143,7 +97,7 @@ export async function runScript(opts, config, extTree, bindingsSrc, disposes) {
|
|
|
143
97
|
},
|
|
144
98
|
configurations: {
|
|
145
99
|
resolvers: {
|
|
146
|
-
ext:
|
|
100
|
+
ext: extTree,
|
|
147
101
|
},
|
|
148
102
|
},
|
|
149
103
|
parseSource: parse,
|
|
@@ -196,7 +150,7 @@ export async function runScript(opts, config, extTree, bindingsSrc, disposes) {
|
|
|
196
150
|
verbose: opts.verbose,
|
|
197
151
|
maxStackDepth: opts.maxStackDepth,
|
|
198
152
|
filePath: opts.scriptPath,
|
|
199
|
-
sources: { script: source
|
|
153
|
+
sources: { script: source },
|
|
200
154
|
});
|
|
201
155
|
return { exitCode: 1, errorOutput: formatted };
|
|
202
156
|
}
|
package/dist/run/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rcrsr/rill-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "CLI tools for the rill scripting language",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andre Bremer",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"dotenv": "^16.0.0",
|
|
23
23
|
"yaml": "^2.8.2",
|
|
24
|
-
"@rcrsr/rill
|
|
25
|
-
"@rcrsr/rill": "^0.
|
|
24
|
+
"@rcrsr/rill": "^0.17.0",
|
|
25
|
+
"@rcrsr/rill-config": "^0.17.0"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist"
|