@ryanatkn/gro 0.183.0 → 0.185.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.
Files changed (42) hide show
  1. package/dist/disknode.d.ts +5 -0
  2. package/dist/disknode.d.ts.map +1 -1
  3. package/dist/filer.d.ts.map +1 -1
  4. package/dist/filer.js +8 -2
  5. package/dist/gen.js +2 -2
  6. package/dist/gro_config.d.ts +3 -3
  7. package/dist/gro_config.d.ts.map +1 -1
  8. package/dist/gro_config.js +1 -1
  9. package/dist/hash.d.ts +7 -1
  10. package/dist/hash.d.ts.map +1 -1
  11. package/dist/hash.js +9 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/package_json.d.ts +0 -1
  15. package/dist/package_json.d.ts.map +1 -1
  16. package/dist/package_json.js +0 -2
  17. package/dist/plugin.d.ts +3 -3
  18. package/dist/plugin.js +2 -2
  19. package/dist/run.task.d.ts +2 -0
  20. package/dist/run.task.d.ts.map +1 -1
  21. package/dist/run.task.js +2 -0
  22. package/dist/source_json.d.ts +1 -1
  23. package/dist/source_json.d.ts.map +1 -1
  24. package/dist/source_json.js +2 -2
  25. package/dist/sveltekit_shim_app_environment.d.ts +2 -0
  26. package/dist/sveltekit_shim_app_environment.d.ts.map +1 -1
  27. package/dist/sveltekit_shim_app_environment.js +2 -0
  28. package/dist/sveltekit_shim_app_paths.d.ts +2 -0
  29. package/dist/sveltekit_shim_app_paths.d.ts.map +1 -1
  30. package/package.json +5 -5
  31. package/src/lib/disknode.ts +5 -0
  32. package/src/lib/filer.ts +9 -2
  33. package/src/lib/gen.ts +2 -2
  34. package/src/lib/gro_config.ts +4 -6
  35. package/src/lib/hash.ts +11 -2
  36. package/src/lib/index.ts +1 -1
  37. package/src/lib/package_json.ts +0 -3
  38. package/src/lib/plugin.ts +3 -3
  39. package/src/lib/run.task.ts +2 -0
  40. package/src/lib/source_json.ts +2 -2
  41. package/src/lib/sveltekit_shim_app_environment.ts +2 -0
  42. package/src/lib/sveltekit_shim_app_paths.ts +2 -0
@@ -12,6 +12,11 @@ export interface Disknode {
12
12
  external: boolean;
13
13
  ctime: number | null;
14
14
  mtime: number | null;
15
+ /**
16
+ * SHA-256 hash of `contents`. `null` iff `contents` is `null`.
17
+ * Used for content-based change detection and caching.
18
+ */
19
+ content_hash: string | null;
15
20
  dependents: Map<PathId, Disknode>;
16
21
  dependencies: Map<PathId, Disknode>;
17
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"disknode.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/disknode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAIrD,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACpC"}
1
+ {"version":3,"file":"disknode.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/disknode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAIrD,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IAEX;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AAI1D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAC,UAAU,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EACN,SAAS,EAET,KAAK,aAAa,EAClB,KAAK,eAAe,EAEpB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAI5C,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAG1B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;gBAetC,OAAO,GAAE,YAA2B;IAUhD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,SAAS,GAAI,IAAI,MAAM,KAAG,QAAQ,GAAG,SAAS,CAE5C;IAEF,aAAa,GAAI,IAAI,MAAM,KAAG,QAAQ,CAoBpC;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;IAsDrB,KAAK,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAmBzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAyOtB;AAGD,eAAO,MAAM,iBAAiB,GAC7B,UAAU,QAAQ,EAClB,WAAW,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,EAC/C,SAAS,UAAU,EACnB,UAAS,GAAG,CAAC,MAAM,CAAa,EAChC,WAAU,GAAG,CAAC,MAAM,CAAa,EACjC,MAAM,MAAM,KACV,GAAG,CAAC,MAAM,CAuBZ,CAAC"}
1
+ {"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AAI1D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAC,UAAU,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EACN,SAAS,EAET,KAAK,aAAa,EAClB,KAAK,eAAe,EAEpB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAK5C,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAG1B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;gBAetC,OAAO,GAAE,YAA2B;IAUhD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,SAAS,GAAI,IAAI,MAAM,KAAG,QAAQ,GAAG,SAAS,CAE5C;IAEF,aAAa,GAAI,IAAI,MAAM,KAAG,QAAQ,CAqBpC;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;IAsDrB,KAAK,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAmBzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA8OtB;AAGD,eAAO,MAAM,iBAAiB,GAC7B,UAAU,QAAQ,EAClB,WAAW,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,EAC/C,SAAS,UAAU,EACnB,UAAS,GAAG,CAAC,MAAM,CAAa,EAChC,WAAU,GAAG,CAAC,MAAM,CAAa,EACjC,MAAM,MAAM,KACV,GAAG,CAAC,MAAM,CAuBZ,CAAC"}
package/dist/filer.js CHANGED
@@ -11,6 +11,7 @@ import { resolve_specifier } from "./resolve_specifier.js";
11
11
  import { default_svelte_config } from "./svelte_config.js";
12
12
  import { map_sveltekit_aliases } from "./sveltekit_helpers.js";
13
13
  import { SVELTEKIT_GLOBAL_SPECIFIER } from "./constants.js";
14
+ import { to_hash } from "./hash.js";
14
15
  const aliases = Object.entries(default_svelte_config.alias);
