@ryanatkn/gro 0.176.0 → 0.177.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/args.d.ts +5 -5
- package/dist/args.d.ts.map +1 -1
- package/dist/build.task.d.ts.map +1 -1
- package/dist/build.task.js +2 -2
- package/dist/build_cache.d.ts +12 -12
- package/dist/build_cache.d.ts.map +1 -1
- package/dist/build_cache.js +4 -4
- package/dist/changelog.d.ts +2 -2
- package/dist/changelog.d.ts.map +1 -1
- package/dist/changelog.js +1 -1
- package/dist/changeset.task.d.ts.map +1 -1
- package/dist/changeset.task.js +9 -9
- package/dist/changeset_helpers.d.ts +4 -4
- package/dist/changeset_helpers.d.ts.map +1 -1
- package/dist/changeset_helpers.js +2 -2
- package/dist/check.task.d.ts.map +1 -1
- package/dist/check.task.js +3 -3
- package/dist/clean.task.js +2 -2
- package/dist/cli.d.ts +6 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/commit.task.js +2 -2
- package/dist/deploy.task.d.ts.map +1 -1
- package/dist/deploy.task.js +13 -13
- package/dist/dev.task.d.ts +2 -2
- package/dist/dev.task.d.ts.map +1 -1
- package/dist/disknode.d.ts +4 -4
- package/dist/disknode.d.ts.map +1 -1
- package/dist/esbuild_helpers.d.ts +2 -2
- package/dist/esbuild_helpers.d.ts.map +1 -1
- package/dist/esbuild_plugin_external_worker.d.ts +5 -5
- package/dist/esbuild_plugin_external_worker.d.ts.map +1 -1
- package/dist/esbuild_plugin_svelte.d.ts +4 -4
- package/dist/esbuild_plugin_svelte.d.ts.map +1 -1
- package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts +2 -2
- package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts.map +1 -1
- package/dist/esbuild_plugin_sveltekit_shim_app.d.ts +5 -5
- package/dist/esbuild_plugin_sveltekit_shim_app.d.ts.map +1 -1
- package/dist/esbuild_plugin_sveltekit_shim_env.d.ts +2 -2
- package/dist/esbuild_plugin_sveltekit_shim_env.d.ts.map +1 -1
- package/dist/filer.d.ts +15 -15
- package/dist/filer.d.ts.map +1 -1
- package/dist/filer.js +2 -2
- package/dist/format.task.d.ts.map +1 -1
- package/dist/format.task.js +2 -2
- package/dist/format_directory.d.ts +2 -2
- package/dist/format_directory.d.ts.map +1 -1
- package/dist/gen.d.ts +73 -73
- package/dist/gen.d.ts.map +1 -1
- package/dist/gen.js +1 -1
- package/dist/gen.task.d.ts.map +1 -1
- package/dist/gen.task.js +8 -8
- package/dist/gen_helpers.d.ts +4 -4
- package/dist/gen_helpers.d.ts.map +1 -1
- package/dist/gen_helpers.js +1 -1
- package/dist/github.d.ts +4 -4
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +3 -3
- package/dist/gro.config.default.d.ts +2 -2
- package/dist/gro.config.default.d.ts.map +1 -1
- package/dist/gro_config.d.ts +25 -25
- package/dist/gro_config.d.ts.map +1 -1
- package/dist/gro_config.js +2 -2
- package/dist/gro_helpers.d.ts +2 -2
- package/dist/gro_helpers.d.ts.map +1 -1
- package/dist/gro_plugin_gen.d.ts +3 -3
- package/dist/gro_plugin_gen.d.ts.map +1 -1
- package/dist/gro_plugin_gen.js +2 -2
- package/dist/gro_plugin_server.d.ts +7 -7
- package/dist/gro_plugin_server.d.ts.map +1 -1
- package/dist/gro_plugin_sveltekit_app.d.ts +10 -10
- package/dist/gro_plugin_sveltekit_app.d.ts.map +1 -1
- package/dist/gro_plugin_sveltekit_app.js +2 -2
- package/dist/gro_plugin_sveltekit_library.d.ts +4 -4
- package/dist/gro_plugin_sveltekit_library.d.ts.map +1 -1
- package/dist/gro_plugin_sveltekit_library.js +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/input_path.d.ts +30 -30
- package/dist/input_path.d.ts.map +1 -1
- package/dist/input_path.js +2 -2
- package/dist/invoke.js +1 -1
- package/dist/invoke_task.d.ts +3 -3
- package/dist/invoke_task.d.ts.map +1 -1
- package/dist/invoke_task.js +4 -4
- package/dist/lint.task.d.ts.map +1 -1
- package/dist/lint.task.js +2 -2
- package/dist/modules.d.ts +20 -20
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +2 -2
- package/dist/package_json.d.ts +16 -16
- package/dist/package_json.d.ts.map +1 -1
- package/dist/package_json.js +6 -6
- package/dist/parse_exports.d.ts +7 -7
- package/dist/parse_exports.d.ts.map +1 -1
- package/dist/parse_exports.js +3 -3
- package/dist/parse_exports_context.d.ts +3 -3
- package/dist/parse_exports_context.d.ts.map +1 -1
- package/dist/parse_exports_context.js +1 -1
- package/dist/parse_imports.d.ts +3 -3
- package/dist/parse_imports.d.ts.map +1 -1
- package/dist/parse_imports.js +2 -2
- package/dist/paths.d.ts +6 -6
- package/dist/paths.d.ts.map +1 -1
- package/dist/plugin.d.ts +13 -13
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +1 -1
- package/dist/publish.task.d.ts.map +1 -1
- package/dist/publish.task.js +12 -12
- package/dist/reinstall.task.d.ts.map +1 -1
- package/dist/reinstall.task.js +4 -4
- package/dist/resolve_specifier.d.ts +4 -4
- package/dist/resolve_specifier.d.ts.map +1 -1
- package/dist/run.task.d.ts.map +1 -1
- package/dist/run.task.js +9 -6
- package/dist/run_gen.d.ts +4 -4
- package/dist/run_gen.d.ts.map +1 -1
- package/dist/run_task.d.ts +4 -4
- package/dist/run_task.d.ts.map +1 -1
- package/dist/run_task.js +3 -3
- package/dist/search_fs.d.ts +6 -6
- package/dist/search_fs.d.ts.map +1 -1
- package/dist/src_json.d.ts +6 -6
- package/dist/src_json.d.ts.map +1 -1
- package/dist/src_json.js +3 -3
- package/dist/svelte_config.d.ts +3 -3
- package/dist/svelte_config.d.ts.map +1 -1
- package/dist/sveltekit_helpers.d.ts +5 -5
- package/dist/sveltekit_helpers.d.ts.map +1 -1
- package/dist/sveltekit_helpers.js +5 -5
- package/dist/sveltekit_shim_app.d.ts +2 -2
- package/dist/sveltekit_shim_app.d.ts.map +1 -1
- package/dist/sync.task.d.ts.map +1 -1
- package/dist/sync.task.js +2 -2
- package/dist/task.d.ts +54 -54
- package/dist/task.d.ts.map +1 -1
- package/dist/task.js +3 -3
- package/dist/task_logging.d.ts +3 -3
- package/dist/task_logging.d.ts.map +1 -1
- package/dist/test.task.d.ts.map +1 -1
- package/dist/test.task.js +4 -4
- package/dist/typecheck.task.d.ts.map +1 -1
- package/dist/typecheck.task.js +4 -4
- package/dist/upgrade.task.d.ts.map +1 -1
- package/dist/upgrade.task.js +5 -5
- package/dist/watch_dir.d.ts +10 -10
- package/dist/watch_dir.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/lib/args.ts +9 -9
- package/src/lib/build.task.ts +2 -2
- package/src/lib/build_cache.ts +18 -18
- package/src/lib/changelog.ts +10 -10
- package/src/lib/changeset.task.ts +16 -16
- package/src/lib/changeset_helpers.ts +4 -4
- package/src/lib/check.task.ts +3 -3
- package/src/lib/clean.task.ts +2 -2
- package/src/lib/cli.ts +7 -7
- package/src/lib/commit.task.ts +2 -2
- package/src/lib/deploy.task.ts +15 -15
- package/src/lib/dev.task.ts +2 -2
- package/src/lib/disknode.ts +4 -4
- package/src/lib/esbuild_helpers.ts +2 -2
- package/src/lib/esbuild_plugin_external_worker.ts +7 -7
- package/src/lib/esbuild_plugin_svelte.ts +4 -4
- package/src/lib/esbuild_plugin_sveltekit_shim_alias.ts +2 -2
- package/src/lib/esbuild_plugin_sveltekit_shim_app.ts +5 -5
- package/src/lib/esbuild_plugin_sveltekit_shim_env.ts +2 -2
- package/src/lib/filer.ts +35 -35
- package/src/lib/format.task.ts +2 -2
- package/src/lib/format_directory.ts +2 -2
- package/src/lib/gen.task.ts +19 -19
- package/src/lib/gen.ts +85 -85
- package/src/lib/gen_helpers.ts +17 -17
- package/src/lib/github.ts +6 -6
- package/src/lib/gro.config.default.ts +2 -2
- package/src/lib/gro_config.ts +28 -28
- package/src/lib/gro_helpers.ts +2 -2
- package/src/lib/gro_plugin_gen.ts +5 -5
- package/src/lib/gro_plugin_server.ts +8 -8
- package/src/lib/gro_plugin_sveltekit_app.ts +15 -15
- package/src/lib/gro_plugin_sveltekit_library.ts +6 -6
- package/src/lib/index.ts +3 -3
- package/src/lib/input_path.ts +56 -56
- package/src/lib/invoke.ts +2 -2
- package/src/lib/invoke_task.ts +7 -7
- package/src/lib/lint.task.ts +2 -2
- package/src/lib/modules.ts +31 -31
- package/src/lib/package_json.ts +27 -27
- package/src/lib/parse_exports.ts +15 -15
- package/src/lib/parse_exports_context.ts +9 -9
- package/src/lib/parse_imports.ts +6 -6
- package/src/lib/paths.ts +6 -6
- package/src/lib/plugin.ts +17 -17
- package/src/lib/publish.task.ts +13 -13
- package/src/lib/reinstall.task.ts +4 -4
- package/src/lib/resolve_specifier.ts +5 -5
- package/src/lib/run.task.ts +10 -6
- package/src/lib/run_gen.ts +14 -14
- package/src/lib/run_task.ts +8 -8
- package/src/lib/search_fs.ts +13 -13
- package/src/lib/src_json.ts +13 -13
- package/src/lib/svelte_config.ts +2 -2
- package/src/lib/sveltekit_helpers.ts +12 -12
- package/src/lib/sveltekit_shim_app.ts +3 -3
- package/src/lib/sync.task.ts +2 -2
- package/src/lib/task.ts +63 -63
- package/src/lib/task_logging.ts +11 -11
- package/src/lib/test.task.ts +4 -4
- package/src/lib/typecheck.task.ts +4 -4
- package/src/lib/upgrade.task.ts +7 -7
- package/src/lib/watch_dir.ts +10 -10
package/src/lib/package_json.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {readFileSync, writeFileSync} from 'node:fs';
|
|
|
4
4
|
import {plural, strip_end} from '@ryanatkn/belt/string.js';
|
|
5
5
|
import type {Logger} from '@ryanatkn/belt/log.js';
|
|
6
6
|
import {styleText as st} from 'node:util';
|
|
7
|
-
import {
|
|
7
|
+
import {PackageJson, PackageJsonExports} from '@ryanatkn/belt/package_json.js';
|
|
8
8
|
|
|
9
9
|
import {paths, gro_paths, IS_THIS_GRO} from './paths.ts';
|
|
10
10
|
import {
|
|
@@ -20,19 +20,19 @@ import {search_fs} from './search_fs.ts';
|
|
|
20
20
|
import {has_sveltekit_library} from './sveltekit_helpers.ts';
|
|
21
21
|
import {GITHUB_REPO_MATCHER} from './github.ts';
|
|
22
22
|
|
|
23
|
-
export type
|
|
24
|
-
package_json:
|
|
25
|
-
) =>
|
|
23
|
+
export type PackageJsonMapper = (
|
|
24
|
+
package_json: PackageJson,
|
|
25
|
+
) => PackageJson | null | Promise<PackageJson | null>;
|
|
26
26
|
|
|
27
|
-
export const EMPTY_PACKAGE_JSON:
|
|
27
|
+
export const EMPTY_PACKAGE_JSON: PackageJson = {name: '', version: ''};
|
|
28
28
|
|
|
29
29
|
export const load_package_json = (
|
|
30
30
|
dir = IS_THIS_GRO ? gro_paths.root : paths.root,
|
|
31
|
-
cache?: Record<string,
|
|
31
|
+
cache?: Record<string, PackageJson>,
|
|
32
32
|
parse = true, // TODO pass `false` here in more places, especially anything perf-sensitive like work on startup
|
|
33
33
|
log?: Logger,
|
|
34
|
-
):
|
|
35
|
-
let package_json:
|
|
34
|
+
): PackageJson => {
|
|
35
|
+
let package_json: PackageJson;
|
|
36
36
|
if (cache && dir in cache) {
|
|
37
37
|
return cache[dir]!;
|
|
38
38
|
}
|
|
@@ -43,7 +43,7 @@ export const load_package_json = (
|
|
|
43
43
|
return EMPTY_PACKAGE_JSON;
|
|
44
44
|
}
|
|
45
45
|
if (parse) {
|
|
46
|
-
package_json = parse_package_json(
|
|
46
|
+
package_json = parse_package_json(PackageJson, package_json);
|
|
47
47
|
}
|
|
48
48
|
if (cache) {
|
|
49
49
|
cache[dir] = package_json;
|
|
@@ -52,12 +52,12 @@ export const load_package_json = (
|
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
export const sync_package_json = async (
|
|
55
|
-
map_package_json:
|
|
55
|
+
map_package_json: PackageJsonMapper,
|
|
56
56
|
log: Logger,
|
|
57
57
|
write = true,
|
|
58
58
|
dir = paths.root,
|
|
59
59
|
exports_dir = paths.lib,
|
|
60
|
-
): Promise<{package_json:
|
|
60
|
+
): Promise<{package_json: PackageJson | null; changed: boolean}> => {
|
|
61
61
|
const exported_files = search_fs(exports_dir);
|
|
62
62
|
const exported_paths = exported_files.map((f) => f.path);
|
|
63
63
|
const updated = await update_package_json(
|
|
@@ -66,7 +66,7 @@ export const sync_package_json = async (
|
|
|
66
66
|
package_json.exports = to_package_exports(exported_paths);
|
|
67
67
|
}
|
|
68
68
|
const mapped = await map_package_json(package_json);
|
|
69
|
-
return mapped ? parse_package_json(
|
|
69
|
+
return mapped ? parse_package_json(PackageJson, mapped) : mapped;
|
|
70
70
|
},
|
|
71
71
|
dir,
|
|
72
72
|
write,
|
|
@@ -85,7 +85,7 @@ export const sync_package_json = async (
|
|
|
85
85
|
return updated;
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
-
export const load_gro_package_json = ():
|
|
88
|
+
export const load_gro_package_json = (): PackageJson => load_package_json(gro_paths.root);
|
|
89
89
|
|
|
90
90
|
// TODO probably make this nullable and make callers handle failures
|
|
91
91
|
const load_package_json_contents = (dir: string): string =>
|
|
@@ -95,17 +95,17 @@ export const write_package_json = (serialized_package_json: string): void => {
|
|
|
95
95
|
writeFileSync(join(paths.root, PACKAGE_JSON_FILENAME), serialized_package_json);
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
export const serialize_package_json = (package_json:
|
|
99
|
-
JSON.stringify(parse_package_json(
|
|
98
|
+
export const serialize_package_json = (package_json: PackageJson): string =>
|
|
99
|
+
JSON.stringify(parse_package_json(PackageJson, package_json), null, 2) + '\n';
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Updates package.json. Writes to the filesystem only when contents change.
|
|
103
103
|
*/
|
|
104
104
|
export const update_package_json = async (
|
|
105
|
-
update: (package_json:
|
|
105
|
+
update: (package_json: PackageJson) => PackageJson | null | Promise<PackageJson | null>,
|
|
106
106
|
dir = paths.root,
|
|
107
107
|
write = true,
|
|
108
|
-
): Promise<{package_json:
|
|
108
|
+
): Promise<{package_json: PackageJson | null; changed: boolean}> => {
|
|
109
109
|
const original_contents = load_package_json_contents(dir);
|
|
110
110
|
const original = JSON.parse(original_contents);
|
|
111
111
|
const updated = await update(original);
|
|
@@ -122,14 +122,14 @@ export const update_package_json = async (
|
|
|
122
122
|
|
|
123
123
|
const is_index = (path: string): boolean => path === 'index.ts' || path === 'index.js';
|
|
124
124
|
|
|
125
|
-
export const to_package_exports = (paths: Array<string>):
|
|
125
|
+
export const to_package_exports = (paths: Array<string>): PackageJsonExports => {
|
|
126
126
|
const has_index = paths.some(is_index);
|
|
127
127
|
const has_js = paths.some((p) => TS_MATCHER.test(p) || JS_MATCHER.test(p));
|
|
128
128
|
const has_svelte = paths.some((p) => SVELTE_MATCHER.test(p));
|
|
129
129
|
const has_json = paths.some((p) => JSON_MATCHER.test(p));
|
|
130
130
|
const has_css = paths.some((p) => CSS_MATCHER.test(p));
|
|
131
131
|
|
|
132
|
-
const exports:
|
|
132
|
+
const exports: PackageJsonExports = {
|
|
133
133
|
'./package.json': './package.json',
|
|
134
134
|
};
|
|
135
135
|
|
|
@@ -172,13 +172,13 @@ export const to_package_exports = (paths: Array<string>): Package_Json_Exports =
|
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
return parse_or_throw_formatted_error('package.json#exports',
|
|
175
|
+
return parse_or_throw_formatted_error('package.json#exports', PackageJsonExports, exports);
|
|
176
176
|
};
|
|
177
177
|
|
|
178
178
|
const IMPORT_PREFIX = './' + SVELTEKIT_DIST_DIRNAME + '/';
|
|
179
179
|
|
|
180
180
|
export const parse_repo_url = (
|
|
181
|
-
package_json:
|
|
181
|
+
package_json: PackageJson,
|
|
182
182
|
): {owner: string; repo: string} | undefined => {
|
|
183
183
|
const {repository} = package_json;
|
|
184
184
|
const repo_url = repository
|
|
@@ -198,9 +198,9 @@ export const parse_repo_url = (
|
|
|
198
198
|
};
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
|
-
* Parses a `
|
|
201
|
+
* Parses a `PackageJson` object but preserves the order of the original keys.
|
|
202
202
|
*/
|
|
203
|
-
const parse_package_json = (schema: typeof
|
|
203
|
+
const parse_package_json = (schema: typeof PackageJson, value: any): PackageJson => {
|
|
204
204
|
const parsed = parse_or_throw_formatted_error(PACKAGE_JSON_FILENAME, schema, value);
|
|
205
205
|
const keys = Object.keys(value);
|
|
206
206
|
return Object.fromEntries(
|
|
@@ -227,19 +227,19 @@ const parse_or_throw_formatted_error = <T extends z.ZodType>(
|
|
|
227
227
|
|
|
228
228
|
export const has_dep = (
|
|
229
229
|
dep_name: string,
|
|
230
|
-
package_json:
|
|
230
|
+
package_json: PackageJson = load_package_json(),
|
|
231
231
|
): boolean =>
|
|
232
232
|
!!package_json.devDependencies?.[dep_name] ||
|
|
233
233
|
!!package_json.dependencies?.[dep_name] ||
|
|
234
234
|
!!package_json.peerDependencies?.[dep_name];
|
|
235
235
|
|
|
236
|
-
export interface
|
|
236
|
+
export interface PackageJsonDep {
|
|
237
237
|
name: string;
|
|
238
238
|
version: string;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
export const extract_deps = (package_json:
|
|
242
|
-
const deps_by_name: Map<string,
|
|
241
|
+
export const extract_deps = (package_json: PackageJson): Array<PackageJsonDep> => {
|
|
242
|
+
const deps_by_name: Map<string, PackageJsonDep> = new Map();
|
|
243
243
|
// Earlier versions override later ones, so peer deps goes last.
|
|
244
244
|
const add_deps = (deps: Record<string, string> | undefined) => {
|
|
245
245
|
if (!deps) return;
|
package/src/lib/parse_exports.ts
CHANGED
|
@@ -2,28 +2,28 @@ import ts from 'typescript';
|
|
|
2
2
|
import {extname} from 'node:path';
|
|
3
3
|
import type {Flavored} from '@ryanatkn/belt/types.js';
|
|
4
4
|
import type {Logger} from '@ryanatkn/belt/log.js';
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
5
|
+
import type {IdentifierKind} from '@ryanatkn/belt/src_json.js';
|
|
6
|
+
import type {PathId} from '@ryanatkn/belt/path.js';
|
|
7
7
|
|
|
8
8
|
import {TS_MATCHER} from './constants.ts';
|
|
9
|
-
import {
|
|
9
|
+
import {ParseExportsContext} from './parse_exports_context.ts';
|
|
10
10
|
|
|
11
11
|
export interface Declaration {
|
|
12
12
|
name: string;
|
|
13
|
-
kind:
|
|
13
|
+
kind: IdentifierKind | null;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export type
|
|
16
|
+
export type ExportDeclaration = Flavored<Declaration, 'ExportDeclaration'>;
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Parse exports from a file based on its file type and content.
|
|
20
20
|
*/
|
|
21
21
|
export const parse_exports = (
|
|
22
|
-
id:
|
|
22
|
+
id: PathId,
|
|
23
23
|
program?: ts.Program,
|
|
24
|
-
declarations: Array<
|
|
24
|
+
declarations: Array<ExportDeclaration> = [],
|
|
25
25
|
log?: Logger,
|
|
26
|
-
): Array<
|
|
26
|
+
): Array<ExportDeclaration> => {
|
|
27
27
|
// First, infer declarations based on file extension
|
|
28
28
|
infer_declarations_from_file_type(id, declarations);
|
|
29
29
|
|
|
@@ -42,7 +42,7 @@ export const parse_exports = (
|
|
|
42
42
|
const exports = checker.getExportsOfModule(symbol);
|
|
43
43
|
|
|
44
44
|
// Process TypeScript declarations
|
|
45
|
-
const export_context = new
|
|
45
|
+
const export_context = new ParseExportsContext(program, log);
|
|
46
46
|
export_context.analyze_source_file(source_file);
|
|
47
47
|
export_context.process_exports(source_file, exports, declarations);
|
|
48
48
|
}
|
|
@@ -52,9 +52,9 @@ export const parse_exports = (
|
|
|
52
52
|
|
|
53
53
|
// TODO temporary until proper type inference
|
|
54
54
|
export const infer_declarations_from_file_type = (
|
|
55
|
-
file_path:
|
|
56
|
-
declarations: Array<
|
|
57
|
-
): Array<
|
|
55
|
+
file_path: PathId,
|
|
56
|
+
declarations: Array<ExportDeclaration> = [],
|
|
57
|
+
): Array<ExportDeclaration> => {
|
|
58
58
|
const extension = extname(file_path).toLowerCase();
|
|
59
59
|
|
|
60
60
|
switch (extension) {
|
|
@@ -91,10 +91,10 @@ export const process_ts_exports = (
|
|
|
91
91
|
source_file: ts.SourceFile,
|
|
92
92
|
program: ts.Program,
|
|
93
93
|
exports: Array<ts.Symbol>,
|
|
94
|
-
declarations: Array<
|
|
94
|
+
declarations: Array<ExportDeclaration> = [],
|
|
95
95
|
log?: Logger,
|
|
96
|
-
): Array<
|
|
97
|
-
const export_context = new
|
|
96
|
+
): Array<ExportDeclaration> => {
|
|
97
|
+
const export_context = new ParseExportsContext(program, log);
|
|
98
98
|
export_context.analyze_source_file(source_file);
|
|
99
99
|
return export_context.process_exports(source_file, exports, declarations);
|
|
100
100
|
};
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import type {Logger} from '@ryanatkn/belt/log.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type {IdentifierKind} from '@ryanatkn/belt/src_json.js';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {ExportDeclaration} from './parse_exports.ts';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* A class to track export context and determine export kinds.
|
|
9
9
|
*/
|
|
10
|
-
export class
|
|
10
|
+
export class ParseExportsContext {
|
|
11
11
|
readonly #checker: ts.TypeChecker;
|
|
12
12
|
|
|
13
13
|
// Map of source file paths to their symbols
|
|
14
14
|
readonly #file_symbols: Map<string, ts.Symbol> = new Map();
|
|
15
15
|
// Cache for resolved symbols to avoid repeated resolution
|
|
16
|
-
readonly #symbol_kind_cache: Map<ts.Symbol,
|
|
16
|
+
readonly #symbol_kind_cache: Map<ts.Symbol, IdentifierKind> = new Map();
|
|
17
17
|
|
|
18
18
|
readonly log: Logger | undefined;
|
|
19
19
|
debug = process.env.DEBUG_EXPORTS === 'true';
|
|
@@ -56,8 +56,8 @@ export class Parse_Exports_Context {
|
|
|
56
56
|
process_exports(
|
|
57
57
|
source_file: ts.SourceFile,
|
|
58
58
|
exports: Array<ts.Symbol>,
|
|
59
|
-
declarations: Array<
|
|
60
|
-
): Array<
|
|
59
|
+
declarations: Array<ExportDeclaration> = [],
|
|
60
|
+
): Array<ExportDeclaration> {
|
|
61
61
|
for (const export_symbol of exports) {
|
|
62
62
|
const name = export_symbol.name;
|
|
63
63
|
this.#log(`Determining kind for export: ${name}`);
|
|
@@ -75,7 +75,7 @@ export class Parse_Exports_Context {
|
|
|
75
75
|
/**
|
|
76
76
|
* Determine the kind of an export based on its symbol.
|
|
77
77
|
*/
|
|
78
|
-
#determine_export_kind(source_file: ts.SourceFile, symbol: ts.Symbol):
|
|
78
|
+
#determine_export_kind(source_file: ts.SourceFile, symbol: ts.Symbol): IdentifierKind {
|
|
79
79
|
// Check if this is a type-only export (no value export)
|
|
80
80
|
if (this.#is_type_only_export(source_file, symbol)) {
|
|
81
81
|
return 'type';
|
|
@@ -115,7 +115,7 @@ export class Parse_Exports_Context {
|
|
|
115
115
|
/**
|
|
116
116
|
* Infer the declaration kind from a symbol's declaration and type information.
|
|
117
117
|
*/
|
|
118
|
-
#infer_declaration_kind(symbol: ts.Symbol):
|
|
118
|
+
#infer_declaration_kind(symbol: ts.Symbol): IdentifierKind {
|
|
119
119
|
// Check symbol flags first for direct type matching
|
|
120
120
|
if (this.#is_class_symbol(symbol)) {
|
|
121
121
|
return 'class';
|
|
@@ -182,7 +182,7 @@ export class Parse_Exports_Context {
|
|
|
182
182
|
/**
|
|
183
183
|
* Infer the declaration kind from a specific declaration node.
|
|
184
184
|
*/
|
|
185
|
-
#infer_kind_from_declaration(decl: ts.Declaration):
|
|
185
|
+
#infer_kind_from_declaration(decl: ts.Declaration): IdentifierKind | null {
|
|
186
186
|
if (ts.isFunctionDeclaration(decl)) {
|
|
187
187
|
return 'function';
|
|
188
188
|
}
|
package/src/lib/parse_imports.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {parseSync, type ImportDeclaration} from 'oxc-parser';
|
|
2
2
|
import type {Flavored} from '@ryanatkn/belt/types.js';
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
3
|
+
import {UnreachableError} from '@ryanatkn/belt/error.js';
|
|
4
|
+
import type {PathId} from '@ryanatkn/belt/path.js';
|
|
5
5
|
|
|
6
6
|
import {JS_MATCHER, TS_MATCHER, SVELTE_MATCHER, SVELTE_SCRIPT_MATCHER} from './constants.ts';
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type ImportSpecifier = Flavored<string, 'ImportSpecifier'>;
|
|
9
9
|
|
|
10
10
|
// TODO this is probably way more complicated that it should be, maybe report the issues upstream unless I made a mistake here
|
|
11
11
|
|
|
@@ -31,10 +31,10 @@ const extract_string_literal = (content: string, start: number, end: number): st
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export const parse_imports = (
|
|
34
|
-
id:
|
|
34
|
+
id: PathId,
|
|
35
35
|
contents: string,
|
|
36
36
|
ignore_types = true,
|
|
37
|
-
): Array<
|
|
37
|
+
): Array<ImportSpecifier> => {
|
|
38
38
|
const specifiers: Array<string> = [];
|
|
39
39
|
const is_svelte = SVELTE_MATCHER.test(id);
|
|
40
40
|
|
|
@@ -129,7 +129,7 @@ export const parse_imports = (
|
|
|
129
129
|
specifiers.push(value);
|
|
130
130
|
}
|
|
131
131
|
} else {
|
|
132
|
-
throw new
|
|
132
|
+
throw new UnreachableError(node.source.type);
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
}
|
package/src/lib/paths.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {join, extname, relative, basename} from 'node:path';
|
|
|
2
2
|
import {fileURLToPath} from 'node:url';
|
|
3
3
|
import {ensure_end, strip_end} from '@ryanatkn/belt/string.js';
|
|
4
4
|
import {styleText as st} from 'node:util';
|
|
5
|
-
import type {
|
|
5
|
+
import type {PathId} from '@ryanatkn/belt/path.js';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
GRO_CONFIG_FILENAME,
|
|
@@ -53,22 +53,22 @@ export const create_paths = (root_dir: string): Paths => {
|
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
export const infer_paths = (id:
|
|
56
|
+
export const infer_paths = (id: PathId): Paths => (is_gro_id(id) ? gro_paths : paths);
|
|
57
57
|
|
|
58
|
-
export const is_gro_id = (id:
|
|
58
|
+
export const is_gro_id = (id: PathId): boolean =>
|
|
59
59
|
id.startsWith(gro_paths.root) || gro_paths.root === ensure_end(id, '/');
|
|
60
60
|
|
|
61
61
|
// '/home/me/app/src/foo/bar/baz.ts' → 'src/foo/bar/baz.ts'
|
|
62
|
-
export const to_root_path = (id:
|
|
62
|
+
export const to_root_path = (id: PathId, p = infer_paths(id)): string =>
|
|
63
63
|
relative(p.root, id) || './';
|
|
64
64
|
|
|
65
65
|
// '/home/me/app/src/foo/bar/baz.ts' → 'foo/bar/baz.ts'
|
|
66
|
-
export const path_id_to_base_path = (path_id:
|
|
66
|
+
export const path_id_to_base_path = (path_id: PathId, p = infer_paths(path_id)): string =>
|
|
67
67
|
relative(p.source, path_id);
|
|
68
68
|
|
|
69
69
|
// TODO base_path is an obsolete concept, it was a remnant from forcing `src/`
|
|
70
70
|
// 'foo/bar/baz.ts' → '/home/me/app/src/foo/bar/baz.ts'
|
|
71
|
-
export const base_path_to_path_id = (base_path: string, p = infer_paths(base_path)):
|
|
71
|
+
export const base_path_to_path_id = (base_path: string, p = infer_paths(base_path)): PathId =>
|
|
72
72
|
join(p.source, base_path);
|
|
73
73
|
|
|
74
74
|
export const print_path = (path: string, p = infer_paths(path)): string => {
|
package/src/lib/plugin.ts
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {TaskContext} from './task.ts';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Gro `Plugin`s enable custom behavior during `gro dev` and `gro build`.
|
|
5
5
|
* In contrast, `Adapter`s use the results of `gro build` to produce final artifacts.
|
|
6
6
|
*/
|
|
7
|
-
export interface Plugin<
|
|
7
|
+
export interface Plugin<TPluginContext extends PluginContext = PluginContext> {
|
|
8
8
|
name: string;
|
|
9
|
-
setup?: (ctx:
|
|
10
|
-
adapt?: (ctx:
|
|
11
|
-
teardown?: (ctx:
|
|
9
|
+
setup?: (ctx: TPluginContext) => void | Promise<void>;
|
|
10
|
+
adapt?: (ctx: TPluginContext) => void | Promise<void>;
|
|
11
|
+
teardown?: (ctx: TPluginContext) => void | Promise<void>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export type
|
|
15
|
-
ctx:
|
|
16
|
-
) => Array<Plugin<
|
|
14
|
+
export type CreateConfigPlugins<TPluginContext extends PluginContext = PluginContext> = (
|
|
15
|
+
ctx: TPluginContext,
|
|
16
|
+
) => Array<Plugin<TPluginContext>> | Promise<Array<Plugin<TPluginContext>>>;
|
|
17
17
|
|
|
18
|
-
export interface
|
|
18
|
+
export interface PluginContext<TArgs = object> extends TaskContext<TArgs> {
|
|
19
19
|
dev: boolean;
|
|
20
20
|
watch: boolean;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/** See `Plugins.create` for a usage example. */
|
|
24
|
-
export class Plugins<
|
|
25
|
-
readonly ctx:
|
|
26
|
-
readonly instances: Array<Plugin<
|
|
24
|
+
export class Plugins<TPluginContext extends PluginContext> {
|
|
25
|
+
readonly ctx: TPluginContext;
|
|
26
|
+
readonly instances: Array<Plugin<TPluginContext>>;
|
|
27
27
|
|
|
28
|
-
constructor(ctx:
|
|
28
|
+
constructor(ctx: TPluginContext, instances: Array<Plugin>) {
|
|
29
29
|
this.ctx = ctx;
|
|
30
30
|
this.instances = instances;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
static async create<
|
|
34
|
-
ctx:
|
|
35
|
-
): Promise<Plugins<
|
|
33
|
+
static async create<TPluginContext extends PluginContext>(
|
|
34
|
+
ctx: TPluginContext,
|
|
35
|
+
): Promise<Plugins<TPluginContext>> {
|
|
36
36
|
const {timings} = ctx;
|
|
37
37
|
const timing_to_create = timings.start('plugins.create');
|
|
38
38
|
const instances: Array<Plugin> = await ctx.config.plugins(ctx);
|
|
@@ -88,7 +88,7 @@ export class Plugins<T_Plugin_Context extends Plugin_Context> {
|
|
|
88
88
|
/**
|
|
89
89
|
* Replaces a plugin by name in `plugins` without mutating the param.
|
|
90
90
|
* Throws if the plugin name cannot be found.
|
|
91
|
-
* @param plugins - accepts the same types as the return value of `
|
|
91
|
+
* @param plugins - accepts the same types as the return value of `CreateConfigPlugins`
|
|
92
92
|
* @param new_plugin
|
|
93
93
|
* @param name - @default new_plugin.name
|
|
94
94
|
* @returns `plugins` with `new_plugin` at the index of the plugin with `name`
|
package/src/lib/publish.task.ts
CHANGED
|
@@ -3,15 +3,15 @@ import {z} from 'zod';
|
|
|
3
3
|
import {styleText as st} from 'node:util';
|
|
4
4
|
import {existsSync} from 'node:fs';
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
GitBranch,
|
|
7
|
+
GitOrigin,
|
|
8
8
|
git_check_clean_workspace,
|
|
9
9
|
git_checkout,
|
|
10
10
|
git_fetch,
|
|
11
11
|
git_pull,
|
|
12
12
|
} from '@ryanatkn/belt/git.js';
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {TaskError, type Task} from './task.ts';
|
|
15
15
|
import {load_package_json, parse_repo_url} from './package_json.ts';
|
|
16
16
|
import {find_cli, spawn_cli} from './cli.ts';
|
|
17
17
|
import {has_sveltekit_library} from './sveltekit_helpers.ts';
|
|
@@ -21,8 +21,8 @@ import {CHANGESET_CLI} from './changeset_helpers.ts';
|
|
|
21
21
|
|
|
22
22
|
/** @nodocs */
|
|
23
23
|
export const Args = z.strictObject({
|
|
24
|
-
branch:
|
|
25
|
-
origin:
|
|
24
|
+
branch: GitBranch.describe('branch to publish from').default('main'),
|
|
25
|
+
origin: GitOrigin.describe('git origin to publish from').default('origin'),
|
|
26
26
|
changelog: z
|
|
27
27
|
.string()
|
|
28
28
|
.meta({description: 'file name and path of the changelog'})
|
|
@@ -89,7 +89,7 @@ export const task: Task<Args> = {
|
|
|
89
89
|
|
|
90
90
|
const has_sveltekit_library_result = await has_sveltekit_library(package_json);
|
|
91
91
|
if (!has_sveltekit_library_result.ok) {
|
|
92
|
-
throw new
|
|
92
|
+
throw new TaskError(
|
|
93
93
|
'Failed to find SvelteKit library: ' + has_sveltekit_library_result.message,
|
|
94
94
|
);
|
|
95
95
|
}
|
|
@@ -98,7 +98,7 @@ export const task: Task<Args> = {
|
|
|
98
98
|
|
|
99
99
|
const found_changeset_cli = find_cli(changeset_cli);
|
|
100
100
|
if (!found_changeset_cli) {
|
|
101
|
-
throw new
|
|
101
|
+
throw new TaskError(
|
|
102
102
|
'changeset command not found, install @changesets/cli locally or globally',
|
|
103
103
|
);
|
|
104
104
|
}
|
|
@@ -108,7 +108,7 @@ export const task: Task<Args> = {
|
|
|
108
108
|
await git_checkout(branch);
|
|
109
109
|
if (pull) {
|
|
110
110
|
if (await git_check_clean_workspace()) {
|
|
111
|
-
throw new
|
|
111
|
+
throw new TaskError('The git workspace is not clean, pass --no-pull to bypass git pull');
|
|
112
112
|
}
|
|
113
113
|
await git_pull(origin, branch);
|
|
114
114
|
}
|
|
@@ -138,11 +138,11 @@ export const task: Task<Args> = {
|
|
|
138
138
|
log.info('dry run, skipping changeset version');
|
|
139
139
|
} else {
|
|
140
140
|
if (typeof package_json.version !== 'string') {
|
|
141
|
-
throw new
|
|
141
|
+
throw new TaskError('Failed to find package.json version');
|
|
142
142
|
}
|
|
143
143
|
const parsed_repo_url = parse_repo_url(package_json);
|
|
144
144
|
if (!parsed_repo_url) {
|
|
145
|
-
throw new
|
|
145
|
+
throw new TaskError(
|
|
146
146
|
'package.json `repository` must contain a repo url (and GitHub only for now, sorry),' +
|
|
147
147
|
' like `git+https://github.com/ryanatkn/gro.git` or `https://github.com/ryanatkn/gro`' +
|
|
148
148
|
' or an object with the `url` key',
|
|
@@ -170,7 +170,7 @@ export const task: Task<Args> = {
|
|
|
170
170
|
if (install) {
|
|
171
171
|
const install_result = await spawn(config.pm_cli, ['install']);
|
|
172
172
|
if (!install_result.ok) {
|
|
173
|
-
throw new
|
|
173
|
+
throw new TaskError(`Failed \`${config.pm_cli} install\` after version bump`);
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
|
|
@@ -187,7 +187,7 @@ export const task: Task<Args> = {
|
|
|
187
187
|
optional_and_version_unchanged = true;
|
|
188
188
|
} else {
|
|
189
189
|
// Doesn't build if the version didn't change and publishing isn't optional.
|
|
190
|
-
throw new
|
|
190
|
+
throw new TaskError(`\`${changeset_cli} version\` failed: are there any changes?`);
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|
|
@@ -212,7 +212,7 @@ export const task: Task<Args> = {
|
|
|
212
212
|
|
|
213
213
|
const changeset_publish_result = await spawn_cli(found_changeset_cli, ['publish'], log);
|
|
214
214
|
if (!changeset_publish_result?.ok) {
|
|
215
|
-
throw new
|
|
215
|
+
throw new TaskError(
|
|
216
216
|
`\`${changeset_cli} publish\` failed - continue manually or try again after running \`git reset --hard\``,
|
|
217
217
|
);
|
|
218
218
|
}
|
|
@@ -2,7 +2,7 @@ import {z} from 'zod';
|
|
|
2
2
|
import {spawn} from '@ryanatkn/belt/process.js';
|
|
3
3
|
import {rm} from 'node:fs/promises';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {TaskError, type Task} from './task.ts';
|
|
6
6
|
import {LOCKFILE_FILENAME, NODE_MODULES_DIRNAME} from './constants.ts';
|
|
7
7
|
|
|
8
8
|
/** @nodocs */
|
|
@@ -17,7 +17,7 @@ export const task: Task<Args> = {
|
|
|
17
17
|
log.info(`running the initial \`${config.pm_cli} install\``);
|
|
18
18
|
const initial_install_result = await spawn(config.pm_cli, ['install']);
|
|
19
19
|
if (!initial_install_result.ok) {
|
|
20
|
-
throw new
|
|
20
|
+
throw new TaskError(`Failed initial \`${config.pm_cli} install\``);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Deleting both the lockfile and node_modules upgrades to the latest minor/patch versions.
|
|
@@ -27,7 +27,7 @@ export const task: Task<Args> = {
|
|
|
27
27
|
);
|
|
28
28
|
const second_install_result = await spawn(config.pm_cli, ['install']);
|
|
29
29
|
if (!second_install_result.ok) {
|
|
30
|
-
throw new
|
|
30
|
+
throw new TaskError(
|
|
31
31
|
`Failed \`${config.pm_cli} install\` after deleting ${LOCKFILE_FILENAME} and ${NODE_MODULES_DIRNAME}`,
|
|
32
32
|
);
|
|
33
33
|
}
|
|
@@ -39,7 +39,7 @@ export const task: Task<Args> = {
|
|
|
39
39
|
log.info(`running \`${config.pm_cli} install\` one last time to clean ${LOCKFILE_FILENAME}`);
|
|
40
40
|
const final_install_result = await spawn(config.pm_cli, ['install']);
|
|
41
41
|
if (!final_install_result.ok) {
|
|
42
|
-
throw new
|
|
42
|
+
throw new TaskError(`Failed \`${config.pm_cli} install\``);
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {extname, isAbsolute, join, relative} from 'node:path';
|
|
2
2
|
import {existsSync} from 'node:fs';
|
|
3
|
-
import type {
|
|
3
|
+
import type {PathId} from '@ryanatkn/belt/path.js';
|
|
4
4
|
|
|
5
5
|
import {replace_extension} from './paths.ts';
|
|
6
6
|
|
|
7
7
|
// TODO ideally this module doesnt exist, but import.meta.resolve doesn't work in loaders last I tried
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface ResolvedSpecifier {
|
|
10
10
|
/**
|
|
11
11
|
* The resolved filesystem path for the specifier.
|
|
12
12
|
*/
|
|
13
|
-
path_id:
|
|
13
|
+
path_id: PathId;
|
|
14
14
|
/**
|
|
15
15
|
* Same as `path_id` but includes `?raw` and other querystrings. (currently none)
|
|
16
16
|
*/
|
|
@@ -26,14 +26,14 @@ export interface Resolved_Specifier {
|
|
|
26
26
|
* and infer the correct extension following Vite conventions.
|
|
27
27
|
* If no `.js` file is found for the specifier on the filesystem, it assumes `.ts`.
|
|
28
28
|
*/
|
|
29
|
-
export const resolve_specifier = (specifier: string, dir: string):
|
|
29
|
+
export const resolve_specifier = (specifier: string, dir: string): ResolvedSpecifier => {
|
|
30
30
|
const raw = specifier.endsWith('?raw'); // TODO more robust detection? other values?
|
|
31
31
|
const final_specifier = raw ? specifier.substring(0, specifier.length - 4) : specifier;
|
|
32
32
|
const absolute_path = isAbsolute(final_specifier) ? final_specifier : join(dir, final_specifier);
|
|
33
33
|
|
|
34
34
|
let mapped_path;
|
|
35
35
|
let path_id;
|
|
36
|
-
let namespace:
|
|
36
|
+
let namespace: ResolvedSpecifier['namespace'];
|
|
37
37
|
|
|
38
38
|
const ext = extname(absolute_path);
|
|
39
39
|
const is_js = ext === '.js';
|
package/src/lib/run.task.ts
CHANGED
|
@@ -2,9 +2,9 @@ import {z} from 'zod';
|
|
|
2
2
|
import {styleText as st} from 'node:util';
|
|
3
3
|
import {existsSync} from 'node:fs';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {TaskError, type Task} from './task.ts';
|
|
6
6
|
import {resolve_gro_module_path, spawn_with_loader} from './gro_helpers.ts';
|
|
7
|
-
import {serialize_args} from './args.ts';
|
|
7
|
+
import {serialize_args, to_implicit_forwarded_args} from './args.ts';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Runs a TypeScript file with Gro's loader, forwarding all args to the script.
|
|
@@ -40,18 +40,22 @@ export const task: Task<Args> = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
if (!existsSync(path)) {
|
|
43
|
-
throw new
|
|
43
|
+
throw new TaskError('Cannot find file to run at path: ' + path);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
//
|
|
47
|
-
|
|
46
|
+
// Get args after `--` without requiring a command name.
|
|
47
|
+
// This allows `gro run script.ts -- --help` to pass --help to the script.
|
|
48
|
+
const implicit_args = to_implicit_forwarded_args();
|
|
49
|
+
|
|
50
|
+
// Reconstruct argv: positional args + explicit named args + implicit args after --
|
|
51
|
+
const named_argv = serialize_args({...forwarded_args, ...implicit_args});
|
|
48
52
|
const full_argv = [...positional_argv, ...named_argv];
|
|
49
53
|
|
|
50
54
|
const loader_path = resolve_gro_module_path('loader.js');
|
|
51
55
|
|
|
52
56
|
const spawned = await spawn_with_loader(loader_path, path, full_argv);
|
|
53
57
|
if (!spawned.ok) {
|
|
54
|
-
throw new
|
|
58
|
+
throw new TaskError(`\`gro run ${path}\` failed with exit code ${spawned.code}`);
|
|
55
59
|
}
|
|
56
60
|
},
|
|
57
61
|
};
|