@ryanatkn/gro 0.141.0 → 0.142.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/changeset.task.d.ts.map +1 -1
- package/dist/changeset.task.js +2 -2
- package/dist/filer.d.ts +7 -0
- package/dist/filer.d.ts.map +1 -1
- package/dist/filer.js +28 -29
- package/dist/gro_config.d.ts +5 -0
- package/dist/gro_config.d.ts.map +1 -1
- package/dist/gro_config.js +3 -1
- package/dist/gro_plugin_sveltekit_library.js +4 -4
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +22 -16
- package/dist/moss_helpers.d.ts.map +1 -1
- package/dist/moss_helpers.js +2 -1
- package/dist/package.d.ts +326 -164
- package/dist/package.d.ts.map +1 -1
- package/dist/package.js +15 -15
- package/dist/package_json.d.ts +9 -6
- package/dist/package_json.d.ts.map +1 -1
- package/dist/package_json.js +19 -4
- package/dist/parse_imports.d.ts.map +1 -1
- package/dist/parse_imports.js +4 -2
- package/dist/publish.task.d.ts.map +1 -1
- package/dist/publish.task.js +3 -8
- package/dist/reinstall.task.js +4 -4
- package/dist/resolve_node_specifier.d.ts +7 -1
- package/dist/resolve_node_specifier.d.ts.map +1 -1
- package/dist/resolve_node_specifier.js +77 -13
- package/dist/resolve_specifier.d.ts +2 -6
- package/dist/resolve_specifier.d.ts.map +1 -1
- package/dist/resolve_specifier.js +2 -6
- package/dist/src_json.d.ts +39 -3
- package/dist/src_json.d.ts.map +1 -1
- package/dist/sveltekit_config.d.ts +1 -1
- package/dist/sveltekit_config.d.ts.map +1 -1
- package/dist/sync.task.js +1 -1
- package/dist/upgrade.task.d.ts.map +1 -1
- package/dist/upgrade.task.js +4 -2
- package/dist/watch_dir.d.ts.map +1 -1
- package/dist/watch_dir.js +5 -5
- package/package.json +14 -14
- package/src/lib/changeset.task.ts +2 -1
- package/src/lib/filer.ts +37 -27
- package/src/lib/gro_config.ts +8 -0
- package/src/lib/gro_plugin_sveltekit_library.ts +4 -4
- package/src/lib/loader.ts +24 -16
- package/src/lib/moss_helpers.ts +2 -1
- package/src/lib/package.ts +15 -15
- package/src/lib/package_json.ts +21 -4
- package/src/lib/parse_imports.ts +4 -2
- package/src/lib/publish.task.ts +3 -9
- package/src/lib/reinstall.task.ts +4 -4
- package/src/lib/resolve_node_specifier.ts +99 -17
- package/src/lib/resolve_specifier.ts +2 -6
- package/src/lib/sveltekit_config.ts +1 -1
- package/src/lib/sync.task.ts +1 -1
- package/src/lib/upgrade.task.ts +4 -2
- package/src/lib/watch_dir.ts +6 -6
package/dist/watch_dir.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { watch } from 'chokidar';
|
|
2
2
|
import { relative } from 'node:path';
|
|
3
3
|
import { statSync } from 'node:fs';
|
|
4
|
+
import { create_deferred } from '@ryanatkn/belt/async.js';
|
|
4
5
|
/**
|
|
5
6
|
* Watch for changes on the filesystem using chokidar.
|
|
6
7
|
*/
|
|
@@ -10,9 +11,8 @@ export const watch_dir = ({ dir, on_change, filter, absolute = true, chokidar, }
|
|
|
10
11
|
return {
|
|
11
12
|
init: async () => {
|
|
12
13
|
if (initing)
|
|
13
|
-
return initing;
|
|
14
|
-
|
|
15
|
-
initing = new Promise((r) => (resolve = r)); // TODO `create_deferred`?// cwd: chokidar?.cwd ?? process.cwd()
|
|
14
|
+
return initing.promise;
|
|
15
|
+
initing = create_deferred();
|
|
16
16
|
watcher = watch(dir, { ...chokidar });
|
|
17
17
|
watcher.on('add', (path) => {
|
|
18
18
|
const final_path = absolute ? path : relative(dir, path);
|
|
@@ -46,8 +46,8 @@ export const watch_dir = ({ dir, on_change, filter, absolute = true, chokidar, }
|
|
|
46
46
|
on_change({ type: 'delete', path: final_path, is_directory: true });
|
|
47
47
|
});
|
|
48
48
|
// wait until ready
|
|
49
|
-
watcher.once('ready', () => resolve());
|
|
50
|
-
await initing;
|
|
49
|
+
watcher.once('ready', () => initing?.resolve());
|
|
50
|
+
await initing.promise;
|
|
51
51
|
},
|
|
52
52
|
close: async () => {
|
|
53
53
|
initing = undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryanatkn/gro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.142.0",
|
|
4
4
|
"description": "task runner and toolkit extending SvelteKit",
|
|
5
5
|
"motto": "generate, run, optimize",
|
|
6
6
|
"glyph": "🌰",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"prettier": "^3.3.3",
|
|
59
59
|
"prettier-plugin-svelte": "^3.2.7",
|
|
60
60
|
"ts-morph": "^24.0.0",
|
|
61
|
-
"tslib": "^2.
|
|
61
|
+
"tslib": "^2.8.0",
|
|
62
62
|
"zod": "^3.23.8"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
@@ -69,21 +69,21 @@
|
|
|
69
69
|
"@changesets/changelog-git": "^0.2.0",
|
|
70
70
|
"@changesets/types": "^6.0.0",
|
|
71
71
|
"@ryanatkn/eslint-config": "^0.5.5",
|
|
72
|
-
"@ryanatkn/fuz": "^0.129.
|
|
73
|
-
"@ryanatkn/moss": "^0.18.
|
|
74
|
-
"@sveltejs/adapter-static": "^3.0.
|
|
75
|
-
"@sveltejs/kit": "^2.
|
|
76
|
-
"@sveltejs/package": "^2.3.
|
|
77
|
-
"@sveltejs/vite-plugin-svelte": "^4.0.0
|
|
72
|
+
"@ryanatkn/fuz": "^0.129.5",
|
|
73
|
+
"@ryanatkn/moss": "^0.18.2",
|
|
74
|
+
"@sveltejs/adapter-static": "^3.0.6",
|
|
75
|
+
"@sveltejs/kit": "^2.7.3",
|
|
76
|
+
"@sveltejs/package": "^2.3.7",
|
|
77
|
+
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
|
78
78
|
"@types/fs-extra": "^11.0.4",
|
|
79
|
-
"@types/node": "^22.
|
|
79
|
+
"@types/node": "^22.8.1",
|
|
80
80
|
"esbuild": "^0.21.5",
|
|
81
|
-
"eslint": "^9.
|
|
82
|
-
"eslint-plugin-svelte": "^2.
|
|
83
|
-
"svelte": "^5.
|
|
84
|
-
"svelte-check": "^4.0.
|
|
81
|
+
"eslint": "^9.13.0",
|
|
82
|
+
"eslint-plugin-svelte": "^2.46.0",
|
|
83
|
+
"svelte": "^5.1.3",
|
|
84
|
+
"svelte-check": "^4.0.5",
|
|
85
85
|
"typescript": "^5.6.3",
|
|
86
|
-
"typescript-eslint": "^8.
|
|
86
|
+
"typescript-eslint": "^8.11.0",
|
|
87
87
|
"uvu": "^0.5.6"
|
|
88
88
|
},
|
|
89
89
|
"prettier": {
|
|
@@ -63,6 +63,7 @@ export const task: Task<Args> = {
|
|
|
63
63
|
args: {_, minor, major, dir, access: access_arg, changelog, dep, origin, changeset_cli},
|
|
64
64
|
log,
|
|
65
65
|
sveltekit_config,
|
|
66
|
+
config,
|
|
66
67
|
} = ctx;
|
|
67
68
|
|
|
68
69
|
const message = _.join(' ');
|
|
@@ -114,7 +115,7 @@ export const task: Task<Args> = {
|
|
|
114
115
|
await spawn('git', ['add', dir]);
|
|
115
116
|
|
|
116
117
|
if (dep) {
|
|
117
|
-
await spawn(
|
|
118
|
+
await spawn(config.pm_cli, ['i', '-D', changelog]);
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
package/src/lib/filer.ts
CHANGED
|
@@ -18,6 +18,8 @@ import {resolve_specifier} from './resolve_specifier.js';
|
|
|
18
18
|
import {default_sveltekit_config} from './sveltekit_config.js';
|
|
19
19
|
import {map_sveltekit_aliases} from './sveltekit_helpers.js';
|
|
20
20
|
import {Unreachable_Error} from '@ryanatkn/belt/error.js';
|
|
21
|
+
import {resolve_node_specifier} from './resolve_node_specifier.js';
|
|
22
|
+
import type {Package_Json} from './package_json.js';
|
|
21
23
|
// TODO see below
|
|
22
24
|
// import {resolve_node_specifier} from './resolve_node_specifier.js';
|
|
23
25
|
|
|
@@ -31,6 +33,11 @@ export interface Source_File {
|
|
|
31
33
|
* We create the file in memory to track its dependents regardless of its existence on disk.
|
|
32
34
|
*/
|
|
33
35
|
contents: string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Is the source file outside of the `root_dir` or excluded by `watch_dir_options.filter`?
|
|
38
|
+
*/
|
|
39
|
+
external: boolean;
|
|
40
|
+
ctime: number | null;
|
|
34
41
|
mtime: number | null;
|
|
35
42
|
dependents: Map<Path_Id, Source_File>;
|
|
36
43
|
dependencies: Map<Path_Id, Source_File>;
|
|
@@ -43,6 +50,7 @@ export type On_Filer_Change = (change: Watcher_Change, source_file: Source_File)
|
|
|
43
50
|
export interface Options {
|
|
44
51
|
watch_dir?: typeof watch_dir;
|
|
45
52
|
watch_dir_options?: Partial<Omit_Strict<Watch_Dir_Options, 'on_change'>>;
|
|
53
|
+
package_json_cache?: Record<string, Package_Json>;
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
export class Filer {
|
|
@@ -53,10 +61,13 @@ export class Filer {
|
|
|
53
61
|
#watch_dir: typeof watch_dir;
|
|
54
62
|
#watch_dir_options: Partial<Watch_Dir_Options>;
|
|
55
63
|
|
|
64
|
+
#package_json_cache: Record<string, Package_Json>;
|
|
65
|
+
|
|
56
66
|
constructor(options: Options = EMPTY_OBJECT) {
|
|
57
67
|
this.#watch_dir = options.watch_dir ?? watch_dir;
|
|
58
68
|
this.#watch_dir_options = options.watch_dir_options ?? EMPTY_OBJECT;
|
|
59
69
|
this.root_dir = resolve(options.watch_dir_options?.dir ?? paths.source);
|
|
70
|
+
this.#package_json_cache = options.package_json_cache ?? {};
|
|
60
71
|
}
|
|
61
72
|
|
|
62
73
|
#watching: Watch_Node_Fs | undefined;
|
|
@@ -74,11 +85,17 @@ export class Filer {
|
|
|
74
85
|
const file: Source_File = {
|
|
75
86
|
id,
|
|
76
87
|
contents: null,
|
|
88
|
+
external: this.#is_external(id), // TODO maybe filter externals by default? the user needs to configure the filer then
|
|
89
|
+
ctime: null,
|
|
77
90
|
mtime: null,
|
|
78
91
|
dependents: new Map(),
|
|
79
92
|
dependencies: new Map(),
|
|
80
93
|
};
|
|
81
94
|
this.files.set(id, file);
|
|
95
|
+
// TODO this may need to be batched/deferred
|
|
96
|
+
if (file.external) {
|
|
97
|
+
this.#on_change({type: 'add', path: file.id, is_directory: false});
|
|
98
|
+
}
|
|
82
99
|
return file;
|
|
83
100
|
};
|
|
84
101
|
|
|
@@ -86,8 +103,7 @@ export class Filer {
|
|
|
86
103
|
const file = this.get_or_create(id);
|
|
87
104
|
|
|
88
105
|
const stats = existsSync(id) ? statSync(id) : null;
|
|
89
|
-
|
|
90
|
-
// const mtime_changed = mtime_prev !== (stats?.mtimeMs ?? null);
|
|
106
|
+
file.ctime = stats?.ctimeMs ?? null;
|
|
91
107
|
file.mtime = stats?.mtimeMs ?? null;
|
|
92
108
|
|
|
93
109
|
const new_contents = stats ? readFileSync(id, 'utf8') : null;
|
|
@@ -109,36 +125,25 @@ export class Filer {
|
|
|
109
125
|
const path = map_sveltekit_aliases(specifier, aliases);
|
|
110
126
|
|
|
111
127
|
// The specifier `path` has now been mapped to its final form, so we can inspect it.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
128
|
+
const resolved =
|
|
129
|
+
path[0] === '.' || path[0] === '/'
|
|
130
|
+
? resolve_specifier(path, dir)
|
|
131
|
+
: resolve_node_specifier(path, undefined, file.id, this.#package_json_cache, false);
|
|
132
|
+
if (!resolved) continue; // ignore any missing imports like Node identifiers
|
|
133
|
+
const {path_id} = resolved;
|
|
134
|
+
dependencies_removed.delete(path_id);
|
|
135
|
+
if (!dependencies_before.has(path_id)) {
|
|
136
|
+
const d = this.get_or_create(path_id);
|
|
137
|
+
file.dependencies.set(d.id, d);
|
|
138
|
+
d.dependents.set(file.id, file);
|
|
120
139
|
}
|
|
121
|
-
// TODO this doesn't work
|
|
122
|
-
// const resolved =
|
|
123
|
-
// path[0] === '.' || path[0] === '/'
|
|
124
|
-
// ? resolve_specifier(path, dir)
|
|
125
|
-
// : resolve_node_specifier(path, dir);
|
|
126
|
-
// const {path_id} = resolved;
|
|
127
|
-
// dependencies_removed.delete(path_id);
|
|
128
|
-
// if (!dependencies_before.has(path_id)) {
|
|
129
|
-
// const d = this.get_or_create(path_id);
|
|
130
|
-
// file.dependencies.set(d.id, d);
|
|
131
|
-
// d.dependents.set(file.id, file);
|
|
132
|
-
// }
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
// update any removed dependencies
|
|
136
143
|
for (const dependency_removed of dependencies_removed) {
|
|
137
|
-
|
|
138
|
-
if (!deleted1) throw Error('expected to delete1 ' + file.id); // TODO @many delete if correct
|
|
144
|
+
file.dependencies.delete(dependency_removed);
|
|
139
145
|
const dependency_removed_file = this.get_or_create(dependency_removed);
|
|
140
|
-
|
|
141
|
-
if (!deleted2) throw Error('expected to delete2 ' + file.id); // TODO @many delete if correct
|
|
146
|
+
dependency_removed_file.dependents.delete(file.id);
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
return file;
|
|
@@ -203,7 +208,7 @@ export class Filer {
|
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
#on_change: Watcher_Change_Callback = (change) => {
|
|
206
|
-
if (change.is_directory) return;
|
|
211
|
+
if (change.is_directory) return; // TODO manage directories?
|
|
207
212
|
let source_file: Source_File | null;
|
|
208
213
|
switch (change.type) {
|
|
209
214
|
case 'add':
|
|
@@ -236,4 +241,9 @@ export class Filer {
|
|
|
236
241
|
this.#watching = undefined;
|
|
237
242
|
}
|
|
238
243
|
}
|
|
244
|
+
|
|
245
|
+
#is_external(id: string): boolean {
|
|
246
|
+
const {filter} = this.#watch_dir_options;
|
|
247
|
+
return !id.startsWith(this.root_dir + '/') || (!!filter && !filter(id, false));
|
|
248
|
+
}
|
|
239
249
|
}
|
package/src/lib/gro_config.ts
CHANGED
|
@@ -40,6 +40,10 @@ export interface Gro_Config {
|
|
|
40
40
|
* directories and files are included if they pass all of these filters.
|
|
41
41
|
*/
|
|
42
42
|
search_filters: Path_Filter[];
|
|
43
|
+
/**
|
|
44
|
+
* The CLI to use that's compatible with `npm install` and `npm link`. Defaults to `'npm'`.
|
|
45
|
+
*/
|
|
46
|
+
pm_cli: string;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
/**
|
|
@@ -52,6 +56,7 @@ export interface Raw_Gro_Config {
|
|
|
52
56
|
map_package_json?: Map_Package_Json | null;
|
|
53
57
|
task_root_dirs?: string[];
|
|
54
58
|
search_filters?: Path_Filter | Path_Filter[] | null;
|
|
59
|
+
pm_cli?: string;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
export type Create_Gro_Config = (
|
|
@@ -68,6 +73,7 @@ export const create_empty_gro_config = (): Gro_Config => ({
|
|
|
68
73
|
IS_THIS_GRO ? null : GRO_DIST_DIR,
|
|
69
74
|
].filter((v) => v !== null),
|
|
70
75
|
search_filters: [(id) => !DEFAULT_SEARCH_EXCLUDER.test(id)],
|
|
76
|
+
pm_cli: 'npm',
|
|
71
77
|
});
|
|
72
78
|
|
|
73
79
|
/**
|
|
@@ -112,6 +118,7 @@ export const normalize_gro_config = (raw_config: Raw_Gro_Config): Gro_Config =>
|
|
|
112
118
|
map_package_json = empty_config.map_package_json,
|
|
113
119
|
task_root_dirs = empty_config.task_root_dirs,
|
|
114
120
|
search_filters = empty_config.search_filters,
|
|
121
|
+
pm_cli = empty_config.pm_cli,
|
|
115
122
|
} = raw_config;
|
|
116
123
|
return {
|
|
117
124
|
plugins,
|
|
@@ -122,6 +129,7 @@ export const normalize_gro_config = (raw_config: Raw_Gro_Config): Gro_Config =>
|
|
|
122
129
|
: search_filters
|
|
123
130
|
? [search_filters]
|
|
124
131
|
: [],
|
|
132
|
+
pm_cli,
|
|
125
133
|
};
|
|
126
134
|
};
|
|
127
135
|
|
|
@@ -33,12 +33,12 @@ export const gro_plugin_sveltekit_library = ({
|
|
|
33
33
|
await run_svelte_package(svelte_package_options, svelte_package_cli, log);
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
-
adapt: async ({log, timings}) => {
|
|
36
|
+
adapt: async ({log, timings, config}) => {
|
|
37
37
|
const package_json = load_package_json();
|
|
38
38
|
|
|
39
39
|
// `npm link`
|
|
40
40
|
if (package_json.bin) {
|
|
41
|
-
const
|
|
41
|
+
const timing_to_link = timings.start(`${config.pm_cli} link`);
|
|
42
42
|
await Promise.all(
|
|
43
43
|
Object.values(package_json.bin).map(async (bin_path) => {
|
|
44
44
|
const chmod_result = await spawn('chmod', ['+x', bin_path]);
|
|
@@ -47,11 +47,11 @@ export const gro_plugin_sveltekit_library = ({
|
|
|
47
47
|
}),
|
|
48
48
|
);
|
|
49
49
|
log.info(`linking`);
|
|
50
|
-
const link_result = await spawn(
|
|
50
|
+
const link_result = await spawn(config.pm_cli, ['link', '-f']); // TODO don't use `-f` unless necessary or at all?
|
|
51
51
|
if (!link_result.ok) {
|
|
52
52
|
throw new Task_Error(`Failed to link. ${print_spawn_result(link_result)}`);
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
timing_to_link();
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
};
|
package/src/lib/loader.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from './sveltekit_shim_app.js';
|
|
17
17
|
import {default_sveltekit_config} from './sveltekit_config.js';
|
|
18
18
|
import {SVELTE_MATCHER, SVELTE_RUNES_MATCHER} from './svelte_helpers.js';
|
|
19
|
-
import {paths} from './paths.js';
|
|
19
|
+
import {IS_THIS_GRO, paths} from './paths.js';
|
|
20
20
|
import {JSON_MATCHER, NODE_MODULES_DIRNAME, TS_MATCHER} from './path_constants.js';
|
|
21
21
|
import {to_define_import_meta_env, default_ts_transform_options} from './esbuild_helpers.js';
|
|
22
22
|
import {resolve_specifier} from './resolve_specifier.js';
|
|
@@ -173,51 +173,59 @@ export const load: LoadHook = async (url, context, nextLoad) => {
|
|
|
173
173
|
};
|
|
174
174
|
|
|
175
175
|
export const resolve: ResolveHook = async (specifier, context, nextResolve) => {
|
|
176
|
+
let s = specifier;
|
|
177
|
+
|
|
178
|
+
// Support SvelteKit `$env` imports
|
|
176
179
|
if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
s === '$env/static/public' ||
|
|
181
|
+
s === '$env/static/private' ||
|
|
182
|
+
s === '$env/dynamic/public' ||
|
|
183
|
+
s === '$env/dynamic/private'
|
|
181
184
|
) {
|
|
182
185
|
// The returned `url` is validated before `load` is called,
|
|
183
186
|
// so we need a slightly roundabout strategy to pass through the specifier for virtual files.
|
|
184
187
|
return {
|
|
185
|
-
url: pathToFileURL(join(dir, 'src/lib',
|
|
188
|
+
url: pathToFileURL(join(dir, 'src/lib', s)).href,
|
|
186
189
|
format: 'module',
|
|
187
190
|
shortCircuit: true,
|
|
188
191
|
};
|
|
189
192
|
}
|
|
190
193
|
|
|
194
|
+
// Special case for Gro's dependencies that import into Gro.
|
|
195
|
+
// Without this, we'd need to add a dev dep to Gro for Gro, which causes problems.
|
|
196
|
+
if (IS_THIS_GRO && s.startsWith('@ryanatkn/gro')) {
|
|
197
|
+
s = join(dir, 'dist', s.substring(13));
|
|
198
|
+
}
|
|
199
|
+
|
|
191
200
|
const parent_url = context.parentURL;
|
|
192
201
|
if (!parent_url || NODE_MODULES_MATCHER.test(parent_url)) {
|
|
193
|
-
return nextResolve(
|
|
202
|
+
return nextResolve(s, context);
|
|
194
203
|
}
|
|
195
204
|
|
|
196
|
-
const shimmed = sveltekit_shim_app_specifiers.get(
|
|
205
|
+
const shimmed = sveltekit_shim_app_specifiers.get(s);
|
|
197
206
|
if (shimmed !== undefined) {
|
|
198
207
|
return nextResolve(shimmed, context);
|
|
199
208
|
}
|
|
200
209
|
|
|
201
|
-
|
|
210
|
+
s = map_sveltekit_aliases(s, aliases);
|
|
202
211
|
|
|
203
|
-
// The specifier
|
|
204
|
-
if (
|
|
212
|
+
// The specifier has now been mapped to its final form, so we can inspect it.
|
|
213
|
+
if (s[0] !== '.' && s[0] !== '/') {
|
|
205
214
|
// Resolve to `node_modules`.
|
|
206
|
-
if (SVELTE_MATCHER.test(
|
|
215
|
+
if (SVELTE_MATCHER.test(s) || JSON_MATCHER.test(s)) {
|
|
207
216
|
// Match the behavior of Vite and esbuild for Svelte and JSON imports.
|
|
208
|
-
//
|
|
209
|
-
const resolved = resolve_node_specifier(path, dir, parent_url, package_json_cache);
|
|
217
|
+
const resolved = resolve_node_specifier(s, dir, parent_url, package_json_cache)!; // `node:` specifiers shouldn't reach this point, so the assertion is safe
|
|
210
218
|
return {
|
|
211
219
|
url: pathToFileURL(resolved.path_id_with_querystring).href,
|
|
212
220
|
format: 'module',
|
|
213
221
|
shortCircuit: true,
|
|
214
222
|
};
|
|
215
223
|
} else {
|
|
216
|
-
return nextResolve(
|
|
224
|
+
return nextResolve(s, context);
|
|
217
225
|
}
|
|
218
226
|
}
|
|
219
227
|
|
|
220
|
-
const resolved = resolve_specifier(
|
|
228
|
+
const resolved = resolve_specifier(s, dirname(fileURLToPath(parent_url)));
|
|
221
229
|
|
|
222
230
|
return {
|
|
223
231
|
url: pathToFileURL(resolved.path_id_with_querystring).href,
|
package/src/lib/moss_helpers.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {existsSync} from 'node:fs';
|
|
|
3
3
|
import {resolve} from 'node:path';
|
|
4
4
|
|
|
5
5
|
import {has_dep, type Package_Json} from './package_json.js';
|
|
6
|
+
import {NODE_MODULES_DIRNAME} from './path_constants.js';
|
|
6
7
|
|
|
7
8
|
export const MOSS_PACKAGE_DEP_NAME = '@ryanatkn/moss';
|
|
8
9
|
|
|
@@ -10,7 +11,7 @@ export const MOSS_PACKAGE_DEP_NAME = '@ryanatkn/moss';
|
|
|
10
11
|
export const load_moss_plugin = async (
|
|
11
12
|
package_json?: Package_Json,
|
|
12
13
|
dep_name = MOSS_PACKAGE_DEP_NAME,
|
|
13
|
-
plugin_path =
|
|
14
|
+
plugin_path = `${NODE_MODULES_DIRNAME}/${dep_name}/dist/gro_plugin_moss.js`, // TODO maybe lookup from its `package_json.exports`? kinda unnecessary
|
|
14
15
|
local_plugin_path = 'src/lib/gro_plugin_moss.ts',
|
|
15
16
|
): Promise<Result<{gro_plugin_moss: any}, {message: string}>> => {
|
|
16
17
|
if (!has_dep(dep_name, package_json)) {
|
package/src/lib/package.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type {Src_Json} from './src_json.js';
|
|
|
5
5
|
|
|
6
6
|
export const package_json = {
|
|
7
7
|
name: '@ryanatkn/gro',
|
|
8
|
-
version: '0.
|
|
8
|
+
version: '0.142.0',
|
|
9
9
|
description: 'task runner and toolkit extending SvelteKit',
|
|
10
10
|
motto: 'generate, run, optimize',
|
|
11
11
|
glyph: '🌰',
|
|
@@ -53,7 +53,7 @@ export const package_json = {
|
|
|
53
53
|
prettier: '^3.3.3',
|
|
54
54
|
'prettier-plugin-svelte': '^3.2.7',
|
|
55
55
|
'ts-morph': '^24.0.0',
|
|
56
|
-
tslib: '^2.
|
|
56
|
+
tslib: '^2.8.0',
|
|
57
57
|
zod: '^3.23.8',
|
|
58
58
|
},
|
|
59
59
|
peerDependencies: {esbuild: '^0.21.0', svelte: '^5.0.0-next.0'},
|
|
@@ -61,21 +61,21 @@ export const package_json = {
|
|
|
61
61
|
'@changesets/changelog-git': '^0.2.0',
|
|
62
62
|
'@changesets/types': '^6.0.0',
|
|
63
63
|
'@ryanatkn/eslint-config': '^0.5.5',
|
|
64
|
-
'@ryanatkn/fuz': '^0.129.
|
|
65
|
-
'@ryanatkn/moss': '^0.18.
|
|
66
|
-
'@sveltejs/adapter-static': '^3.0.
|
|
67
|
-
'@sveltejs/kit': '^2.
|
|
68
|
-
'@sveltejs/package': '^2.3.
|
|
69
|
-
'@sveltejs/vite-plugin-svelte': '^4.0.0
|
|
64
|
+
'@ryanatkn/fuz': '^0.129.5',
|
|
65
|
+
'@ryanatkn/moss': '^0.18.2',
|
|
66
|
+
'@sveltejs/adapter-static': '^3.0.6',
|
|
67
|
+
'@sveltejs/kit': '^2.7.3',
|
|
68
|
+
'@sveltejs/package': '^2.3.7',
|
|
69
|
+
'@sveltejs/vite-plugin-svelte': '^4.0.0',
|
|
70
70
|
'@types/fs-extra': '^11.0.4',
|
|
71
|
-
'@types/node': '^22.
|
|
71
|
+
'@types/node': '^22.8.1',
|
|
72
72
|
esbuild: '^0.21.5',
|
|
73
|
-
eslint: '^9.
|
|
74
|
-
'eslint-plugin-svelte': '^2.
|
|
75
|
-
svelte: '^5.
|
|
76
|
-
'svelte-check': '^4.0.
|
|
73
|
+
eslint: '^9.13.0',
|
|
74
|
+
'eslint-plugin-svelte': '^2.46.0',
|
|
75
|
+
svelte: '^5.1.3',
|
|
76
|
+
'svelte-check': '^4.0.5',
|
|
77
77
|
typescript: '^5.6.3',
|
|
78
|
-
'typescript-eslint': '^8.
|
|
78
|
+
'typescript-eslint': '^8.11.0',
|
|
79
79
|
uvu: '^0.5.6',
|
|
80
80
|
},
|
|
81
81
|
prettier: {
|
|
@@ -270,7 +270,7 @@ export const package_json = {
|
|
|
270
270
|
|
|
271
271
|
export const src_json = {
|
|
272
272
|
name: '@ryanatkn/gro',
|
|
273
|
-
version: '0.
|
|
273
|
+
version: '0.142.0',
|
|
274
274
|
modules: {
|
|
275
275
|
'.': {
|
|
276
276
|
path: 'index.ts',
|
package/src/lib/package_json.ts
CHANGED
|
@@ -21,7 +21,7 @@ export const Email = z.string();
|
|
|
21
21
|
export type Email = Flavored<z.infer<typeof Email>, 'Email'>;
|
|
22
22
|
|
|
23
23
|
// TODO move this where?
|
|
24
|
-
export const transform_empty_object_to_undefined = (val:
|
|
24
|
+
export const transform_empty_object_to_undefined = <T>(val: T): T | undefined => {
|
|
25
25
|
if (val && Object.keys(val).length === 0) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
@@ -63,8 +63,19 @@ export const Package_Json_Funding = z.union([
|
|
|
63
63
|
]);
|
|
64
64
|
export type Package_Json_Funding = z.infer<typeof Package_Json_Funding>;
|
|
65
65
|
|
|
66
|
+
// exports: {
|
|
67
|
+
// './': './index.js',
|
|
68
|
+
// './record': {default: './record.js'},
|
|
69
|
+
// './export_condition': {default: {development: './ec1', default: './ec2.js'}},
|
|
70
|
+
// }
|
|
66
71
|
export const Package_Json_Exports = z.record(
|
|
67
|
-
z
|
|
72
|
+
z
|
|
73
|
+
.union([
|
|
74
|
+
z.string(),
|
|
75
|
+
z.record(z.string().optional()),
|
|
76
|
+
z.record(z.record(z.string().optional()).optional()),
|
|
77
|
+
])
|
|
78
|
+
.optional(),
|
|
68
79
|
);
|
|
69
80
|
export type Package_Json_Exports = z.infer<typeof Package_Json_Exports>;
|
|
70
81
|
|
|
@@ -131,6 +142,7 @@ export const Package_Json = z
|
|
|
131
142
|
bin: z.record(z.string()).optional(),
|
|
132
143
|
sideEffects: z.array(z.string()).optional(),
|
|
133
144
|
files: z.array(z.string()).optional(),
|
|
145
|
+
main: z.string().optional(),
|
|
134
146
|
exports: Package_Json_Exports.transform(transform_empty_object_to_undefined).optional(),
|
|
135
147
|
})
|
|
136
148
|
.passthrough();
|
|
@@ -145,6 +157,7 @@ export const EMPTY_PACKAGE_JSON: Package_Json = {name: '', version: ''};
|
|
|
145
157
|
export const load_package_json = (
|
|
146
158
|
dir = IS_THIS_GRO ? gro_paths.root : paths.root,
|
|
147
159
|
cache?: Record<string, Package_Json>,
|
|
160
|
+
parse = true, // TODO pass `false` here in more places, especially anything perf-sensitive like work on startup
|
|
148
161
|
): Package_Json => {
|
|
149
162
|
let package_json: Package_Json;
|
|
150
163
|
if (cache && dir in cache) {
|
|
@@ -155,8 +168,12 @@ export const load_package_json = (
|
|
|
155
168
|
} catch (_err) {
|
|
156
169
|
return EMPTY_PACKAGE_JSON;
|
|
157
170
|
}
|
|
158
|
-
|
|
159
|
-
|
|
171
|
+
if (parse) {
|
|
172
|
+
package_json = parse_package_json(Package_Json, package_json);
|
|
173
|
+
}
|
|
174
|
+
if (cache) {
|
|
175
|
+
cache[dir] = package_json;
|
|
176
|
+
}
|
|
160
177
|
return package_json;
|
|
161
178
|
};
|
|
162
179
|
|
package/src/lib/parse_imports.ts
CHANGED
|
@@ -2,6 +2,8 @@ import {init, parse} from 'es-module-lexer';
|
|
|
2
2
|
import type {Flavored} from '@ryanatkn/belt/types.js';
|
|
3
3
|
|
|
4
4
|
import type {Path_Id} from './path.js';
|
|
5
|
+
import {SVELTE_MATCHER} from './svelte_helpers.js';
|
|
6
|
+
import {JS_MATCHER, TS_MATCHER} from './path_constants.js';
|
|
5
7
|
|
|
6
8
|
export const init_lexer = (): Promise<void> => init;
|
|
7
9
|
|
|
@@ -29,12 +31,12 @@ export const parse_imports = (
|
|
|
29
31
|
}
|
|
30
32
|
};
|
|
31
33
|
|
|
32
|
-
if (
|
|
34
|
+
if (SVELTE_MATCHER.test(id)) {
|
|
33
35
|
const matches = contents.matchAll(script_matcher);
|
|
34
36
|
for (const m of matches) {
|
|
35
37
|
parse_from(m[1]);
|
|
36
38
|
}
|
|
37
|
-
} else {
|
|
39
|
+
} else if (TS_MATCHER.test(id) || JS_MATCHER.test(id)) {
|
|
38
40
|
parse_from(contents);
|
|
39
41
|
}
|
|
40
42
|
|
package/src/lib/publish.task.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {existsSync} from 'node:fs';
|
|
|
6
6
|
import {Task_Error, type Task} from './task.js';
|
|
7
7
|
import {load_package_json, parse_repo_url} from './package_json.js';
|
|
8
8
|
import {find_cli, spawn_cli} from './cli.js';
|
|
9
|
-
import {IS_THIS_GRO} from './paths.js';
|
|
10
9
|
import {has_sveltekit_library} from './sveltekit_helpers.js';
|
|
11
10
|
import {update_changelog} from './changelog.js';
|
|
12
11
|
import {load_from_env} from './env.js';
|
|
@@ -84,11 +83,6 @@ export const task: Task<Args> = {
|
|
|
84
83
|
);
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
// TODO hacky, ensures Gro bootstraps itself
|
|
88
|
-
if (IS_THIS_GRO) {
|
|
89
|
-
await spawn('npm', ['run', 'build']);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
86
|
const changelog_exists = existsSync(changelog);
|
|
93
87
|
|
|
94
88
|
const found_changeset_cli = find_cli(changeset_cli);
|
|
@@ -139,9 +133,9 @@ export const task: Task<Args> = {
|
|
|
139
133
|
|
|
140
134
|
// This is the first line that alters the repo.
|
|
141
135
|
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
144
|
-
throw Error('
|
|
136
|
+
const changeset_ersion_result = await spawn_cli(found_changeset_cli, ['version'], log);
|
|
137
|
+
if (!changeset_ersion_result?.ok) {
|
|
138
|
+
throw Error('changeset version failed: no commits were made: see the error above');
|
|
145
139
|
}
|
|
146
140
|
|
|
147
141
|
if (!preserve_changelog) {
|
|
@@ -11,9 +11,9 @@ export type Args = z.infer<typeof Args>;
|
|
|
11
11
|
export const task: Task<Args> = {
|
|
12
12
|
summary: `refreshes ${LOCKFILE_FILENAME} with the latest and cleanest deps`,
|
|
13
13
|
Args,
|
|
14
|
-
run: async ({log}): Promise<void> => {
|
|
14
|
+
run: async ({log, config}): Promise<void> => {
|
|
15
15
|
log.info('running the initial npm install');
|
|
16
|
-
const initial_install_result = await spawn(
|
|
16
|
+
const initial_install_result = await spawn(config.pm_cli, ['i']);
|
|
17
17
|
if (!initial_install_result.ok) {
|
|
18
18
|
throw new Task_Error('Failed initial npm install');
|
|
19
19
|
}
|
|
@@ -23,7 +23,7 @@ export const task: Task<Args> = {
|
|
|
23
23
|
log.info(
|
|
24
24
|
`running npm install after deleting ${LOCKFILE_FILENAME} and ${NODE_MODULES_DIRNAME}, this can take a while...`,
|
|
25
25
|
);
|
|
26
|
-
const second_install_result = await spawn(
|
|
26
|
+
const second_install_result = await spawn(config.pm_cli, ['i']);
|
|
27
27
|
if (!second_install_result.ok) {
|
|
28
28
|
throw new Task_Error(
|
|
29
29
|
`Failed npm install after deleting ${LOCKFILE_FILENAME} and ${NODE_MODULES_DIRNAME}`,
|
|
@@ -34,7 +34,7 @@ export const task: Task<Args> = {
|
|
|
34
34
|
// like esbuild's many packages for each platform.
|
|
35
35
|
await rm(LOCKFILE_FILENAME);
|
|
36
36
|
log.info(`running npm install one last time to clean ${LOCKFILE_FILENAME}`);
|
|
37
|
-
const final_install_result = await spawn(
|
|
37
|
+
const final_install_result = await spawn(config.pm_cli, ['i']);
|
|
38
38
|
if (!final_install_result.ok) {
|
|
39
39
|
throw new Task_Error('Failed npm install');
|
|
40
40
|
}
|