15
16
  export class Filer {
16
17
  root_dir;
@@ -51,6 +52,7 @@ export class Filer {
51
52
  external: this.#is_external(id), // TODO maybe filter externals by default? the user needs to configure the filer then
52
53
  ctime: null,
53
54
  mtime: null,
55
+ content_hash: null,
54
56
  dependents: new Map(),
55
57
  dependencies: new Map(),
56
58
  };
@@ -198,13 +200,16 @@ export class Filer {
198
200
  throw error;
199
201
  }
200
202
  }
201
- const old_mtime = file.mtime;
203
+ // Compute hash for new contents
204
+ const new_hash = new_contents !== null ? await to_hash(new_contents) : null;
202
205
  file.ctime = stats?.ctimeMs ?? null;
203
206
  file.mtime = stats?.mtimeMs ?? null;
204
- if (file.mtime === old_mtime && file.contents === new_contents) {
207
+ // Use hash comparison for change detection (content-based, not mtime-based)
208
+ if (file.content_hash === new_hash) {
205
209
  return null;
206
210
  }
207
211
  file.contents = new_contents;
212
+ file.content_hash = new_hash;
208
213
  const dir = dirname(file.id);
209
214
  const dependencies_before = new Set(file.dependencies.keys());
210
215
  const dependencies_removed = new Set(dependencies_before);
@@ -260,6 +265,7 @@ export class Filer {
260
265
  if (!file)
261
266
  return null; // this is safe because the object would exist if any other file referenced it as a dependency or dependent
262
267
  file.contents = null; // clear contents in case it gets re-added later, we want the change to be detected
268
+ file.content_hash = null; // clear hash so re-add detects the change
263
269
  file.dependencies.clear();
264
270
  // keep the file in memory if other files still depend on it
265
271
  if (file.dependents.size === 0) {
package/dist/gen.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { join, basename, dirname, isAbsolute } from 'node:path';
2
2
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
3
  import { styleText as st } from 'node:util';
4
- import { map_concurrent } from '@fuzdev/fuz_util/async.js';
4
+ import { each_concurrent, map_concurrent } from '@fuzdev/fuz_util/async.js';
5
5
  import { fs_search } from '@fuzdev/fuz_util/fs.js';
6
6
  import { print_path } from "./paths.js";
7
7
  import { load_modules } from "./modules.js";
@@ -112,7 +112,7 @@ export const analyze_gen_result = async (file) => {
112
112
  };
113
113
  export const write_gen_results = async (gen_results, analyzed_gen_results, log) => {
114
114
  const files = gen_results.successes.flatMap((result) => result.files);
115
- await map_concurrent(files, async (file) => {
115
+ await each_concurrent(files, async (file) => {
116
116
  const analyzed = analyzed_gen_results.find((r) => r.file.id === file.id);
117
117
  if (!analyzed)
118
118
  throw Error('Expected to find analyzed result: ' + file.id);
@@ -1,5 +1,5 @@
1
1
  import type { PathFilter, PathId } from '@fuzdev/fuz_util/path.js';
2
- import type { CreateConfigPlugins } from './plugin.ts';
2
+ import type { PluginsCreateConfig } from './plugin.ts';
3
3
  import type { PackageJsonMapper } from './package_json.ts';
4
4
  import type { ParsedSvelteConfig } from './svelte_config.ts';
5
5
  /**
@@ -16,7 +16,7 @@ export interface GroConfig extends RawGroConfig {
16
16
  /**
17
17
  * @see https://github.com/ryanatkn/gro/blob/main/src/docs/plugin.md
18
18
  */
19
- plugins: CreateConfigPlugins;
19
+ plugins: PluginsCreateConfig;
20
20
  /**
21
21
  * Maps the project's `package.json` before writing it to the filesystem.
22
22
  * The `package_json` argument may be mutated, but the return value is what's used by the caller.
@@ -57,7 +57,7 @@ export interface GroConfig extends RawGroConfig {
57
57
  * @see https://github.com/ryanatkn/gro/blob/main/src/docs/config.md
58
58
  */
59
59
  export interface RawGroConfig {
60
- plugins?: CreateConfigPlugins;
60
+ plugins?: PluginsCreateConfig;
61
61
  map_package_json?: PackageJsonMapper | null;
62
62
  task_root_dirs?: Array<string>;
63
63
  search_filters?: PathFilter | Array<PathFilter> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"gro_config.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gro_config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAcjE,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAG3D;;;GAGG;AACH,eAAO,MAAM,6BAA6B,qEACyB,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC9C;;OAEG;IACH,OAAO,EAAE,mBAAmB,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC3C;;;OAGG;IACH,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,cAAc,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;OAcG;IACH,kBAAkB,CAAC,EAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACtE;AAED,MAAM,MAAM,eAAe,GAAG,CAC7B,WAAW,EAAE,SAAS,EACtB,aAAa,CAAC,EAAE,kBAAkB,KAC9B,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAE1C,eAAO,MAAM,uBAAuB,QAAO,SAazC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAUnC,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAA+C,CAAC;AAErF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAU,YAAY,YAAY,KAAG,OAAO,CAAC,SAAS,CA+CjF,CAAC;AAEF,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,eAAe,CAAC;CACjD;AAED,eAAO,MAAM,eAAe,GAAU,YAAgB,KAAG,OAAO,CAAC,SAAS,CAqBzE,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,CACxC,aAAa,EAAE,GAAG,EAClB,WAAW,EAAE,MAAM,KACf,OAAO,CAAC,aAAa,IAAI,eAS7B,CAAC"}
1
+ {"version":3,"file":"gro_config.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gro_config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAcjE,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAG3D;;;GAGG;AACH,eAAO,MAAM,6BAA6B,qEACyB,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC9C;;OAEG;IACH,OAAO,EAAE,mBAAmB,CAAC;IAC7B;;;;OAIG;IACH,gBAAgB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC3C;;;OAGG;IACH,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B;;;OAGG;IACH,cAAc,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,MAAM,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;OAcG;IACH,kBAAkB,CAAC,EAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACtE;AAED,MAAM,MAAM,eAAe,GAAG,CAC7B,WAAW,EAAE,SAAS,EACtB,aAAa,CAAC,EAAE,kBAAkB,KAC9B,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAE1C,eAAO,MAAM,uBAAuB,QAAO,SAazC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,QAUnC,CAAC;AAEF,eAAO,MAAM,wBAAwB,QAA+C,CAAC;AAErF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAU,YAAY,YAAY,KAAG,OAAO,CAAC,SAAS,CA6CjF,CAAC;AAEF,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,eAAe,CAAC;CACjD;AAED,eAAO,MAAM,eAAe,GAAU,YAAgB,KAAG,OAAO,CAAC,SAAS,CAqBzE,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,CACxC,aAAa,EAAE,GAAG,EAClB,WAAW,EAAE,MAAM,KACf,OAAO,CAAC,aAAa,IAAI,eAS7B,CAAC"}
@@ -67,7 +67,7 @@ export const cook_gro_config = async (raw_config) => {
67
67
  // Resolve if it's a function
68
68
  const resolved = typeof build_cache_config === 'function' ? await build_cache_config() : build_cache_config;
69
69
  // Hash the JSON representation with deterministic key ordering
70
- build_cache_config_hash = await to_hash(new TextEncoder().encode(json_stringify_deterministic(resolved)));
70
+ build_cache_config_hash = await to_hash(json_stringify_deterministic(resolved));
71
71
  }
72
72
  // Delete the raw value to ensure it doesn't persist in memory
73
73
  delete raw_config.build_cache_config;
package/dist/hash.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  /**
2
+ * Computes a cryptographic hash of the given data.
3
+ *
4
+ * @param data - String or binary data to hash. Strings are UTF-8 encoded internally.
5
+ * @param algorithm - Hash algorithm to use. Defaults to SHA-256.
6
+ * @returns Hexadecimal hash string.
7
+ *
2
8
  * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
3
9
  */
4
- export declare const to_hash: (data: BufferSource, algorithm?: "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512") => Promise<string>;
10
+ export declare const to_hash: (data: BufferSource | string, algorithm?: "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512") => Promise<string>;
5
11
  //# sourceMappingURL=hash.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/hash.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,OAAO,GACnB,MAAM,YAAY,EAClB,YAAW,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAqB,KAChE,OAAO,CAAC,MAAM,CAQhB,CAAC"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/hash.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GACnB,MAAM,YAAY,GAAG,MAAM,EAC3B,YAAW,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAqB,KAChE,OAAO,CAAC,MAAM,CAShB,CAAC"}
package/dist/hash.js CHANGED
@@ -1,9 +1,17 @@
1
1
  const { subtle } = globalThis.crypto;
2
+ const encoder = new TextEncoder();
2
3
  /**
4
+ * Computes a cryptographic hash of the given data.
5
+ *
6
+ * @param data - String or binary data to hash. Strings are UTF-8 encoded internally.
7
+ * @param algorithm - Hash algorithm to use. Defaults to SHA-256.
8
+ * @returns Hexadecimal hash string.
9
+ *
3
10
  * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
4
11
  */
5
12
  export const to_hash = async (data, algorithm = 'SHA-256') => {
6
- const digested = await subtle.digest(algorithm, data);
13
+ const buffer = typeof data === 'string' ? encoder.encode(data) : data;
14
+ const digested = await subtle.digest(algorithm, buffer);
7
15
  const bytes = Array.from(new Uint8Array(digested));
8
16
  let hex = '';
9
17
  for (const h of bytes) {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** @nodocs */
2
2
  export type { GroConfig, CreateGroConfig, RawGroConfig } from './gro_config.ts';
3
3
  /** @nodocs */
4
- export { type Plugin, replace_plugin } from './plugin.ts';
4
+ export { type Plugin, plugin_replace } from './plugin.ts';
5
5
  /** @nodocs */
6
6
  export type { Gen, GenContext } from './gen.ts';
7
7
  /** @nodocs */
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /** @nodocs */
2
- export { replace_plugin } from "./plugin.js";
2
+ export { plugin_replace } from "./plugin.js";
3
3
  /** @nodocs */
4
4
  export { TaskError } from "./task.js";
@@ -4,7 +4,6 @@ export type PackageJsonMapper = (package_json: PackageJson) => PackageJson | nul
4
4
  export declare const PACKAGE_JSON_EMPTY: PackageJson;
5
5
  export declare const package_json_load: (dir?: string, cache?: Record<string, PackageJson>, parse?: boolean, // TODO pass `false` here in more places, especially anything perf-sensitive like work on startup
6
6
  log?: Logger) => Promise<PackageJson>;
7
- export declare const load_package_json: (dir?: string, cache?: Record<string, PackageJson>, parse?: boolean, log?: Logger) => Promise<PackageJson>;
8
7
  export declare const package_json_sync: (map_package_json: PackageJsonMapper, log: Logger, write?: boolean, dir?: string, exports_dir?: string) => Promise<{
9
8
  package_json: PackageJson | null;
10
9
  changed: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"package_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/package_json.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,kCAAkC,CAAC;AAgBjF,MAAM,MAAM,iBAAiB,GAAG,CAC/B,YAAY,EAAE,WAAW,KACrB,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAEtD,eAAO,MAAM,kBAAkB,EAAE,WAAqC,CAAC;AAEvE,eAAO,MAAM,iBAAiB,GAC7B,YAA+C,EAC/C,QAAQ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,eAAY,EAAE,iGAAiG;AAC/G,MAAM,MAAM,KACV,OAAO,CAAC,WAAW,CAkBrB,CAAC;AAGF,eAAO,MAAM,iBAAiB,yBAxBrB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,yBAE7B,MAAM,KACV,OAAO,CAAC,WAAW,CAqB4B,CAAC;AAEnD,eAAO,MAAM,iBAAiB,GAC7B,kBAAkB,iBAAiB,EACnC,KAAK,MAAM,EACX,eAAY,EACZ,YAAgB,EAChB,oBAAuB,KACrB,OAAO,CAAC;IAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CA0B9D,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAO,OAAO,CAAC,WAAW,CAC9B,CAAC;AAMnC,eAAO,MAAM,kBAAkB,GAAI,yBAAyB,MAAM,KAAG,OAAO,CAAC,IAAI,CACL,CAAC;AAE7E,eAAO,MAAM,sBAAsB,GAAI,cAAc,WAAW,KAAG,MACW,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC/B,QAAQ,CAAC,YAAY,EAAE,WAAW,KAAK,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,EACvF,YAAgB,EAChB,eAAY,KACV,OAAO,CAAC;IAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAa9D,CAAC;AAIF,eAAO,MAAM,uBAAuB,GAAI,OAAO,KAAK,CAAC,MAAM,CAAC,KAAG,kBAmD9D,CAAC;AAIF,eAAO,MAAM,2BAA2B,GACvC,cAAc,WAAW,KACvB;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG,SAgBlC,CAAC;AA8BF,eAAO,MAAM,2BAA2B,GAAI,UAAU,MAAM,EAAE,cAAc,WAAW,KAAG,OAG9C,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iCAAiC,GAC7C,cAAc,WAAW,KACvB,KAAK,CAAC,cAAc,CAetB,CAAC"}
1
+ {"version":3,"file":"package_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/package_json.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,kCAAkC,CAAC;AAgBjF,MAAM,MAAM,iBAAiB,GAAG,CAC/B,YAAY,EAAE,WAAW,KACrB,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAEtD,eAAO,MAAM,kBAAkB,EAAE,WAAqC,CAAC;AAEvE,eAAO,MAAM,iBAAiB,GAC7B,YAA+C,EAC/C,QAAQ,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,eAAY,EAAE,iGAAiG;AAC/G,MAAM,MAAM,KACV,OAAO,CAAC,WAAW,CAkBrB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC7B,kBAAkB,iBAAiB,EACnC,KAAK,MAAM,EACX,eAAY,EACZ,YAAgB,EAChB,oBAAuB,KACrB,OAAO,CAAC;IAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CA0B9D,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAO,OAAO,CAAC,WAAW,CAC9B,CAAC;AAMnC,eAAO,MAAM,kBAAkB,GAAI,yBAAyB,MAAM,KAAG,OAAO,CAAC,IAAI,CACL,CAAC;AAE7E,eAAO,MAAM,sBAAsB,GAAI,cAAc,WAAW,KAAG,MACW,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC/B,QAAQ,CAAC,YAAY,EAAE,WAAW,KAAK,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,EACvF,YAAgB,EAChB,eAAY,KACV,OAAO,CAAC;IAAC,YAAY,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAa9D,CAAC;AAIF,eAAO,MAAM,uBAAuB,GAAI,OAAO,KAAK,CAAC,MAAM,CAAC,KAAG,kBAmD9D,CAAC;AAIF,eAAO,MAAM,2BAA2B,GACvC,cAAc,WAAW,KACvB;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG,SAgBlC,CAAC;AA8BF,eAAO,MAAM,2BAA2B,GAAI,UAAU,MAAM,EAAE,cAAc,WAAW,KAAG,OAG9C,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iCAAiC,GAC7C,cAAc,WAAW,KACvB,KAAK,CAAC,cAAc,CAetB,CAAC"}
@@ -31,8 +31,6 @@ log) => {
31
31
  }
32
32
  return package_json;
33
33
  };
34
- // TODO remove
35
- export const load_package_json = package_json_load;
36
34
  export const package_json_sync = async (map_package_json, log, write = true, dir = paths.root, exports_dir = paths.lib) => {
37
35
  const exported_files = await fs_search(exports_dir);
38
36
  const exported_paths = exported_files.map((f) => f.path);
package/dist/plugin.d.ts CHANGED
@@ -9,7 +9,7 @@ export interface Plugin<TPluginContext extends PluginContext = PluginContext> {
9
9
  adapt?: (ctx: TPluginContext) => void | Promise<void>;
10
10
  teardown?: (ctx: TPluginContext) => void | Promise<void>;
11
11
  }
12
- export type CreateConfigPlugins<TPluginContext extends PluginContext = PluginContext> = (ctx: TPluginContext) => Array<Plugin<TPluginContext>> | Promise<Array<Plugin<TPluginContext>>>;
12
+ export type PluginsCreateConfig<TPluginContext extends PluginContext = PluginContext> = (ctx: TPluginContext) => Array<Plugin<TPluginContext>> | Promise<Array<Plugin<TPluginContext>>>;
13
13
  export interface PluginContext<TArgs = object> extends TaskContext<TArgs> {
14
14
  dev: boolean;
15
15
  watch: boolean;
@@ -27,10 +27,10 @@ export declare class Plugins<TPluginContext extends PluginContext> {
27
27
  /**
28
28
  * Replaces a plugin by name in `plugins` without mutating the param.
29
29
  * Throws if the plugin name cannot be found.
30
- * @param plugins - accepts the same types as the return value of `CreateConfigPlugins`
30
+ * @param plugins - accepts the same types as the return value of `PluginsCreateConfig`
31
31
  * @param new_plugin
32
32
  * @param name - @default new_plugin.name
33
33
  * @returns `plugins` with `new_plugin` at the index of the plugin with `name`
34
34
  */
35
- export declare const replace_plugin: (plugins: Array<Plugin>, new_plugin: Plugin, name?: string) => Array<Plugin>;
35
+ export declare const plugin_replace: (plugins: Array<Plugin>, new_plugin: Plugin, name?: string) => Array<Plugin>;
36
36
  //# sourceMappingURL=plugin.d.ts.map
package/dist/plugin.js CHANGED
@@ -63,12 +63,12 @@ export class Plugins {
63
63
  /**
64
64
  * Replaces a plugin by name in `plugins` without mutating the param.
65
65
  * Throws if the plugin name cannot be found.
66
- * @param plugins - accepts the same types as the return value of `CreateConfigPlugins`
66
+ * @param plugins - accepts the same types as the return value of `PluginsCreateConfig`
67
67
  * @param new_plugin
68
68
  * @param name - @default new_plugin.name
69
69
  * @returns `plugins` with `new_plugin` at the index of the plugin with `name`
70
70
  */
71
- export const replace_plugin = (plugins, new_plugin, name = new_plugin.name) => {
71
+ export const plugin_replace = (plugins, new_plugin, name = new_plugin.name) => {
72
72
  const index = plugins.findIndex((p) => p.name === name);
73
73
  if (index === -1)
74
74
  throw Error('Failed to find plugin to replace: ' + name);
@@ -3,6 +3,8 @@ import { type Task } from './task.ts';
3
3
  /**
4
4
  * Runs a TypeScript file with Gro's loader, forwarding all args to the script.
5
5
  * Useful for scripts that need SvelteKit shims ($lib, $env, etc).
6
+ *
7
+ * @module
6
8
  */
7
9
  /** @nodocs */
8
10
  export declare const Args: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"run.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/run.task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAItB,OAAO,EAAY,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAI/C;;;GAGG;AAEH,cAAc;AACd,eAAO,MAAM,IAAI;;8JAWf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,cAAc;AACd,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CA+B3B,CAAC"}
1
+ {"version":3,"file":"run.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/run.task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAItB,OAAO,EAAY,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAI/C;;;;;GAKG;AAEH,cAAc;AACd,eAAO,MAAM,IAAI;;8JAWf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,cAAc;AACd,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CA+B3B,CAAC"}
package/dist/run.task.js CHANGED
@@ -7,6 +7,8 @@ import { serialize_args, to_implicit_forwarded_args } from "./args.js";
7
7
  /**
8
8
  * Runs a TypeScript file with Gro's loader, forwarding all args to the script.
9
9
  * Useful for scripts that need SvelteKit shims ($lib, $env, etc).
10
+ *
11
+ * @module
10
12
  */
11
13
  /** @nodocs */
12
14
  export const Args = z
@@ -3,5 +3,5 @@ import { SourceJson, type ModuleJson } from '@fuzdev/fuz_util/source_json.js';
3
3
  import type { Logger } from '@fuzdev/fuz_util/log.js';
4
4
  export type SourceJsonMapper = (source_json: SourceJson) => SourceJson | null | Promise<SourceJson | null>;
5
5
  export declare const source_json_create: (package_json: PackageJson, lib_path?: string, log?: Logger) => Promise<SourceJson>;
6
- export declare const source_modules_create: (exports: PackageJsonExports | undefined, lib_path?: string, log?: Logger) => Promise<Array<ModuleJson> | undefined>;
6
+ export declare const source_json_modules_create: (exports: PackageJsonExports | undefined, lib_path?: string, log?: Logger) => Promise<Array<ModuleJson> | undefined>;
7
7
  //# sourceMappingURL=source_json.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"source_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/source_json.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,kCAAkC,CAAC;AACtF,OAAO,EAAC,UAAU,EAAE,KAAK,UAAU,EAAuB,MAAM,iCAAiC,CAAC;AAClG,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAMpD,MAAM,MAAM,gBAAgB,GAAG,CAC9B,WAAW,EAAE,UAAU,KACnB,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;AAEpD,eAAO,MAAM,kBAAkB,GAC9B,cAAc,WAAW,EACzB,WAAW,MAAM,EACjB,MAAM,MAAM,KACV,OAAO,CAAC,UAAU,CAKlB,CAAC;AAEJ,eAAO,MAAM,qBAAqB,GACjC,SAAS,kBAAkB,GAAG,SAAS,EACvC,iBAAoB,EACpB,MAAM,MAAM,KACV,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,SAAS,CAgDvC,CAAC"}
1
+ {"version":3,"file":"source_json.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/source_json.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,WAAW,EAAE,kBAAkB,EAAC,MAAM,kCAAkC,CAAC;AACtF,OAAO,EAAC,UAAU,EAAE,KAAK,UAAU,EAAuB,MAAM,iCAAiC,CAAC;AAClG,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAMpD,MAAM,MAAM,gBAAgB,GAAG,CAC9B,WAAW,EAAE,UAAU,KACnB,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;AAEpD,eAAO,MAAM,kBAAkB,GAC9B,cAAc,WAAW,EACzB,WAAW,MAAM,EACjB,MAAM,MAAM,KACV,OAAO,CAAC,UAAU,CAKlB,CAAC;AAEJ,eAAO,MAAM,0BAA0B,GACtC,SAAS,kBAAkB,GAAG,SAAS,EACvC,iBAAoB,EACpB,MAAM,MAAM,KACV,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,SAAS,CAgDvC,CAAC"}
@@ -9,9 +9,9 @@ import { TS_MATCHER, SVELTE_MATCHER, JSON_MATCHER, CSS_MATCHER } from "./constan
9
9
  export const source_json_create = async (package_json, lib_path, log) => SourceJson.parse({
10
10
  name: package_json.name,
11
11
  version: package_json.version,
12
- modules: await source_modules_create(package_json.exports, lib_path, log),
12
+ modules: await source_json_modules_create(package_json.exports, lib_path, log),
13
13
  });
14
- export const source_modules_create = async (exports, lib_path = paths.lib, log) => {
14
+ export const source_json_modules_create = async (exports, lib_path = paths.lib, log) => {
15
15
  if (!exports)
16
16
  return;
17
17
  const file_paths = await collect_file_paths(exports, lib_path);
@@ -3,6 +3,8 @@
3
3
  * but exists here for the sake of the Node loader.
4
4
  * There may be a cleaner workaround but I couldn't find it.
5
5
  * @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
6
+ *
7
+ * @module
6
8
  */
7
9
  export declare const browser = false;
8
10
  export declare const building = false;
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit_shim_app_environment.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/sveltekit_shim_app_environment.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,QAAQ,CAAC;AAC7B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,GAAG,OAAO,CAAC;AACxB,eAAO,MAAM,OAAO,SAAS,CAAC"}
1
+ {"version":3,"file":"sveltekit_shim_app_environment.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/sveltekit_shim_app_environment.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,eAAO,MAAM,OAAO,QAAQ,CAAC;AAC7B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,GAAG,OAAO,CAAC;AACxB,eAAO,MAAM,OAAO,SAAS,CAAC"}
@@ -5,6 +5,8 @@
5
5
  * but exists here for the sake of the Node loader.
6
6
  * There may be a cleaner workaround but I couldn't find it.
7
7
  * @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
8
+ *
9
+ * @module
8
10
  */
9
11
  export const browser = false;
10
12
  export const building = false;
@@ -3,6 +3,8 @@
3
3
  * but exists here for the sake of the Node loader.
4
4
  * There may be a cleaner workaround but I couldn't find it.
5
5
  * @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
6
+ *
7
+ * @module
6
8
  */
7
9
  import type { resolve as base_resolve, asset as base_asset, resolveRoute as base_resolveRoute } from '$app/paths';
8
10
  export declare const assets = "";
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit_shim_app_paths.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/sveltekit_shim_app_paths.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,KAAK,EACX,OAAO,IAAI,YAAY,EACvB,KAAK,IAAI,UAAU,EACnB,YAAY,IAAI,iBAAiB,EACjC,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,MAAM,KAAK,CAAC;AACzB,kBAAkB;AAClB,eAAO,MAAM,IAAI,KAAK,CAAC;AACvB,eAAO,MAAM,OAAO,EAAE,OAAO,YAAmE,CAAC;AACjG,kBAAkB;AAClB,eAAO,MAAM,YAAY,EAAE,OAAO,iBAAwB,CAAC;AAC3D,eAAO,MAAM,KAAK,EAAE,OAAO,UAAuD,CAAC"}
1
+ {"version":3,"file":"sveltekit_shim_app_paths.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/sveltekit_shim_app_paths.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACX,OAAO,IAAI,YAAY,EACvB,KAAK,IAAI,UAAU,EACnB,YAAY,IAAI,iBAAiB,EACjC,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,MAAM,KAAK,CAAC;AACzB,kBAAkB;AAClB,eAAO,MAAM,IAAI,KAAK,CAAC;AACvB,eAAO,MAAM,OAAO,EAAE,OAAO,YAAmE,CAAC;AACjG,kBAAkB;AAClB,eAAO,MAAM,YAAY,EAAE,OAAO,iBAAwB,CAAC;AAC3D,eAAO,MAAM,KAAK,EAAE,OAAO,UAAuD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryanatkn/gro",
3
- "version": "0.183.0",
3
+ "version": "0.185.0",
4
4
  "description": "task runner and toolkit extending SvelteKit",
5
5
  "motto": "generate, run, optimize",
6
6
  "glyph": "🌰",
@@ -53,8 +53,8 @@
53
53
  "esm-env": "^1.2.2",
54
54
  "mri": "^1.2.0",
55
55
  "oxc-parser": "^0.99.0",
56
- "prettier": "^3.6.2",
57
- "prettier-plugin-svelte": "^3.4.0",
56
+ "prettier": "^3.7.4",
57
+ "prettier-plugin-svelte": "^3.4.1",
58
58
  "ts-blank-space": "^0.6.2",
59
59
  "tslib": "^2.8.1",
60
60
  "zod": "^4.1.13"
@@ -83,8 +83,8 @@
83
83
  "@changesets/types": "^6.1.0",
84
84
  "@fuzdev/fuz_code": "^0.38.0",
85
85
  "@fuzdev/fuz_css": "^0.42.1",
86
- "@fuzdev/fuz_ui": "^0.173.0",
87
- "@fuzdev/fuz_util": "^0.45.0",
86
+ "@fuzdev/fuz_ui": "^0.177.0",
87
+ "@fuzdev/fuz_util": "^0.45.3",
88
88
  "@ryanatkn/eslint-config": "^0.9.0",
89
89
  "@sveltejs/adapter-static": "^3.0.10",
90
90
  "@sveltejs/kit": "^2.49.1",
@@ -16,6 +16,11 @@ export interface Disknode {
16
16
  external: boolean;
17
17
  ctime: number | null;
18
18
  mtime: number | null;
19
+ /**
20
+ * SHA-256 hash of `contents`. `null` iff `contents` is `null`.
21
+ * Used for content-based change detection and caching.
22
+ */
23
+ content_hash: string | null;
19
24
  dependents: Map<PathId, Disknode>;
20
25
  dependencies: Map<PathId, Disknode>;
21
26
  }
package/src/lib/filer.ts CHANGED
@@ -23,6 +23,7 @@ import {default_svelte_config} from './svelte_config.ts';
23
23
  import {map_sveltekit_aliases} from './sveltekit_helpers.ts';
24
24
  import {SVELTEKIT_GLOBAL_SPECIFIER} from './constants.ts';
25
25
  import type {Disknode} from './disknode.ts';
26
+ import {to_hash} from './hash.ts';
26
27
 
27
28
  const aliases = Object.entries(default_svelte_config.alias);
28
29
 
@@ -81,6 +82,7 @@ export class Filer {
81
82
  external: this.#is_external(id), // TODO maybe filter externals by default? the user needs to configure the filer then
82
83
  ctime: null,
83
84
  mtime: null,
85
+ content_hash: null,
84
86
  dependents: new Map(),
85
87
  dependencies: new Map(),
86
88
  };
@@ -242,15 +244,19 @@ export class Filer {
242
244
  }
243
245
  }
244
246
 
245
- const old_mtime = file.mtime;
247
+ // Compute hash for new contents
248
+ const new_hash = new_contents !== null ? await to_hash(new_contents) : null;
249
+
246
250
  file.ctime = stats?.ctimeMs ?? null;
247
251
  file.mtime = stats?.mtimeMs ?? null;
248
252
 
249
- if (file.mtime === old_mtime && file.contents === new_contents) {
253
+ // Use hash comparison for change detection (content-based, not mtime-based)
254
+ if (file.content_hash === new_hash) {
250
255
  return null;
251
256
  }
252
257
 
253
258
  file.contents = new_contents;
259
+ file.content_hash = new_hash;
254
260
 
255
261
  const dir = dirname(file.id);
256
262
 
@@ -308,6 +314,7 @@ export class Filer {
308
314
  if (!file) return null; // this is safe because the object would exist if any other file referenced it as a dependency or dependent
309
315
 
310
316
  file.contents = null; // clear contents in case it gets re-added later, we want the change to be detected
317
+ file.content_hash = null; // clear hash so re-add detects the change
311
318
 
312
319
  file.dependencies.clear();
313
320
 
package/src/lib/gen.ts CHANGED
@@ -5,7 +5,7 @@ import type {Result} from '@fuzdev/fuz_util/result.js';
5
5
  import type {Timings} from '@fuzdev/fuz_util/timings.js';
6
6
  import {styleText as st} from 'node:util';
7
7
  import type {PathId} from '@fuzdev/fuz_util/path.js';
8
- import {map_concurrent} from '@fuzdev/fuz_util/async.js';
8
+ import {each_concurrent, map_concurrent} from '@fuzdev/fuz_util/async.js';
9
9
  import {fs_search} from '@fuzdev/fuz_util/fs.js';
10
10
 
11
11
  import {print_path} from './paths.ts';
@@ -246,7 +246,7 @@ export const write_gen_results = async (
246
246
  log: Logger,
247
247
  ): Promise<void> => {
248
248
  const files = gen_results.successes.flatMap((result) => result.files);
249
- await map_concurrent(
249
+ await each_concurrent(
250
250
  files,
251
251
  async (file) => {
252
252
  const analyzed = analyzed_gen_results.find((r) => r.file.id === file.id);
@@ -15,7 +15,7 @@ import {
15
15
  SVELTEKIT_DIST_DIRNAME,
16
16
  } from './constants.ts';
17
17
  import create_default_config from './gro.config.default.ts';
18
- import type {CreateConfigPlugins} from './plugin.ts';
18
+ import type {PluginsCreateConfig} from './plugin.ts';
19
19
  import type {PackageJsonMapper} from './package_json.ts';
20
20
  import type {ParsedSvelteConfig} from './svelte_config.ts';
21
21
  import {to_hash} from './hash.ts';
@@ -36,7 +36,7 @@ export interface GroConfig extends RawGroConfig {
36
36
  /**
37
37
  * @see https://github.com/ryanatkn/gro/blob/main/src/docs/plugin.md
38
38
  */
39
- plugins: CreateConfigPlugins;
39
+ plugins: PluginsCreateConfig;
40
40
  /**
41
41
  * Maps the project's `package.json` before writing it to the filesystem.
42
42
  * The `package_json` argument may be mutated, but the return value is what's used by the caller.
@@ -78,7 +78,7 @@ export interface GroConfig extends RawGroConfig {
78
78
  * @see https://github.com/ryanatkn/gro/blob/main/src/docs/config.md
79
79
  */
80
80
  export interface RawGroConfig {
81
- plugins?: CreateConfigPlugins;
81
+ plugins?: PluginsCreateConfig;
82
82
  map_package_json?: PackageJsonMapper | null;
83
83
  task_root_dirs?: Array<string>;
84
84
  search_filters?: PathFilter | Array<PathFilter> | null;
@@ -175,9 +175,7 @@ export const cook_gro_config = async (raw_config: RawGroConfig): Promise<GroConf
175
175
  typeof build_cache_config === 'function' ? await build_cache_config() : build_cache_config;
176
176
 
177
177
  // Hash the JSON representation with deterministic key ordering
178
- build_cache_config_hash = await to_hash(
179
- new TextEncoder().encode(json_stringify_deterministic(resolved)),
180
- );
178
+ build_cache_config_hash = await to_hash(json_stringify_deterministic(resolved));
181
179
  }
182
180
 
183
181
  // Delete the raw value to ensure it doesn't persist in memory
package/src/lib/hash.ts CHANGED
@@ -1,13 +1,22 @@
1
1
  const {subtle} = globalThis.crypto;
2
2
 
3
+ const encoder = new TextEncoder();
4
+
3
5
  /**
6
+ * Computes a cryptographic hash of the given data.
7
+ *
8
+ * @param data - String or binary data to hash. Strings are UTF-8 encoded internally.
9
+ * @param algorithm - Hash algorithm to use. Defaults to SHA-256.
10
+ * @returns Hexadecimal hash string.
11
+ *
4
12
  * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
5
13
  */
6
14
  export const to_hash = async (
7
- data: BufferSource,
15
+ data: BufferSource | string,
8
16
  algorithm: 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512' = 'SHA-256',
9
17
  ): Promise<string> => {
10
- const digested = await subtle.digest(algorithm, data);
18
+ const buffer = typeof data === 'string' ? encoder.encode(data) : data;
19
+ const digested = await subtle.digest(algorithm, buffer);
11
20
  const bytes = Array.from(new Uint8Array(digested));
12
21
  let hex = '';
13
22
  for (const h of bytes) {
package/src/lib/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** @nodocs */
2
2
  export type {GroConfig, CreateGroConfig, RawGroConfig} from './gro_config.ts';
3
3
  /** @nodocs */
4
- export {type Plugin, replace_plugin} from './plugin.ts';
4
+ export {type Plugin, plugin_replace} from './plugin.ts';
5
5
  /** @nodocs */
6
6
  export type {Gen, GenContext} from './gen.ts';
7
7
  /** @nodocs */
@@ -51,9 +51,6 @@ export const package_json_load = async (
51
51
  return package_json;
52
52
  };
53
53
 
54
- // TODO remove
55
- export const load_package_json = package_json_load;
56
-
57
54
  export const package_json_sync = async (
58
55
  map_package_json: PackageJsonMapper,
59
56
  log: Logger,
package/src/lib/plugin.ts CHANGED
@@ -11,7 +11,7 @@ export interface Plugin<TPluginContext extends PluginContext = PluginContext> {
11
11
  teardown?: (ctx: TPluginContext) => void | Promise<void>;
12
12
  }
13
13
 
14
- export type CreateConfigPlugins<TPluginContext extends PluginContext = PluginContext> = (
14
+ export type PluginsCreateConfig<TPluginContext extends PluginContext = PluginContext> = (
15
15
  ctx: TPluginContext,
16
16
  ) => Array<Plugin<TPluginContext>> | Promise<Array<Plugin<TPluginContext>>>;
17
17
 
@@ -88,12 +88,12 @@ export class Plugins<TPluginContext extends PluginContext> {
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 `CreateConfigPlugins`
91
+ * @param plugins - accepts the same types as the return value of `PluginsCreateConfig`
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`
95
95
  */
96
- export const replace_plugin = (
96
+ export const plugin_replace = (
97
97
  plugins: Array<Plugin>,
98
98
  new_plugin: Plugin,
99
99
  name = new_plugin.name,
@@ -9,6 +9,8 @@ import {serialize_args, to_implicit_forwarded_args} from './args.ts';
9
9
  /**
10
10
  * Runs a TypeScript file with Gro's loader, forwarding all args to the script.
11
11
  * Useful for scripts that need SvelteKit shims ($lib, $env, etc).
12
+ *
13
+ * @module
12
14
  */
13
15
 
14
16
  /** @nodocs */
@@ -22,10 +22,10 @@ export const source_json_create = async (
22
22
  SourceJson.parse({
23
23
  name: package_json.name,
24
24
  version: package_json.version,
25
- modules: await source_modules_create(package_json.exports, lib_path, log),
25
+ modules: await source_json_modules_create(package_json.exports, lib_path, log),
26
26
  });
27
27
 
28
- export const source_modules_create = async (
28
+ export const source_json_modules_create = async (
29
29
  exports: PackageJsonExports | undefined,
30
30
  lib_path = paths.lib,
31
31
  log?: Logger,
@@ -6,6 +6,8 @@
6
6
  * but exists here for the sake of the Node loader.
7
7
  * There may be a cleaner workaround but I couldn't find it.
8
8
  * @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
9
+ *
10
+ * @module
9
11
  */
10
12
 
11
13
  export const browser = false;
@@ -6,6 +6,8 @@
6
6
  * but exists here for the sake of the Node loader.
7
7
  * There may be a cleaner workaround but I couldn't find it.
8
8
  * @see https://github.com/nodejs/loaders for details about the forthcoming virtual file support
9
+ *
10
+ * @module
9
11
  */
10
12
 
11
13
  import type {