@ryanatkn/gro 0.165.1 → 0.166.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/dev.task.d.ts.map +1 -1
- package/dist/dev.task.js +9 -1
- package/dist/filer.d.ts +2 -1
- package/dist/filer.d.ts.map +1 -1
- package/dist/filer.js +11 -1
- package/dist/gen.d.ts +13 -1
- package/dist/gen.d.ts.map +1 -1
- package/dist/gen.js +9 -1
- package/dist/gen.task.d.ts.map +1 -1
- package/dist/gen.task.js +0 -2
- package/dist/gen_helpers.d.ts +12 -0
- package/dist/gen_helpers.d.ts.map +1 -0
- package/dist/gen_helpers.js +91 -0
- package/dist/gro_plugin_gen.d.ts.map +1 -1
- package/dist/gro_plugin_gen.js +47 -23
- package/dist/package.d.ts.map +1 -1
- package/dist/package.js +15 -5
- package/dist/run_gen.d.ts.map +1 -1
- package/dist/run_gen.js +3 -3
- package/dist/watch_dir.d.ts.map +1 -1
- package/dist/watch_dir.js +2 -1
- package/package.json +3 -4
- package/src/lib/dev.task.ts +8 -1
- package/src/lib/filer.ts +16 -5
- package/src/lib/gen.task.ts +0 -2
- package/src/lib/gen.ts +32 -3
- package/src/lib/gen_helpers.ts +126 -0
- package/src/lib/gro_plugin_gen.ts +70 -28
- package/src/lib/package.ts +15 -5
- package/src/lib/run_gen.ts +3 -2
- package/src/lib/watch_dir.ts +3 -1
package/dist/dev.task.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dev.task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,aAAa,CAAC;AAGzD,eAAO,MAAM,IAAI;;;;;;kBAWf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;AAEnD,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"dev.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dev.task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,aAAa,CAAC;AAGzD,eAAO,MAAM,IAAI;;;;;;kBAWf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;AAEnD,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CA2B3B,CAAC"}
|
package/dist/dev.task.js
CHANGED
|
@@ -23,12 +23,20 @@ export const task = {
|
|
|
23
23
|
if (sync || install) {
|
|
24
24
|
if (!sync)
|
|
25
25
|
log.warn('sync is false but install is true, so ignoring the sync option');
|
|
26
|
-
await invoke_task('sync', { install });
|
|
26
|
+
await invoke_task('sync', { install, gen: !watch });
|
|
27
27
|
}
|
|
28
28
|
const plugins = await Plugins.create({ ...ctx, dev: true, watch });
|
|
29
29
|
await plugins.setup();
|
|
30
30
|
if (!watch) {
|
|
31
31
|
await plugins.teardown();
|
|
32
32
|
}
|
|
33
|
+
else {
|
|
34
|
+
// TODO maybe redesign for this API to be explicitly cancelable?
|
|
35
|
+
// Keep the task running indefinitely in watch mode.
|
|
36
|
+
// This prevents invoke_task from calling finish() and closing the filer.
|
|
37
|
+
await new Promise(() => {
|
|
38
|
+
// Never resolves - keeps filer and listeners alive.
|
|
39
|
+
});
|
|
40
|
+
}
|
|
33
41
|
},
|
|
34
42
|
};
|
package/dist/filer.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare class Filer {
|
|
|
19
19
|
get inited(): boolean;
|
|
20
20
|
get_by_id: (id: Path_Id) => Disknode | undefined;
|
|
21
21
|
get_or_create: (id: Path_Id) => Disknode;
|
|
22
|
+
filter(predicate: (disknode: Disknode) => boolean): Array<Disknode> | null;
|
|
22
23
|
/**
|
|
23
24
|
* Initialize the filer to populate files without watching.
|
|
24
25
|
* Safe to call multiple times - subsequent calls are no-ops.
|
|
@@ -28,5 +29,5 @@ export declare class Filer {
|
|
|
28
29
|
watch(listener: On_Filer_Change): Promise<() => void>;
|
|
29
30
|
close(): Promise<void>;
|
|
30
31
|
}
|
|
31
|
-
export declare const filter_dependents: (disknode: Disknode, get_by_id: (id: Path_Id) => Disknode | undefined, filter?: File_Filter, results?: Set<
|
|
32
|
+
export declare const filter_dependents: (disknode: Disknode, get_by_id: (id: Path_Id) => Disknode | undefined, filter?: File_Filter, results?: Set<Path_Id>, searched?: Set<Path_Id>, log?: Logger) => Set<Path_Id>;
|
|
32
33
|
//# sourceMappingURL=filer.d.ts.map
|
package/dist/filer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAIzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAEjE,OAAO,KAAK,EAAC,WAAW,EAAE,OAAO,EAAC,MAAM,WAAW,CAAC;AACpD,OAAO,EACN,SAAS,EAET,KAAK,cAAc,EACnB,KAAK,iBAAiB,EAEtB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAI5C,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEnF,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAG3B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAa;gBAYvC,OAAO,GAAE,aAA4B;IAUjD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,SAAS,GAAI,IAAI,OAAO,KAAG,QAAQ,GAAG,SAAS,CAE7C;IAEF,aAAa,GAAI,IAAI,OAAO,KAAG,QAAQ,CAkBrC;IAEF;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDrB,KAAK,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAiB3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAIzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AAEjE,OAAO,KAAK,EAAC,WAAW,EAAE,OAAO,EAAC,MAAM,WAAW,CAAC;AACpD,OAAO,EACN,SAAS,EAET,KAAK,cAAc,EACnB,KAAK,iBAAiB,EAEtB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAI5C,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEnF,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAG3B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAa;gBAYvC,OAAO,GAAE,aAA4B;IAUjD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,SAAS,GAAI,IAAI,OAAO,KAAG,QAAQ,GAAG,SAAS,CAE7C;IAEF,aAAa,GAAI,IAAI,OAAO,KAAG,QAAQ,CAkBrC;IAEF,MAAM,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI;IAU1E;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDrB,KAAK,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAiB3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAmLtB;AAGD,eAAO,MAAM,iBAAiB,GAC7B,UAAU,QAAQ,EAClB,WAAW,CAAC,EAAE,EAAE,OAAO,KAAK,QAAQ,GAAG,SAAS,EAChD,SAAS,WAAW,EACpB,UAAS,GAAG,CAAC,OAAO,CAAa,EACjC,WAAU,GAAG,CAAC,OAAO,CAAa,EAClC,MAAM,MAAM,KACV,GAAG,CAAC,OAAO,CAkBb,CAAC"}
|
package/dist/filer.js
CHANGED
|
@@ -59,6 +59,15 @@ export class Filer {
|
|
|
59
59
|
}
|
|
60
60
|
return file;
|
|
61
61
|
};
|
|
62
|
+
filter(predicate) {
|
|
63
|
+
let found = null;
|
|
64
|
+
for (const disknode of this.files.values()) {
|
|
65
|
+
if (predicate(disknode)) {
|
|
66
|
+
(found ??= []).push(disknode);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return found;
|
|
70
|
+
}
|
|
62
71
|
/**
|
|
63
72
|
* Initialize the filer to populate files without watching.
|
|
64
73
|
* Safe to call multiple times - subsequent calls are no-ops.
|
|
@@ -167,10 +176,11 @@ export class Filer {
|
|
|
167
176
|
#update(id) {
|
|
168
177
|
const file = this.get_or_create(id);
|
|
169
178
|
const stats = existsSync(id) ? statSync(id) : null;
|
|
179
|
+
const old_mtime = file.mtime;
|
|
170
180
|
file.ctime = stats?.ctimeMs ?? null;
|
|
171
181
|
file.mtime = stats?.mtimeMs ?? null;
|
|
172
182
|
const new_contents = stats ? readFileSync(id, 'utf8') : null; // TODO need to lazily load contents, probably turn `Disknode` into a class
|
|
173
|
-
if (file.contents === new_contents) {
|
|
183
|
+
if (file.mtime === old_mtime && file.contents === new_contents) {
|
|
174
184
|
return null;
|
|
175
185
|
}
|
|
176
186
|
file.contents = new_contents;
|
package/dist/gen.d.ts
CHANGED
|
@@ -21,7 +21,18 @@ export interface Gen_File {
|
|
|
21
21
|
origin_id: Path_Id;
|
|
22
22
|
format: boolean;
|
|
23
23
|
}
|
|
24
|
-
export type
|
|
24
|
+
export type Gen_Dependencies = 'all' | Gen_Dependencies_Config | Gen_Dependencies_Resolver;
|
|
25
|
+
export interface Gen_Dependencies_Config {
|
|
26
|
+
patterns?: Array<RegExp>;
|
|
27
|
+
files?: Array<Path_Id>;
|
|
28
|
+
}
|
|
29
|
+
export type Gen_Dependencies_Resolver = (ctx: Gen_Context) => Gen_Dependencies_Config | 'all' | Promise<Gen_Dependencies_Config | 'all'>;
|
|
30
|
+
export type Gen = Gen_Function | Gen_Config;
|
|
31
|
+
export type Gen_Function = (ctx: Gen_Context) => Raw_Gen_Result | Promise<Raw_Gen_Result>;
|
|
32
|
+
export interface Gen_Config {
|
|
33
|
+
generate: Gen_Function;
|
|
34
|
+
dependencies?: Gen_Dependencies;
|
|
35
|
+
}
|
|
25
36
|
export interface Gen_Context {
|
|
26
37
|
config: Gro_Config;
|
|
27
38
|
svelte_config: Parsed_Svelte_Config;
|
|
@@ -121,4 +132,5 @@ export type Load_Genfiles_Result = Result<{
|
|
|
121
132
|
export type Load_Genfiles_Failure = Load_Modules_Failure<Genfile_Module_Meta>;
|
|
122
133
|
export declare const load_genfiles: (found_genfiles: Found_Genfiles, timings?: Timings) => Promise<Load_Genfiles_Result>;
|
|
123
134
|
export declare const validate_gen_module: (mod: Record<string, any>) => mod is Genfile_Module;
|
|
135
|
+
export declare const normalize_gen_config: (gen: Gen) => Gen_Config;
|
|
124
136
|
//# sourceMappingURL=gen.d.ts.map
|
package/dist/gen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAGlD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AACrD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,2BAA2B,CAAC;AAKvD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAe,KAAK,oBAAoB,EAAE,KAAK,WAAW,EAAC,MAAM,cAAc,CAAC;AACvF,OAAO,EACN,UAAU,EAGV,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAE3C,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAC3C,eAAO,MAAM,gBAAgB,QAAoC,CAAC;AAElE,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,OAA0C,CAAC;AAEtF,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;CACvB;AACD,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen.ts"],"names":[],"mappings":"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"}
|
package/dist/gen.js
CHANGED
|
@@ -182,4 +182,12 @@ export const load_genfiles = async (found_genfiles, timings) => {
|
|
|
182
182
|
value: { modules: loaded_modules.modules, found_genfiles },
|
|
183
183
|
};
|
|
184
184
|
};
|
|
185
|
-
export const validate_gen_module = (mod) =>
|
|
185
|
+
export const validate_gen_module = (mod) => {
|
|
186
|
+
if (typeof mod.gen === 'function')
|
|
187
|
+
return true;
|
|
188
|
+
if (typeof mod.gen === 'object' && mod.gen !== null && typeof mod.gen.generate === 'function') {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
};
|
|
193
|
+
export const normalize_gen_config = (gen) => typeof gen === 'function' ? { generate: gen } : gen;
|
package/dist/gen.task.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gen.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen.task.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAa,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAgBhD,eAAO,MAAM,IAAI;;;;kBAaf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"gen.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen.task.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAa,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAgBhD,eAAO,MAAM,IAAI;;;;kBAaf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CAqG3B,CAAC"}
|
package/dist/gen.task.js
CHANGED
|
@@ -79,8 +79,6 @@ export const task = {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
else {
|
|
82
|
-
// write generated files to disk
|
|
83
|
-
log.info('writing generated files to disk');
|
|
84
82
|
const timing_to_output_results = timings.start('output results');
|
|
85
83
|
await write_gen_results(gen_results, analyzed_gen_results, log);
|
|
86
84
|
timing_to_output_results();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Logger } from '@ryanatkn/belt/log.js';
|
|
2
|
+
import type { Timings } from '@ryanatkn/belt/timings.js';
|
|
3
|
+
import type { Gro_Config } from './gro_config.ts';
|
|
4
|
+
import type { Filer } from './filer.ts';
|
|
5
|
+
import type { Invoke_Task } from './task.ts';
|
|
6
|
+
import { type Gen_Dependencies } from './gen.ts';
|
|
7
|
+
import type { Path_Id } from './path.ts';
|
|
8
|
+
/**
|
|
9
|
+
* Check if a file change should trigger a gen file.
|
|
10
|
+
*/
|
|
11
|
+
export declare const should_trigger_gen: (gen_file_id: Path_Id, changed_file_id: Path_Id, config: Gro_Config, filer: Filer, log: Logger, timings: Timings, invoke_task: Invoke_Task, dependencies_cache: Map<Path_Id, Gen_Dependencies | null>) => Promise<boolean>;
|
|
12
|
+
//# sourceMappingURL=gen_helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen_helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,2BAA2B,CAAC;AAEvD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAC3C,OAAO,EAIN,KAAK,gBAAgB,EACrB,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AAEvC;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC9B,aAAa,OAAO,EACpB,iBAAiB,OAAO,EACxB,QAAQ,UAAU,EAClB,OAAO,KAAK,EACZ,KAAK,MAAM,EACX,SAAS,OAAO,EAChB,aAAa,WAAW,EACxB,oBAAoB,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC,KACvD,OAAO,CAAC,OAAO,CA0CjB,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { pathToFileURL } from 'node:url';
|
|
10
|
+
import { resolve } from 'node:path';
|
|
11
|
+
import { normalize_gen_config, validate_gen_module, } from "./gen.js";
|
|
12
|
+
import { default_svelte_config } from "./svelte_config.js";
|
|
13
|
+
import { to_root_path } from "./paths.js";
|
|
14
|
+
/**
|
|
15
|
+
* Check if a file change should trigger a gen file.
|
|
16
|
+
*/
|
|
17
|
+
export const should_trigger_gen = async (gen_file_id, changed_file_id, config, filer, log, timings, invoke_task, dependencies_cache) => {
|
|
18
|
+
// Always trigger if the gen file itself changed
|
|
19
|
+
if (gen_file_id === changed_file_id) {
|
|
20
|
+
// Invalidate cache for this gen file
|
|
21
|
+
dependencies_cache.delete(gen_file_id);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
let dependencies;
|
|
25
|
+
if (!dependencies_cache.has(gen_file_id)) {
|
|
26
|
+
dependencies = await resolve_gen_dependencies(gen_file_id, config, filer, log, timings, invoke_task);
|
|
27
|
+
dependencies_cache.set(gen_file_id, dependencies);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
dependencies = dependencies_cache.get(gen_file_id);
|
|
31
|
+
}
|
|
32
|
+
if (!dependencies)
|
|
33
|
+
return false;
|
|
34
|
+
if (dependencies === 'all')
|
|
35
|
+
return true;
|
|
36
|
+
if (typeof dependencies !== 'function') {
|
|
37
|
+
if (dependencies.patterns) {
|
|
38
|
+
if (dependencies.patterns.some((p) => p.test(changed_file_id))) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (dependencies.files) {
|
|
43
|
+
if (dependencies.files.includes(changed_file_id)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Resolve dependencies for a gen file.
|
|
52
|
+
* Uses cache-busting to get fresh imports, allowing dependency
|
|
53
|
+
* declarations to update during watch mode without restart.
|
|
54
|
+
*/
|
|
55
|
+
const resolve_gen_dependencies = async (gen_file_id, config, filer, log, timings, invoke_task) => {
|
|
56
|
+
try {
|
|
57
|
+
const url = pathToFileURL(gen_file_id);
|
|
58
|
+
url.searchParams.set('t', Date.now().toString());
|
|
59
|
+
const module = await import(__rewriteRelativeImportExtension(url.href, true));
|
|
60
|
+
if (!validate_gen_module(module)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const gen_config = normalize_gen_config(module.gen);
|
|
64
|
+
if (!gen_config.dependencies) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
let dependencies = gen_config.dependencies;
|
|
68
|
+
if (typeof dependencies === 'function') {
|
|
69
|
+
const gen_ctx = {
|
|
70
|
+
config,
|
|
71
|
+
svelte_config: default_svelte_config,
|
|
72
|
+
filer,
|
|
73
|
+
log,
|
|
74
|
+
timings,
|
|
75
|
+
invoke_task,
|
|
76
|
+
origin_id: gen_file_id,
|
|
77
|
+
origin_path: to_root_path(gen_file_id),
|
|
78
|
+
};
|
|
79
|
+
dependencies = await dependencies(gen_ctx);
|
|
80
|
+
}
|
|
81
|
+
// Normalize file paths to absolute paths
|
|
82
|
+
if (dependencies !== 'all' && dependencies.files) {
|
|
83
|
+
dependencies.files = dependencies.files.map((f) => resolve(f));
|
|
84
|
+
}
|
|
85
|
+
return dependencies;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
log.error(`Failed to resolve dependencies for ${gen_file_id}:`, err);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gro_plugin_gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gro_plugin_gen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"gro_plugin_gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gro_plugin_gen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAcpC,MAAM,WAAW,SAAU,SAAQ,IAAI;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACtC,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,cAAc,GAAI,oDAI5B,sBAAqC,KAAG,MA2H1C,CAAC"}
|
package/dist/gro_plugin_gen.js
CHANGED
|
@@ -3,60 +3,81 @@ import { throttle } from '@ryanatkn/belt/throttle.js';
|
|
|
3
3
|
import { Unreachable_Error } from '@ryanatkn/belt/error.js';
|
|
4
4
|
import { paths } from "./paths.js";
|
|
5
5
|
import { find_genfiles, is_gen_path } from "./gen.js";
|
|
6
|
-
import { spawn_cli } from "./cli.js";
|
|
7
6
|
import { filter_dependents } from "./filer.js";
|
|
7
|
+
import { should_trigger_gen } from "./gen_helpers.js";
|
|
8
|
+
import { spawn_cli } from "./cli.js";
|
|
8
9
|
const FLUSH_DEBOUNCE_DELAY = 500;
|
|
10
|
+
// TODO is cache busting a good idea here to speed up and run in-process?
|
|
11
|
+
// await invoke_task('gen', {_: files, bust_cache: true});
|
|
12
|
+
const gen = (files = []) => spawn_cli('gro', ['gen', ...files]);
|
|
9
13
|
export const gro_plugin_gen = ({ input_paths = [paths.source], root_dirs = [paths.source], flush_debounce_delay = FLUSH_DEBOUNCE_DELAY, } = EMPTY_OBJECT) => {
|
|
10
|
-
let flushing_timeout;
|
|
11
14
|
const queued_files = new Set();
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (flushing_timeout === undefined) {
|
|
15
|
-
flushing_timeout = setTimeout(() => {
|
|
16
|
-
flushing_timeout = undefined;
|
|
17
|
-
void flush_gen_queue();
|
|
18
|
-
}); // the timeout batches synchronously
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
const flush_gen_queue = throttle(async () => {
|
|
22
|
-
const files = Array.from(queued_files);
|
|
23
|
-
queued_files.clear();
|
|
24
|
-
await gen(files);
|
|
25
|
-
}, { delay: flush_debounce_delay });
|
|
26
|
-
// TODO do this in-process - will it cause caching issues with the current impl?
|
|
27
|
-
const gen = (files = []) => spawn_cli('gro', ['gen', ...files]);
|
|
15
|
+
// Cache for gen file declared dependencies to avoid repeated imports
|
|
16
|
+
const gen_dependencies_cache = new Map();
|
|
28
17
|
let cleanup_watch;
|
|
29
18
|
return {
|
|
30
19
|
name: 'gro_plugin_gen',
|
|
31
|
-
setup: async ({ watch, dev, log, config, filer }) => {
|
|
20
|
+
setup: async ({ watch, dev, log, config, filer, invoke_task, timings }) => {
|
|
32
21
|
// For production builds, we assume `gen` is already fresh,
|
|
33
22
|
// which should be checked by CI via `gro check` which calls `gro gen --check`.
|
|
34
23
|
if (!dev)
|
|
35
24
|
return;
|
|
36
25
|
// Do we need to just generate everything once and exit?
|
|
37
26
|
if (!watch) {
|
|
38
|
-
log.info('generating and exiting early');
|
|
39
27
|
// Run `gen`, first checking if there are any modules to avoid a console error.
|
|
40
28
|
// Some parts of the build may have already happened,
|
|
41
29
|
// making us miss `build` events for gen dependencies,
|
|
42
|
-
// so we run `gen` here even if it's usually wasteful.
|
|
30
|
+
// so we run a full `gen` here even if it's usually wasteful.
|
|
43
31
|
const found = find_genfiles(input_paths, root_dirs, config);
|
|
44
32
|
if (found.ok && found.value.resolved_input_files.length > 0) {
|
|
45
33
|
await gen();
|
|
46
34
|
}
|
|
47
35
|
return;
|
|
48
36
|
}
|
|
37
|
+
const queue_gen = (gen_file_id) => {
|
|
38
|
+
queued_files.add(gen_file_id);
|
|
39
|
+
void flush_gen_queue();
|
|
40
|
+
};
|
|
41
|
+
const flush_gen_queue = throttle(async () => {
|
|
42
|
+
const files = Array.from(queued_files);
|
|
43
|
+
log.info(files.length === 0
|
|
44
|
+
? '[gen] generating all files'
|
|
45
|
+
: `[gen] generating ${files.length} file${files.length === 1 ? '' : 's'}`);
|
|
46
|
+
queued_files.clear();
|
|
47
|
+
await gen(files);
|
|
48
|
+
// run again?
|
|
49
|
+
if (queued_files.size > 0) {
|
|
50
|
+
log.info(`[gen] re-running for ${queued_files.size} more queued file${queued_files.size === 1 ? '' : 's'}`);
|
|
51
|
+
setTimeout(flush_gen_queue); // setTimeout is needed bc of throttle behavior
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
log.info('[gen] queue empty, done');
|
|
55
|
+
}
|
|
56
|
+
}, { delay: flush_debounce_delay, when: 'trailing' });
|
|
49
57
|
// When a file builds, check it and its tree of dependents
|
|
50
58
|
// for any `.gen.` files that need to run.
|
|
51
|
-
cleanup_watch = await filer.watch((change, source_file) => {
|
|
59
|
+
cleanup_watch = await filer.watch(async (change, source_file) => {
|
|
52
60
|
if (source_file.external)
|
|
53
61
|
return;
|
|
54
62
|
switch (change.type) {
|
|
55
63
|
case 'add':
|
|
56
64
|
case 'update': {
|
|
65
|
+
// Queue the gen file itself if it changed
|
|
57
66
|
if (is_gen_path(source_file.id)) {
|
|
58
67
|
queue_gen(source_file.id);
|
|
59
68
|
}
|
|
69
|
+
// Find all current gen files and check their dependencies
|
|
70
|
+
const gen_files = filer.filter((d) => !d.external && is_gen_path(d.id));
|
|
71
|
+
if (gen_files) {
|
|
72
|
+
for (const gen_file of gen_files) {
|
|
73
|
+
// eslint-disable-next-line no-await-in-loop
|
|
74
|
+
const should_trigger = await should_trigger_gen(gen_file.id, source_file.id, config, filer, log, timings, invoke_task, gen_dependencies_cache);
|
|
75
|
+
if (should_trigger) {
|
|
76
|
+
queue_gen(gen_file.id);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Check import-based dependents
|
|
60
81
|
const dependent_gen_file_ids = filter_dependents(source_file, filer.get_by_id, is_gen_path, undefined, undefined, log);
|
|
61
82
|
for (const dependent_gen_file_id of dependent_gen_file_ids) {
|
|
62
83
|
queue_gen(dependent_gen_file_id);
|
|
@@ -64,7 +85,10 @@ export const gro_plugin_gen = ({ input_paths = [paths.source], root_dirs = [path
|
|
|
64
85
|
break;
|
|
65
86
|
}
|
|
66
87
|
case 'delete': {
|
|
67
|
-
|
|
88
|
+
if (is_gen_path(source_file.id)) {
|
|
89
|
+
gen_dependencies_cache.delete(source_file.id);
|
|
90
|
+
}
|
|
91
|
+
// I think for the gen plugin this is best as a no-op? avoids broken attempts
|
|
68
92
|
break;
|
|
69
93
|
}
|
|
70
94
|
default:
|
package/dist/package.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/package.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,4BAA4B,CAAC;AAEzD,eAAO,MAAM,YAAY,EAAE,YAiGnB,CAAC;AAET,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"package.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/package.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,4BAA4B,CAAC;AAEzD,eAAO,MAAM,YAAY,EAAE,YAiGnB,CAAC;AAET,eAAO,MAAM,QAAQ,EAAE,QAgyBf,CAAC"}
|
package/dist/package.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// generated by src/lib/package.gen.ts
|
|
2
2
|
export const package_json = {
|
|
3
3
|
name: '@ryanatkn/gro',
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.166.1',
|
|
5
5
|
description: 'task runner and toolkit extending SvelteKit',
|
|
6
6
|
motto: 'generate, run, optimize',
|
|
7
7
|
glyph: '🌰',
|
|
@@ -59,13 +59,13 @@ export const package_json = {
|
|
|
59
59
|
vitest: '^3',
|
|
60
60
|
},
|
|
61
61
|
peerDependenciesMeta: { '@sveltejs/kit': { optional: true }, vitest: { optional: true } },
|
|
62
|
-
optionalDependencies: {
|
|
62
|
+
optionalDependencies: { vitest: '^3' },
|
|
63
63
|
devDependencies: {
|
|
64
64
|
'@changesets/changelog-git': '^0.2.1',
|
|
65
65
|
'@changesets/types': '^6.1.0',
|
|
66
66
|
'@ryanatkn/eslint-config': '^0.8.0',
|
|
67
67
|
'@ryanatkn/fuz': '^0.146.0',
|
|
68
|
-
'@ryanatkn/moss': '^0.
|
|
68
|
+
'@ryanatkn/moss': '^0.35.0',
|
|
69
69
|
'@sveltejs/adapter-static': '^3.0.9',
|
|
70
70
|
'@sveltejs/kit': '^2.37.1',
|
|
71
71
|
'@sveltejs/package': '^2.5.0',
|
|
@@ -75,7 +75,7 @@ export const package_json = {
|
|
|
75
75
|
eslint: '^9.35.0',
|
|
76
76
|
'eslint-plugin-svelte': '^3.12.2',
|
|
77
77
|
svelte: '^5.38.7',
|
|
78
|
-
'svelte-check': '^4.3.
|
|
78
|
+
'svelte-check': '^4.3.2',
|
|
79
79
|
typescript: '^5.9.2',
|
|
80
80
|
'typescript-eslint': '^8.42.0',
|
|
81
81
|
vitest: '^3.2.4',
|
|
@@ -98,7 +98,7 @@ export const package_json = {
|
|
|
98
98
|
};
|
|
99
99
|
export const src_json = {
|
|
100
100
|
name: '@ryanatkn/gro',
|
|
101
|
-
version: '0.
|
|
101
|
+
version: '0.166.1',
|
|
102
102
|
modules: {
|
|
103
103
|
'.': {
|
|
104
104
|
path: 'index.ts',
|
|
@@ -343,6 +343,10 @@ export const src_json = {
|
|
|
343
343
|
],
|
|
344
344
|
},
|
|
345
345
|
'./fs.js': { path: 'fs.ts', declarations: [{ name: 'empty_dir', kind: 'function' }] },
|
|
346
|
+
'./gen_helpers.js': {
|
|
347
|
+
path: 'gen_helpers.ts',
|
|
348
|
+
declarations: [{ name: 'should_trigger_gen', kind: 'function' }],
|
|
349
|
+
},
|
|
346
350
|
'./gen.task.js': {
|
|
347
351
|
path: 'gen.task.ts',
|
|
348
352
|
declarations: [
|
|
@@ -358,7 +362,12 @@ export const src_json = {
|
|
|
358
362
|
{ name: 'is_gen_path', kind: 'function' },
|
|
359
363
|
{ name: 'Gen_Result', kind: 'type' },
|
|
360
364
|
{ name: 'Gen_File', kind: 'type' },
|
|
365
|
+
{ name: 'Gen_Dependencies', kind: 'type' },
|
|
366
|
+
{ name: 'Gen_Dependencies_Config', kind: 'type' },
|
|
367
|
+
{ name: 'Gen_Dependencies_Resolver', kind: 'type' },
|
|
361
368
|
{ name: 'Gen', kind: 'type' },
|
|
369
|
+
{ name: 'Gen_Function', kind: 'type' },
|
|
370
|
+
{ name: 'Gen_Config', kind: 'type' },
|
|
362
371
|
{ name: 'Gen_Context', kind: 'type' },
|
|
363
372
|
{ name: 'Raw_Gen_Result', kind: 'type' },
|
|
364
373
|
{ name: 'Raw_Gen_File', kind: 'type' },
|
|
@@ -383,6 +392,7 @@ export const src_json = {
|
|
|
383
392
|
{ name: 'Load_Genfiles_Failure', kind: 'type' },
|
|
384
393
|
{ name: 'load_genfiles', kind: 'function' },
|
|
385
394
|
{ name: 'validate_gen_module', kind: 'function' },
|
|
395
|
+
{ name: 'normalize_gen_config', kind: 'function' },
|
|
386
396
|
],
|
|
387
397
|
},
|
|
388
398
|
'./git.js': {
|
package/dist/run_gen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run_gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/run_gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAElD,OAAO,EACN,KAAK,WAAW,EAGhB,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"run_gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/run_gen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAElD,OAAO,EACN,KAAK,WAAW,EAGhB,KAAK,mBAAmB,EAIxB,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAC,WAAW,IAAI,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AACtE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAEhD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAE3C,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AAEtE,eAAO,MAAM,OAAO,GACnB,aAAa,KAAK,CAAC,mBAAmB,CAAC,EACvC,QAAQ,UAAU,EAClB,OAAO,KAAK,EACZ,KAAK,MAAM,EACX,SAAS,OAAO,EAChB,aAAa,WAAW,EACxB,cAAc,OAAO,gBAAgB,KACnC,OAAO,CAAC,WAAW,CAwErB,CAAC"}
|
package/dist/run_gen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { styleText as st } from 'node:util';
|
|
2
2
|
import { print_error } from '@ryanatkn/belt/print.js';
|
|
3
|
-
import { to_gen_result, } from "./gen.js";
|
|
3
|
+
import { to_gen_result, normalize_gen_config, } from "./gen.js";
|
|
4
4
|
import { print_path, to_root_path } from "./paths.js";
|
|
5
5
|
import { default_svelte_config } from "./svelte_config.js";
|
|
6
6
|
export const GEN_NO_PROD_MESSAGE = 'gen runs only during development';
|
|
@@ -12,7 +12,7 @@ export const run_gen = async (gen_modules, config, filer, log, timings, invoke_t
|
|
|
12
12
|
input_count++;
|
|
13
13
|
const { id } = module_meta;
|
|
14
14
|
const timing_for_module = timings.start(id);
|
|
15
|
-
|
|
15
|
+
const gen_config = normalize_gen_config(module_meta.mod.gen);
|
|
16
16
|
const gen_ctx = {
|
|
17
17
|
config,
|
|
18
18
|
svelte_config: default_svelte_config,
|
|
@@ -25,7 +25,7 @@ export const run_gen = async (gen_modules, config, filer, log, timings, invoke_t
|
|
|
25
25
|
};
|
|
26
26
|
let raw_gen_result;
|
|
27
27
|
try {
|
|
28
|
-
raw_gen_result = await
|
|
28
|
+
raw_gen_result = await gen_config.generate(gen_ctx);
|
|
29
29
|
}
|
|
30
30
|
catch (err) {
|
|
31
31
|
return {
|
package/dist/watch_dir.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch_dir.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/watch_dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,eAAe,EAAiB,MAAM,UAAU,CAAC;AAKrE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAI3C,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACtB;AACD,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC9D,MAAM,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,iDAMvB,iBAAiB,KAAG,
|
|
1
|
+
{"version":3,"file":"watch_dir.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/watch_dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,eAAe,EAAiB,MAAM,UAAU,CAAC;AAKrE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAI3C,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACtB;AACD,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC9D,MAAM,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,iDAMvB,iBAAiB,KAAG,aA+CtB,CAAC"}
|
package/dist/watch_dir.js
CHANGED
|
@@ -29,8 +29,9 @@ export const watch_dir = ({ dir, on_change, filter, absolute = true, chokidar, }
|
|
|
29
29
|
watcher.on('change', (path, s) => {
|
|
30
30
|
const stats = s ?? statSync(path);
|
|
31
31
|
const final_path = absolute ? path : relative(dir, path);
|
|
32
|
-
if (filter && !filter(final_path, stats.isDirectory()))
|
|
32
|
+
if (filter && !filter(final_path, stats.isDirectory())) {
|
|
33
33
|
return;
|
|
34
|
+
}
|
|
34
35
|
on_change({ type: 'update', path: final_path, is_directory: stats.isDirectory() });
|
|
35
36
|
});
|
|
36
37
|
watcher.on('unlink', (path) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryanatkn/gro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.166.1",
|
|
4
4
|
"description": "task runner and toolkit extending SvelteKit",
|
|
5
5
|
"motto": "generate, run, optimize",
|
|
6
6
|
"glyph": "🌰",
|
|
@@ -77,7 +77,6 @@
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
"optionalDependencies": {
|
|
80
|
-
"@ryanatkn/moss": ">=0.33.0",
|
|
81
80
|
"vitest": "^3"
|
|
82
81
|
},
|
|
83
82
|
"devDependencies": {
|
|
@@ -85,7 +84,7 @@
|
|
|
85
84
|
"@changesets/types": "^6.1.0",
|
|
86
85
|
"@ryanatkn/eslint-config": "^0.8.0",
|
|
87
86
|
"@ryanatkn/fuz": "^0.146.0",
|
|
88
|
-
"@ryanatkn/moss": "^0.
|
|
87
|
+
"@ryanatkn/moss": "^0.35.0",
|
|
89
88
|
"@sveltejs/adapter-static": "^3.0.9",
|
|
90
89
|
"@sveltejs/kit": "^2.37.1",
|
|
91
90
|
"@sveltejs/package": "^2.5.0",
|
|
@@ -95,7 +94,7 @@
|
|
|
95
94
|
"eslint": "^9.35.0",
|
|
96
95
|
"eslint-plugin-svelte": "^3.12.2",
|
|
97
96
|
"svelte": "^5.38.7",
|
|
98
|
-
"svelte-check": "^4.3.
|
|
97
|
+
"svelte-check": "^4.3.2",
|
|
99
98
|
"typescript": "^5.9.2",
|
|
100
99
|
"typescript-eslint": "^8.42.0",
|
|
101
100
|
"vitest": "^3.2.4"
|
package/src/lib/dev.task.ts
CHANGED
|
@@ -31,13 +31,20 @@ export const task: Task<Args> = {
|
|
|
31
31
|
|
|
32
32
|
if (sync || install) {
|
|
33
33
|
if (!sync) log.warn('sync is false but install is true, so ignoring the sync option');
|
|
34
|
-
await invoke_task('sync', {install});
|
|
34
|
+
await invoke_task('sync', {install, gen: !watch});
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const plugins = await Plugins.create({...ctx, dev: true, watch});
|
|
38
38
|
await plugins.setup();
|
|
39
39
|
if (!watch) {
|
|
40
40
|
await plugins.teardown();
|
|
41
|
+
} else {
|
|
42
|
+
// TODO maybe redesign for this API to be explicitly cancelable?
|
|
43
|
+
// Keep the task running indefinitely in watch mode.
|
|
44
|
+
// This prevents invoke_task from calling finish() and closing the filer.
|
|
45
|
+
await new Promise(() => {
|
|
46
|
+
// Never resolves - keeps filer and listeners alive.
|
|
47
|
+
});
|
|
41
48
|
}
|
|
42
49
|
},
|
|
43
50
|
};
|
package/src/lib/filer.ts
CHANGED
|
@@ -89,6 +89,16 @@ export class Filer {
|
|
|
89
89
|
return file;
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
+
filter(predicate: (disknode: Disknode) => boolean): Array<Disknode> | null {
|
|
93
|
+
let found: Array<Disknode> | null = null;
|
|
94
|
+
for (const disknode of this.files.values()) {
|
|
95
|
+
if (predicate(disknode)) {
|
|
96
|
+
(found ??= []).push(disknode);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return found;
|
|
100
|
+
}
|
|
101
|
+
|
|
92
102
|
/**
|
|
93
103
|
* Initialize the filer to populate files without watching.
|
|
94
104
|
* Safe to call multiple times - subsequent calls are no-ops.
|
|
@@ -208,12 +218,13 @@ export class Filer {
|
|
|
208
218
|
const file = this.get_or_create(id);
|
|
209
219
|
|
|
210
220
|
const stats = existsSync(id) ? statSync(id) : null;
|
|
221
|
+
const old_mtime = file.mtime;
|
|
211
222
|
file.ctime = stats?.ctimeMs ?? null;
|
|
212
223
|
file.mtime = stats?.mtimeMs ?? null;
|
|
213
224
|
|
|
214
225
|
const new_contents = stats ? readFileSync(id, 'utf8') : null; // TODO need to lazily load contents, probably turn `Disknode` into a class
|
|
215
226
|
|
|
216
|
-
if (file.contents === new_contents) {
|
|
227
|
+
if (file.mtime === old_mtime && file.contents === new_contents) {
|
|
217
228
|
return null;
|
|
218
229
|
}
|
|
219
230
|
|
|
@@ -336,7 +347,7 @@ export class Filer {
|
|
|
336
347
|
}
|
|
337
348
|
};
|
|
338
349
|
|
|
339
|
-
#is_external(id:
|
|
350
|
+
#is_external(id: Path_Id): boolean {
|
|
340
351
|
const {filter} = this.#watch_dir_options;
|
|
341
352
|
return !id.startsWith(this.root_dir + '/') || (!!filter && !filter(id, false));
|
|
342
353
|
}
|
|
@@ -347,10 +358,10 @@ export const filter_dependents = (
|
|
|
347
358
|
disknode: Disknode,
|
|
348
359
|
get_by_id: (id: Path_Id) => Disknode | undefined,
|
|
349
360
|
filter?: File_Filter,
|
|
350
|
-
results: Set<
|
|
351
|
-
searched: Set<
|
|
361
|
+
results: Set<Path_Id> = new Set(),
|
|
362
|
+
searched: Set<Path_Id> = new Set(),
|
|
352
363
|
log?: Logger,
|
|
353
|
-
): Set<
|
|
364
|
+
): Set<Path_Id> => {
|
|
354
365
|
const {dependents} = disknode;
|
|
355
366
|
for (const dependent_id of dependents.keys()) {
|
|
356
367
|
if (searched.has(dependent_id)) continue;
|
package/src/lib/gen.task.ts
CHANGED
|
@@ -112,8 +112,6 @@ export const task: Task<Args> = {
|
|
|
112
112
|
log.info('check passed, no files have changed');
|
|
113
113
|
}
|
|
114
114
|
} else {
|
|
115
|
-
// write generated files to disk
|
|
116
|
-
log.info('writing generated files to disk');
|
|
117
115
|
const timing_to_output_results = timings.start('output results');
|
|
118
116
|
await write_gen_results(gen_results, analyzed_gen_results, log);
|
|
119
117
|
timing_to_output_results();
|
package/src/lib/gen.ts
CHANGED
|
@@ -38,7 +38,28 @@ export interface Gen_File {
|
|
|
38
38
|
format: boolean;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export type
|
|
41
|
+
export type Gen_Dependencies = 'all' | Gen_Dependencies_Config | Gen_Dependencies_Resolver;
|
|
42
|
+
|
|
43
|
+
export interface Gen_Dependencies_Config {
|
|
44
|
+
patterns?: Array<RegExp>;
|
|
45
|
+
files?: Array<Path_Id>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type Gen_Dependencies_Resolver = (
|
|
49
|
+
ctx: Gen_Context,
|
|
50
|
+
) => Gen_Dependencies_Config | 'all' | Promise<Gen_Dependencies_Config | 'all'>;
|
|
51
|
+
|
|
52
|
+
export type Gen = Gen_Function | Gen_Config;
|
|
53
|
+
|
|
54
|
+
export type Gen_Function = (ctx: Gen_Context) => Raw_Gen_Result | Promise<Raw_Gen_Result>;
|
|
55
|
+
|
|
56
|
+
export interface Gen_Config {
|
|
57
|
+
generate: Gen_Function;
|
|
58
|
+
dependencies?: Gen_Dependencies;
|
|
59
|
+
// TODO think about what could be added
|
|
60
|
+
// cache?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
42
63
|
export interface Gen_Context {
|
|
43
64
|
config: Gro_Config;
|
|
44
65
|
svelte_config: Parsed_Svelte_Config;
|
|
@@ -362,5 +383,13 @@ export const load_genfiles = async (
|
|
|
362
383
|
};
|
|
363
384
|
};
|
|
364
385
|
|
|
365
|
-
export const validate_gen_module = (mod: Record<string, any>): mod is Genfile_Module =>
|
|
366
|
-
typeof mod.gen === 'function';
|
|
386
|
+
export const validate_gen_module = (mod: Record<string, any>): mod is Genfile_Module => {
|
|
387
|
+
if (typeof mod.gen === 'function') return true;
|
|
388
|
+
if (typeof mod.gen === 'object' && mod.gen !== null && typeof mod.gen.generate === 'function') {
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
return false;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
export const normalize_gen_config = (gen: Gen): Gen_Config =>
|
|
395
|
+
typeof gen === 'function' ? {generate: gen} : gen;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import {pathToFileURL} from 'node:url';
|
|
2
|
+
import {resolve} from 'node:path';
|
|
3
|
+
import type {Logger} from '@ryanatkn/belt/log.js';
|
|
4
|
+
import type {Timings} from '@ryanatkn/belt/timings.js';
|
|
5
|
+
|
|
6
|
+
import type {Gro_Config} from './gro_config.ts';
|
|
7
|
+
import type {Filer} from './filer.ts';
|
|
8
|
+
import type {Invoke_Task} from './task.ts';
|
|
9
|
+
import {
|
|
10
|
+
normalize_gen_config,
|
|
11
|
+
validate_gen_module,
|
|
12
|
+
type Gen_Context,
|
|
13
|
+
type Gen_Dependencies,
|
|
14
|
+
} from './gen.ts';
|
|
15
|
+
import {default_svelte_config} from './svelte_config.ts';
|
|
16
|
+
import {to_root_path} from './paths.ts';
|
|
17
|
+
import type {Path_Id} from './path.ts';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Check if a file change should trigger a gen file.
|
|
21
|
+
*/
|
|
22
|
+
export const should_trigger_gen = async (
|
|
23
|
+
gen_file_id: Path_Id,
|
|
24
|
+
changed_file_id: Path_Id,
|
|
25
|
+
config: Gro_Config,
|
|
26
|
+
filer: Filer,
|
|
27
|
+
log: Logger,
|
|
28
|
+
timings: Timings,
|
|
29
|
+
invoke_task: Invoke_Task,
|
|
30
|
+
dependencies_cache: Map<Path_Id, Gen_Dependencies | null>,
|
|
31
|
+
): Promise<boolean> => {
|
|
32
|
+
// Always trigger if the gen file itself changed
|
|
33
|
+
if (gen_file_id === changed_file_id) {
|
|
34
|
+
// Invalidate cache for this gen file
|
|
35
|
+
dependencies_cache.delete(gen_file_id);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let dependencies: Gen_Dependencies | null | undefined;
|
|
40
|
+
if (!dependencies_cache.has(gen_file_id)) {
|
|
41
|
+
dependencies = await resolve_gen_dependencies(
|
|
42
|
+
gen_file_id,
|
|
43
|
+
config,
|
|
44
|
+
filer,
|
|
45
|
+
log,
|
|
46
|
+
timings,
|
|
47
|
+
invoke_task,
|
|
48
|
+
);
|
|
49
|
+
dependencies_cache.set(gen_file_id, dependencies);
|
|
50
|
+
} else {
|
|
51
|
+
dependencies = dependencies_cache.get(gen_file_id);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!dependencies) return false;
|
|
55
|
+
|
|
56
|
+
if (dependencies === 'all') return true;
|
|
57
|
+
|
|
58
|
+
if (typeof dependencies !== 'function') {
|
|
59
|
+
if (dependencies.patterns) {
|
|
60
|
+
if (dependencies.patterns.some((p) => p.test(changed_file_id))) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (dependencies.files) {
|
|
66
|
+
if (dependencies.files.includes(changed_file_id)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return false;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Resolve dependencies for a gen file.
|
|
77
|
+
* Uses cache-busting to get fresh imports, allowing dependency
|
|
78
|
+
* declarations to update during watch mode without restart.
|
|
79
|
+
*/
|
|
80
|
+
const resolve_gen_dependencies = async (
|
|
81
|
+
gen_file_id: string,
|
|
82
|
+
config: Gro_Config,
|
|
83
|
+
filer: Filer,
|
|
84
|
+
log: Logger,
|
|
85
|
+
timings: Timings,
|
|
86
|
+
invoke_task: Invoke_Task,
|
|
87
|
+
): Promise<Gen_Dependencies | null> => {
|
|
88
|
+
try {
|
|
89
|
+
const url = pathToFileURL(gen_file_id);
|
|
90
|
+
url.searchParams.set('t', Date.now().toString());
|
|
91
|
+
const module = await import(url.href);
|
|
92
|
+
if (!validate_gen_module(module)) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const gen_config = normalize_gen_config(module.gen);
|
|
97
|
+
if (!gen_config.dependencies) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let dependencies = gen_config.dependencies;
|
|
102
|
+
if (typeof dependencies === 'function') {
|
|
103
|
+
const gen_ctx: Gen_Context = {
|
|
104
|
+
config,
|
|
105
|
+
svelte_config: default_svelte_config,
|
|
106
|
+
filer,
|
|
107
|
+
log,
|
|
108
|
+
timings,
|
|
109
|
+
invoke_task,
|
|
110
|
+
origin_id: gen_file_id,
|
|
111
|
+
origin_path: to_root_path(gen_file_id),
|
|
112
|
+
};
|
|
113
|
+
dependencies = await dependencies(gen_ctx);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Normalize file paths to absolute paths
|
|
117
|
+
if (dependencies !== 'all' && dependencies.files) {
|
|
118
|
+
dependencies.files = dependencies.files.map((f) => resolve(f));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return dependencies;
|
|
122
|
+
} catch (err) {
|
|
123
|
+
log.error(`Failed to resolve dependencies for ${gen_file_id}:`, err);
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
@@ -5,12 +5,18 @@ import {Unreachable_Error} from '@ryanatkn/belt/error.js';
|
|
|
5
5
|
import type {Plugin} from './plugin.ts';
|
|
6
6
|
import type {Args} from './args.ts';
|
|
7
7
|
import {paths} from './paths.ts';
|
|
8
|
-
import {find_genfiles, is_gen_path} from './gen.ts';
|
|
9
|
-
import {spawn_cli} from './cli.ts';
|
|
8
|
+
import {find_genfiles, is_gen_path, type Gen_Dependencies} from './gen.ts';
|
|
10
9
|
import {filter_dependents} from './filer.ts';
|
|
10
|
+
import {should_trigger_gen} from './gen_helpers.ts';
|
|
11
|
+
import {spawn_cli} from './cli.ts';
|
|
12
|
+
import type {Path_Id} from './path.ts';
|
|
11
13
|
|
|
12
14
|
const FLUSH_DEBOUNCE_DELAY = 500;
|
|
13
15
|
|
|
16
|
+
// TODO is cache busting a good idea here to speed up and run in-process?
|
|
17
|
+
// await invoke_task('gen', {_: files, bust_cache: true});
|
|
18
|
+
const gen = (files: Array<string> = []) => spawn_cli('gro', ['gen', ...files]);
|
|
19
|
+
|
|
14
20
|
export interface Task_Args extends Args {
|
|
15
21
|
watch?: boolean;
|
|
16
22
|
}
|
|
@@ -26,46 +32,26 @@ export const gro_plugin_gen = ({
|
|
|
26
32
|
root_dirs = [paths.source],
|
|
27
33
|
flush_debounce_delay = FLUSH_DEBOUNCE_DELAY,
|
|
28
34
|
}: Gro_Plugin_Gen_Options = EMPTY_OBJECT): Plugin => {
|
|
29
|
-
let flushing_timeout: NodeJS.Timeout | undefined;
|
|
30
35
|
const queued_files: Set<string> = new Set();
|
|
31
|
-
const queue_gen = (gen_file_id: string) => {
|
|
32
|
-
queued_files.add(gen_file_id);
|
|
33
|
-
if (flushing_timeout === undefined) {
|
|
34
|
-
flushing_timeout = setTimeout(() => {
|
|
35
|
-
flushing_timeout = undefined;
|
|
36
|
-
void flush_gen_queue();
|
|
37
|
-
}); // the timeout batches synchronously
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
const flush_gen_queue = throttle(
|
|
41
|
-
async () => {
|
|
42
|
-
const files = Array.from(queued_files);
|
|
43
|
-
queued_files.clear();
|
|
44
|
-
await gen(files);
|
|
45
|
-
},
|
|
46
|
-
{delay: flush_debounce_delay},
|
|
47
|
-
);
|
|
48
36
|
|
|
49
|
-
//
|
|
50
|
-
const
|
|
37
|
+
// Cache for gen file declared dependencies to avoid repeated imports
|
|
38
|
+
const gen_dependencies_cache: Map<Path_Id, Gen_Dependencies | null> = new Map();
|
|
51
39
|
|
|
52
40
|
let cleanup_watch: (() => void) | undefined;
|
|
53
41
|
|
|
54
42
|
return {
|
|
55
43
|
name: 'gro_plugin_gen',
|
|
56
|
-
setup: async ({watch, dev, log, config, filer}) => {
|
|
44
|
+
setup: async ({watch, dev, log, config, filer, invoke_task, timings}) => {
|
|
57
45
|
// For production builds, we assume `gen` is already fresh,
|
|
58
46
|
// which should be checked by CI via `gro check` which calls `gro gen --check`.
|
|
59
47
|
if (!dev) return;
|
|
60
48
|
|
|
61
49
|
// Do we need to just generate everything once and exit?
|
|
62
50
|
if (!watch) {
|
|
63
|
-
log.info('generating and exiting early');
|
|
64
|
-
|
|
65
51
|
// Run `gen`, first checking if there are any modules to avoid a console error.
|
|
66
52
|
// Some parts of the build may have already happened,
|
|
67
53
|
// making us miss `build` events for gen dependencies,
|
|
68
|
-
// so we run `gen` here even if it's usually wasteful.
|
|
54
|
+
// so we run a full `gen` here even if it's usually wasteful.
|
|
69
55
|
const found = find_genfiles(input_paths, root_dirs, config);
|
|
70
56
|
if (found.ok && found.value.resolved_input_files.length > 0) {
|
|
71
57
|
await gen();
|
|
@@ -73,16 +59,69 @@ export const gro_plugin_gen = ({
|
|
|
73
59
|
return;
|
|
74
60
|
}
|
|
75
61
|
|
|
62
|
+
const queue_gen = (gen_file_id: string) => {
|
|
63
|
+
queued_files.add(gen_file_id);
|
|
64
|
+
void flush_gen_queue();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const flush_gen_queue = throttle(
|
|
68
|
+
async () => {
|
|
69
|
+
const files = Array.from(queued_files);
|
|
70
|
+
log.info(
|
|
71
|
+
files.length === 0
|
|
72
|
+
? '[gen] generating all files'
|
|
73
|
+
: `[gen] generating ${files.length} file${files.length === 1 ? '' : 's'}`,
|
|
74
|
+
);
|
|
75
|
+
queued_files.clear();
|
|
76
|
+
await gen(files);
|
|
77
|
+
|
|
78
|
+
// run again?
|
|
79
|
+
if (queued_files.size > 0) {
|
|
80
|
+
log.info(
|
|
81
|
+
`[gen] re-running for ${queued_files.size} more queued file${queued_files.size === 1 ? '' : 's'}`,
|
|
82
|
+
);
|
|
83
|
+
setTimeout(flush_gen_queue); // setTimeout is needed bc of throttle behavior
|
|
84
|
+
} else {
|
|
85
|
+
log.info('[gen] queue empty, done');
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{delay: flush_debounce_delay, when: 'trailing'},
|
|
89
|
+
);
|
|
90
|
+
|
|
76
91
|
// When a file builds, check it and its tree of dependents
|
|
77
92
|
// for any `.gen.` files that need to run.
|
|
78
|
-
cleanup_watch = await filer.watch((change, source_file) => {
|
|
93
|
+
cleanup_watch = await filer.watch(async (change, source_file) => {
|
|
79
94
|
if (source_file.external) return;
|
|
80
95
|
switch (change.type) {
|
|
81
96
|
case 'add':
|
|
82
97
|
case 'update': {
|
|
98
|
+
// Queue the gen file itself if it changed
|
|
83
99
|
if (is_gen_path(source_file.id)) {
|
|
84
100
|
queue_gen(source_file.id);
|
|
85
101
|
}
|
|
102
|
+
|
|
103
|
+
// Find all current gen files and check their dependencies
|
|
104
|
+
const gen_files = filer.filter((d) => !d.external && is_gen_path(d.id));
|
|
105
|
+
if (gen_files) {
|
|
106
|
+
for (const gen_file of gen_files) {
|
|
107
|
+
// eslint-disable-next-line no-await-in-loop
|
|
108
|
+
const should_trigger = await should_trigger_gen(
|
|
109
|
+
gen_file.id,
|
|
110
|
+
source_file.id,
|
|
111
|
+
config,
|
|
112
|
+
filer,
|
|
113
|
+
log,
|
|
114
|
+
timings,
|
|
115
|
+
invoke_task,
|
|
116
|
+
gen_dependencies_cache,
|
|
117
|
+
);
|
|
118
|
+
if (should_trigger) {
|
|
119
|
+
queue_gen(gen_file.id);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check import-based dependents
|
|
86
125
|
const dependent_gen_file_ids = filter_dependents(
|
|
87
126
|
source_file,
|
|
88
127
|
filer.get_by_id,
|
|
@@ -97,7 +136,10 @@ export const gro_plugin_gen = ({
|
|
|
97
136
|
break;
|
|
98
137
|
}
|
|
99
138
|
case 'delete': {
|
|
100
|
-
|
|
139
|
+
if (is_gen_path(source_file.id)) {
|
|
140
|
+
gen_dependencies_cache.delete(source_file.id);
|
|
141
|
+
}
|
|
142
|
+
// I think for the gen plugin this is best as a no-op? avoids broken attempts
|
|
101
143
|
break;
|
|
102
144
|
}
|
|
103
145
|
default:
|
package/src/lib/package.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type {Src_Json} from '@ryanatkn/belt/src_json.js';
|
|
|
5
5
|
|
|
6
6
|
export const package_json: Package_Json = {
|
|
7
7
|
name: '@ryanatkn/gro',
|
|
8
|
-
version: '0.
|
|
8
|
+
version: '0.166.1',
|
|
9
9
|
description: 'task runner and toolkit extending SvelteKit',
|
|
10
10
|
motto: 'generate, run, optimize',
|
|
11
11
|
glyph: '🌰',
|
|
@@ -64,13 +64,13 @@ export const package_json: Package_Json = {
|
|
|
64
64
|
vitest: '^3',
|
|
65
65
|
},
|
|
66
66
|
peerDependenciesMeta: {'@sveltejs/kit': {optional: true}, vitest: {optional: true}},
|
|
67
|
-
optionalDependencies: {
|
|
67
|
+
optionalDependencies: {vitest: '^3'},
|
|
68
68
|
devDependencies: {
|
|
69
69
|
'@changesets/changelog-git': '^0.2.1',
|
|
70
70
|
'@changesets/types': '^6.1.0',
|
|
71
71
|
'@ryanatkn/eslint-config': '^0.8.0',
|
|
72
72
|
'@ryanatkn/fuz': '^0.146.0',
|
|
73
|
-
'@ryanatkn/moss': '^0.
|
|
73
|
+
'@ryanatkn/moss': '^0.35.0',
|
|
74
74
|
'@sveltejs/adapter-static': '^3.0.9',
|
|
75
75
|
'@sveltejs/kit': '^2.37.1',
|
|
76
76
|
'@sveltejs/package': '^2.5.0',
|
|
@@ -80,7 +80,7 @@ export const package_json: Package_Json = {
|
|
|
80
80
|
eslint: '^9.35.0',
|
|
81
81
|
'eslint-plugin-svelte': '^3.12.2',
|
|
82
82
|
svelte: '^5.38.7',
|
|
83
|
-
'svelte-check': '^4.3.
|
|
83
|
+
'svelte-check': '^4.3.2',
|
|
84
84
|
typescript: '^5.9.2',
|
|
85
85
|
'typescript-eslint': '^8.42.0',
|
|
86
86
|
vitest: '^3.2.4',
|
|
@@ -104,7 +104,7 @@ export const package_json: Package_Json = {
|
|
|
104
104
|
|
|
105
105
|
export const src_json: Src_Json = {
|
|
106
106
|
name: '@ryanatkn/gro',
|
|
107
|
-
version: '0.
|
|
107
|
+
version: '0.166.1',
|
|
108
108
|
modules: {
|
|
109
109
|
'.': {
|
|
110
110
|
path: 'index.ts',
|
|
@@ -349,6 +349,10 @@ export const src_json: Src_Json = {
|
|
|
349
349
|
],
|
|
350
350
|
},
|
|
351
351
|
'./fs.js': {path: 'fs.ts', declarations: [{name: 'empty_dir', kind: 'function'}]},
|
|
352
|
+
'./gen_helpers.js': {
|
|
353
|
+
path: 'gen_helpers.ts',
|
|
354
|
+
declarations: [{name: 'should_trigger_gen', kind: 'function'}],
|
|
355
|
+
},
|
|
352
356
|
'./gen.task.js': {
|
|
353
357
|
path: 'gen.task.ts',
|
|
354
358
|
declarations: [
|
|
@@ -364,7 +368,12 @@ export const src_json: Src_Json = {
|
|
|
364
368
|
{name: 'is_gen_path', kind: 'function'},
|
|
365
369
|
{name: 'Gen_Result', kind: 'type'},
|
|
366
370
|
{name: 'Gen_File', kind: 'type'},
|
|
371
|
+
{name: 'Gen_Dependencies', kind: 'type'},
|
|
372
|
+
{name: 'Gen_Dependencies_Config', kind: 'type'},
|
|
373
|
+
{name: 'Gen_Dependencies_Resolver', kind: 'type'},
|
|
367
374
|
{name: 'Gen', kind: 'type'},
|
|
375
|
+
{name: 'Gen_Function', kind: 'type'},
|
|
376
|
+
{name: 'Gen_Config', kind: 'type'},
|
|
368
377
|
{name: 'Gen_Context', kind: 'type'},
|
|
369
378
|
{name: 'Raw_Gen_Result', kind: 'type'},
|
|
370
379
|
{name: 'Raw_Gen_File', kind: 'type'},
|
|
@@ -389,6 +398,7 @@ export const src_json: Src_Json = {
|
|
|
389
398
|
{name: 'Load_Genfiles_Failure', kind: 'type'},
|
|
390
399
|
{name: 'load_genfiles', kind: 'function'},
|
|
391
400
|
{name: 'validate_gen_module', kind: 'function'},
|
|
401
|
+
{name: 'normalize_gen_config', kind: 'function'},
|
|
392
402
|
],
|
|
393
403
|
},
|
|
394
404
|
'./git.js': {
|
package/src/lib/run_gen.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type Genfile_Module_Meta,
|
|
11
11
|
to_gen_result,
|
|
12
12
|
type Raw_Gen_Result,
|
|
13
|
+
normalize_gen_config,
|
|
13
14
|
} from './gen.ts';
|
|
14
15
|
import {print_path, to_root_path} from './paths.ts';
|
|
15
16
|
import type {format_file as base_format_file} from './format_file.ts';
|
|
@@ -38,7 +39,7 @@ export const run_gen = async (
|
|
|
38
39
|
const {id} = module_meta;
|
|
39
40
|
const timing_for_module = timings.start(id);
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
const gen_config = normalize_gen_config(module_meta.mod.gen);
|
|
42
43
|
const gen_ctx: Gen_Context = {
|
|
43
44
|
config,
|
|
44
45
|
svelte_config: default_svelte_config,
|
|
@@ -51,7 +52,7 @@ export const run_gen = async (
|
|
|
51
52
|
};
|
|
52
53
|
let raw_gen_result: Raw_Gen_Result;
|
|
53
54
|
try {
|
|
54
|
-
raw_gen_result = await
|
|
55
|
+
raw_gen_result = await gen_config.generate(gen_ctx);
|
|
55
56
|
} catch (err) {
|
|
56
57
|
return {
|
|
57
58
|
ok: false,
|
package/src/lib/watch_dir.ts
CHANGED
|
@@ -63,7 +63,9 @@ export const watch_dir = ({
|
|
|
63
63
|
watcher.on('change', (path, s) => {
|
|
64
64
|
const stats = s ?? statSync(path);
|
|
65
65
|
const final_path = absolute ? path : relative(dir, path);
|
|
66
|
-
if (filter && !filter(final_path, stats.isDirectory()))
|
|
66
|
+
if (filter && !filter(final_path, stats.isDirectory())) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
67
69
|
on_change({type: 'update', path: final_path, is_directory: stats.isDirectory()});
|
|
68
70
|
});
|
|
69
71
|
watcher.on('unlink', (path) => {
|