@ryanatkn/gro 0.146.2 → 0.147.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.
@@ -1 +1 @@
1
- {"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAGzD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AACvC,OAAO,EACN,SAAS,EAET,KAAK,cAAc,EACnB,KAAK,iBAAiB,EAEtB,MAAM,gBAAgB,CAAC;AAQxB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAIpD,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ;;;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,OAAO,EAAE,WAAW,CAAC,CAAC;IACtC,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;AAEzF,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;CAClD;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAa;gBAO1C,OAAO,GAAE,aAA4B;IAYjD,SAAS,OAAQ,OAAO,KAAG,WAAW,GAAG,SAAS,CAEhD;IAEF,aAAa,OAAQ,OAAO,KAAG,WAAW,CAkBxC;IAmII,KAAK,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC;IAKxD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAa5B"}
1
+ {"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAMzD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AACvC,OAAO,EACN,SAAS,EAET,KAAK,cAAc,EACnB,KAAK,iBAAiB,EAEtB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAIpD,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ;;;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,OAAO,EAAE,WAAW,CAAC,CAAC;IACtC,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC;AAEzF,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;CAClD;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAa;gBAK1C,OAAO,GAAE,aAA4B;IAWjD,SAAS,OAAQ,OAAO,KAAG,WAAW,GAAG,SAAS,CAEhD;IAEF,aAAa,OAAQ,OAAO,KAAG,WAAW,CAkBxC;IA4II,KAAK,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC;IAKxD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAa5B"}
package/dist/filer.js CHANGED
@@ -2,26 +2,25 @@ import { EMPTY_OBJECT } from '@ryanatkn/belt/object.js';
2
2
  import { existsSync, readFileSync, statSync } from 'node:fs';
3
3
  import { dirname, resolve } from 'node:path';
4
4
  import { wait } from '@ryanatkn/belt/async.js';
5
+ import { isBuiltin } from 'node:module';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { Unreachable_Error } from '@ryanatkn/belt/error.js';
5
8
  import { watch_dir, } from './watch_dir.js';
6
9
  import { paths } from './paths.js';
7
10
  import { parse_imports } from './parse_imports.js';
8
11
  import { resolve_specifier } from './resolve_specifier.js';
9
12
  import { default_sveltekit_config } from './sveltekit_config.js';
10
- import { map_sveltekit_aliases } from './sveltekit_helpers.js';
11
- import { Unreachable_Error } from '@ryanatkn/belt/error.js';
12
- import { resolve_node_specifier } from './resolve_node_specifier.js';
13
+ import { map_sveltekit_aliases, SVELTEKIT_GLOBAL_SPECIFIER } from './sveltekit_helpers.js';
13
14
  const aliases = Object.entries(default_sveltekit_config.alias);
14
15
  export class Filer {
15
16
  root_dir;
16
17
  files = new Map();
17
18
  #watch_dir;
18
19
  #watch_dir_options;
19
- #package_json_cache;
20
20
  constructor(options = EMPTY_OBJECT) {
21
21
  this.#watch_dir = options.watch_dir ?? watch_dir;
22
22
  this.#watch_dir_options = options.watch_dir_options ?? EMPTY_OBJECT;
23
23
  this.root_dir = resolve(options.watch_dir_options?.dir ?? paths.source);
24
- this.#package_json_cache = options.package_json_cache ?? {};
25
24
  }
26
25
  #watching;
27
26
  #listeners = new Set();
@@ -64,15 +63,28 @@ export class Filer {
64
63
  const dependencies_removed = new Set(dependencies_before);
65
64
  const imported = file.contents ? parse_imports(file.id, file.contents) : [];
66
65
  for (const specifier of imported) {
67
- // TODO logic is duplicated from loader
66
+ if (SVELTEKIT_GLOBAL_SPECIFIER.test(specifier))
67
+ continue;
68
68
  const path = map_sveltekit_aliases(specifier, aliases);
69
- // The specifier `path` has now been mapped to its final form, so we can inspect it.
70
- const resolved = path[0] === '.' || path[0] === '/'
71
- ? resolve_specifier(path, dir)
72
- : resolve_node_specifier(path, undefined, file.id, this.#package_json_cache, false);
73
- if (!resolved)
74
- continue; // ignore any missing imports like Node identifiers
75
- const { path_id } = resolved;
69
+ let path_id;
70
+ if (path[0] === '.' || path[0] === '/') {
71
+ const resolved = resolve_specifier(path, dir);
72
+ path_id = resolved.path_id;
73
+ }
74
+ else {
75
+ if (isBuiltin(path))
76
+ continue;
77
+ try {
78
+ path_id = fileURLToPath(import.meta.resolve(path, file.id));
79
+ }
80
+ catch (error) {
81
+ // If it's imported from an external module, ignore any import errors.
82
+ if (error.code === 'ERR_MODULE_NOT_FOUND' && file.external) {
83
+ continue;
84
+ }
85
+ throw error;
86
+ }
87
+ }
76
88
  dependencies_removed.delete(path_id);
77
89
  if (!dependencies_before.has(path_id)) {
78
90
  const d = this.get_or_create(path_id);
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"../src/lib/","sources":["loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,QAAQ,EAAE,WAAW,EAAC,MAAM,aAAa,CAAC;AAgFvD,eAAO,MAAM,IAAI,EAAE,QAwFlB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WA6DrB,CAAC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"../src/lib/","sources":["loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,QAAQ,EAAE,WAAW,EAAC,MAAM,aAAa,CAAC;AA4EvD,eAAO,MAAM,IAAI,EAAE,QAwFlB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,WAoDrB,CAAC"}
package/dist/loader.js CHANGED
@@ -12,7 +12,6 @@ import { IS_THIS_GRO, paths } from './paths.js';
12
12
  import { JSON_MATCHER, NODE_MODULES_DIRNAME, TS_MATCHER } from './constants.js';
13
13
  import { to_define_import_meta_env, default_ts_transform_options } from './esbuild_helpers.js';
14
14
  import { resolve_specifier } from './resolve_specifier.js';
15
- import { resolve_node_specifier } from './resolve_node_specifier.js';
16
15
  import { map_sveltekit_aliases } from './sveltekit_helpers.js';
17
16
  /*
18
17
 
@@ -52,7 +51,6 @@ const aliases = Object.entries(alias);
52
51
  const RAW_MATCHER = /(%3Fraw|\.css|\.svg)$/; // TODO others? configurable?
53
52
  const ENV_MATCHER = /src\/lib\/\$env\/(static|dynamic)\/(public|private)$/;
54
53
  const NODE_MODULES_MATCHER = new RegExp(escape_regexp('/' + NODE_MODULES_DIRNAME + '/'), 'u');
55
- const package_json_cache = {};
56
54
  export const load = async (url, context, nextLoad) => {
57
55
  if (SVELTEKIT_SHIM_APP_PATHS_MATCHER.test(url)) {
58
56
  // SvelteKit `$app/paths` shim
@@ -162,20 +160,9 @@ export const resolve = async (specifier, context, nextResolve) => {
162
160
  }
163
161
  s = map_sveltekit_aliases(s, aliases);
164
162
  // The specifier has now been mapped to its final form, so we can inspect it.
163
+ // Imports into `node_modules` use the default algorithm, and the rest use use Vite conventions.
165
164
  if (s[0] !== '.' && s[0] !== '/') {
166
- // Resolve to `node_modules`.
167
- if (SVELTE_MATCHER.test(s) || JSON_MATCHER.test(s)) {
168
- // Match the behavior of Vite and esbuild for Svelte and JSON imports.
169
- const resolved = resolve_node_specifier(s, dir, parent_url, package_json_cache); // `node:` specifiers shouldn't reach this point, so the assertion is safe
170
- return {
171
- url: pathToFileURL(resolved.path_id_with_querystring).href,
172
- format: 'module',
173
- shortCircuit: true,
174
- };
175
- }
176
- else {
177
- return nextResolve(s, context);
178
- }
165
+ return nextResolve(s, context);
179
166
  }
180
167
  const resolved = resolve_specifier(s, dirname(fileURLToPath(parent_url)));
181
168
  return {
package/dist/package.d.ts CHANGED
@@ -333,10 +333,6 @@ export declare const package_json: {
333
333
  types: string;
334
334
  default: string;
335
335
  };
336
- './resolve_node_specifier.js': {
337
- types: string;
338
- default: string;
339
- };
340
336
  './resolve_specifier.js': {
341
337
  types: string;
342
338
  default: string;
@@ -965,13 +961,6 @@ export declare const src_json: {
965
961
  kind: "variable";
966
962
  }[];
967
963
  };
968
- './resolve_node_specifier.js': {
969
- path: string;
970
- declarations: {
971
- name: string;
972
- kind: "function";
973
- }[];
974
- };
975
964
  './resolve_specifier.js': {
976
965
  path: string;
977
966
  declarations: ({
@@ -1 +1 @@
1
- {"version":3,"file":"package.d.ts","sourceRoot":"../src/lib/","sources":["package.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuQD,CAAC;AAEzB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0wBD,CAAC"}
1
+ {"version":3,"file":"package.d.ts","sourceRoot":"../src/lib/","sources":["package.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmQD,CAAC;AAEzB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuwBD,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.146.2',
4
+ version: '0.147.1',
5
5
  description: 'task runner and toolkit extending SvelteKit',
6
6
  motto: 'generate, run, optimize',
7
7
  glyph: '🌰',
@@ -196,10 +196,6 @@ export const package_json = {
196
196
  default: './dist/reinstall.task.js',
197
197
  },
198
198
  './release.task.js': { types: './dist/release.task.d.ts', default: './dist/release.task.js' },
199
- './resolve_node_specifier.js': {
200
- types: './dist/resolve_node_specifier.d.ts',
201
- default: './dist/resolve_node_specifier.js',
202
- },
203
199
  './resolve_specifier.js': {
204
200
  types: './dist/resolve_specifier.d.ts',
205
201
  default: './dist/resolve_specifier.js',
@@ -264,7 +260,7 @@ export const package_json = {
264
260
  };
265
261
  export const src_json = {
266
262
  name: '@ryanatkn/gro',
267
- version: '0.146.2',
263
+ version: '0.147.1',
268
264
  modules: {
269
265
  '.': {
270
266
  path: 'index.ts',
@@ -810,10 +806,6 @@ export const src_json = {
810
806
  { name: 'task', kind: 'variable' },
811
807
  ],
812
808
  },
813
- './resolve_node_specifier.js': {
814
- path: 'resolve_node_specifier.ts',
815
- declarations: [{ name: 'resolve_node_specifier', kind: 'function' }],
816
- },
817
809
  './resolve_specifier.js': {
818
810
  path: 'resolve_specifier.ts',
819
811
  declarations: [
@@ -895,6 +887,7 @@ export const src_json = {
895
887
  { name: 'SVELTE_PACKAGE_DEP_NAME', kind: 'variable' },
896
888
  { name: 'VITE_CLI', kind: 'variable' },
897
889
  { name: 'SVELTEKIT_ENV_MATCHER', kind: 'variable' },
890
+ { name: 'SVELTEKIT_GLOBAL_SPECIFIER', kind: 'variable' },
898
891
  { name: 'has_sveltekit_app', kind: 'function' },
899
892
  { name: 'has_sveltekit_library', kind: 'function' },
900
893
  { name: 'sveltekit_sync', kind: 'function' },
@@ -9,6 +9,7 @@ export declare const SVELTE_PACKAGE_CLI = "svelte-package";
9
9
  export declare const SVELTE_PACKAGE_DEP_NAME = "@sveltejs/package";
10
10
  export declare const VITE_CLI = "vite";
11
11
  export declare const SVELTEKIT_ENV_MATCHER: RegExp;
12
+ export declare const SVELTEKIT_GLOBAL_SPECIFIER: RegExp;
12
13
  export declare const has_sveltekit_app: () => Result<object, {
13
14
  message: string;
14
15
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit_helpers.d.ts","sourceRoot":"../src/lib/","sources":["sveltekit_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAErD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAC,YAAY,EAAU,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAA2B,KAAK,uBAAuB,EAAC,MAAM,uBAAuB,CAAC;AAE7F,OAAO,EAAmC,KAAK,GAAG,EAAC,MAAM,UAAU,CAAC;AAIpE,eAAO,MAAM,aAAa,eAAe,CAAC;AAE1C,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAE3D,eAAO,MAAM,QAAQ,SAAS,CAAC;AAE/B,eAAO,MAAM,qBAAqB,QAAgD,CAAC;AAEnF,eAAO,MAAM,iBAAiB,QAAO,MAAM,CAAC,MAAM,EAAE;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAMpE,CAAC;AAEF,eAAO,MAAM,qBAAqB,iBACnB,YAAY,qBACR,uBAAuB,wBAEvC,MAAM,CAAC,MAAM,EAAE;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAkBlC,CAAC;AAEF,eAAO,MAAM,cAAc,mBACX,MAAM,GAAG,GAAG,sBAEzB,OAAO,CAAC,IAAI,CASd,CAAC;AAGF;;GAEG;AACH,eAAO,MAAM,2BAA2B,mBACxB,MAAM,GAAG,GAAG,KACzB,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,mBAC/B,MAAM,GAAG,GAAG,KACzB,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,CAAC,CAAC,EAAE,OAAO,CAAC;IACZ;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,CAAC,CAAC,EAAE,OAAO,CAAC;IACZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,kBAAkB,iBAChB,YAAY,WACjB,sBAAsB,GAAG,SAAS,OACtC,MAAM,GAAG,GAAG,OACZ,MAAM,UACH,MAAM,KACZ,OAAO,CAAC,IAAI,CAmBd,CAAC;AAGF;;GAEG;AACH,eAAO,MAAM,qBAAqB,cACtB,MAAM,WACR,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAC9B,MASF,CAAC"}
1
+ {"version":3,"file":"sveltekit_helpers.d.ts","sourceRoot":"../src/lib/","sources":["sveltekit_helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAErD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAC,YAAY,EAAU,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAA2B,KAAK,uBAAuB,EAAC,MAAM,uBAAuB,CAAC;AAE7F,OAAO,EAAmC,KAAK,GAAG,EAAC,MAAM,UAAU,CAAC;AAIpE,eAAO,MAAM,aAAa,eAAe,CAAC;AAE1C,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAE3D,eAAO,MAAM,QAAQ,SAAS,CAAC;AAE/B,eAAO,MAAM,qBAAqB,QAAgD,CAAC;AACnF,eAAO,MAAM,0BAA0B,QAAmB,CAAC;AAE3D,eAAO,MAAM,iBAAiB,QAAO,MAAM,CAAC,MAAM,EAAE;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAMpE,CAAC;AAEF,eAAO,MAAM,qBAAqB,iBACnB,YAAY,qBACR,uBAAuB,wBAEvC,MAAM,CAAC,MAAM,EAAE;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAkBlC,CAAC;AAEF,eAAO,MAAM,cAAc,mBACX,MAAM,GAAG,GAAG,sBAEzB,OAAO,CAAC,IAAI,CASd,CAAC;AAGF;;GAEG;AACH,eAAO,MAAM,2BAA2B,mBACxB,MAAM,GAAG,GAAG,KACzB,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,mBAC/B,MAAM,GAAG,GAAG,KACzB,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACtC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,CAAC,CAAC,EAAE,OAAO,CAAC;IACZ;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,CAAC,CAAC,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,CAAC,CAAC,EAAE,OAAO,CAAC;IACZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,kBAAkB,iBAChB,YAAY,WACjB,sBAAsB,GAAG,SAAS,OACtC,MAAM,GAAG,GAAG,OACZ,MAAM,UACH,MAAM,KACZ,OAAO,CAAC,IAAI,CAmBd,CAAC;AAGF;;GAEG;AACH,eAAO,MAAM,qBAAqB,cACtB,MAAM,WACR,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAC9B,MASF,CAAC"}
@@ -12,6 +12,7 @@ export const SVELTE_PACKAGE_CLI = 'svelte-package';
12
12
  export const SVELTE_PACKAGE_DEP_NAME = '@sveltejs/package';
13
13
  export const VITE_CLI = 'vite';
14
14
  export const SVELTEKIT_ENV_MATCHER = /^\$env\/(static|dynamic)\/(public|private)$/;
15
+ export const SVELTEKIT_GLOBAL_SPECIFIER = /^\$(env|app)\//;
15
16
  export const has_sveltekit_app = () => {
16
17
  if (!existsSync(SVELTEKIT_CONFIG_FILENAME)) {
17
18
  return { ok: false, message: `no SvelteKit config found at ${SVELTEKIT_CONFIG_FILENAME}` };
@@ -1 +1 @@
1
- {"version":3,"file":"sveltekit_shim_app_forms.d.ts","sourceRoot":"../src/lib/","sources":["sveltekit_shim_app_forms.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,WAAW,IAAI,gBAAgB,EAC/B,WAAW,IAAI,gBAAgB,EAC/B,OAAO,IAAI,YAAY,EACvB,MAAM,YAAY,CAAC;AAMpB,eAAO,MAAM,WAAW,EAAE,OAAO,gBAA6B,CAAC;AAC/D,eAAO,MAAM,WAAW,EAAE,OAAO,gBAMhC,CAAC;AACF,eAAO,MAAM,OAAO,EAAE,OAAO,YAAsC,CAAC"}
1
+ {"version":3,"file":"sveltekit_shim_app_forms.d.ts","sourceRoot":"../src/lib/","sources":["sveltekit_shim_app_forms.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,WAAW,IAAI,gBAAgB,EAC/B,WAAW,IAAI,gBAAgB,EAC/B,OAAO,IAAI,YAAY,EACvB,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,WAAW,EAAE,OAAO,gBAA6B,CAAC;AAC/D,eAAO,MAAM,WAAW,EAAE,OAAO,gBAAoC,CAAC;AACtE,eAAO,MAAM,OAAO,EAAE,OAAO,YAAsC,CAAC"}
@@ -1,15 +1,6 @@
1
1
  // shim for $app/forms
2
2
  // @see https://github.com/sveltejs/kit/issues/1485
3
3
  import { noop, noop_async } from '@ryanatkn/belt/function.js';
4
- // TODO better way todo this?
5
- // @ts-expect-error
6
- import * as devalue from 'devalue';
7
4
  export const applyAction = noop_async;
8
- export const deserialize = (result) => {
9
- const parsed = JSON.parse(result);
10
- if (parsed.data) {
11
- parsed.data = devalue.parse(parsed.data);
12
- }
13
- return parsed;
14
- };
5
+ export const deserialize = () => ({});
15
6
  export const enhance = () => ({ destroy: noop });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryanatkn/gro",
3
- "version": "0.146.2",
3
+ "version": "0.147.1",
4
4
  "description": "task runner and toolkit extending SvelteKit",
5
5
  "motto": "generate, run, optimize",
6
6
  "glyph": "🌰",
@@ -354,10 +354,6 @@
354
354
  "types": "./dist/release.task.d.ts",
355
355
  "default": "./dist/release.task.js"
356
356
  },
357
- "./resolve_node_specifier.js": {
358
- "types": "./dist/resolve_node_specifier.d.ts",
359
- "default": "./dist/resolve_node_specifier.js"
360
- },
361
357
  "./resolve_specifier.js": {
362
358
  "types": "./dist/resolve_specifier.d.ts",
363
359
  "default": "./dist/resolve_specifier.js"
package/src/lib/filer.ts CHANGED
@@ -3,6 +3,9 @@ import {existsSync, readFileSync, statSync} from 'node:fs';
3
3
  import {dirname, resolve} from 'node:path';
4
4
  import type {Omit_Strict} from '@ryanatkn/belt/types.js';
5
5
  import {wait} from '@ryanatkn/belt/async.js';
6
+ import {isBuiltin} from 'node:module';
7
+ import {fileURLToPath} from 'node:url';
8
+ import {Unreachable_Error} from '@ryanatkn/belt/error.js';
6
9
 
7
10
  import type {Path_Id} from './path.js';
8
11
  import {
@@ -16,9 +19,7 @@ import {paths} from './paths.js';
16
19
  import {parse_imports} from './parse_imports.js';
17
20
  import {resolve_specifier} from './resolve_specifier.js';
18
21
  import {default_sveltekit_config} from './sveltekit_config.js';
19
- import {map_sveltekit_aliases} from './sveltekit_helpers.js';
20
- import {Unreachable_Error} from '@ryanatkn/belt/error.js';
21
- import {resolve_node_specifier} from './resolve_node_specifier.js';
22
+ import {map_sveltekit_aliases, SVELTEKIT_GLOBAL_SPECIFIER} from './sveltekit_helpers.js';
22
23
  import type {Package_Json} from './package_json.js';
23
24
 
24
25
  const aliases = Object.entries(default_sveltekit_config.alias);
@@ -58,13 +59,10 @@ export class Filer {
58
59
  #watch_dir: typeof watch_dir;
59
60
  #watch_dir_options: Partial<Watch_Dir_Options>;
60
61
 
61
- #package_json_cache: Record<string, Package_Json>;
62
-
63
62
  constructor(options: Filer_Options = EMPTY_OBJECT) {
64
63
  this.#watch_dir = options.watch_dir ?? watch_dir;
65
64
  this.#watch_dir_options = options.watch_dir_options ?? EMPTY_OBJECT;
66
65
  this.root_dir = resolve(options.watch_dir_options?.dir ?? paths.source);
67
- this.#package_json_cache = options.package_json_cache ?? {};
68
66
  }
69
67
 
70
68
  #watching: Watch_Node_Fs | undefined;
@@ -118,16 +116,25 @@ export class Filer {
118
116
 
119
117
  const imported = file.contents ? parse_imports(file.id, file.contents) : [];
120
118
  for (const specifier of imported) {
121
- // TODO logic is duplicated from loader
119
+ if (SVELTEKIT_GLOBAL_SPECIFIER.test(specifier)) continue;
122
120
  const path = map_sveltekit_aliases(specifier, aliases);
123
121
 
124
- // The specifier `path` has now been mapped to its final form, so we can inspect it.
125
- const resolved =
126
- path[0] === '.' || path[0] === '/'
127
- ? resolve_specifier(path, dir)
128
- : resolve_node_specifier(path, undefined, file.id, this.#package_json_cache, false);
129
- if (!resolved) continue; // ignore any missing imports like Node identifiers
130
- const {path_id} = resolved;
122
+ let path_id;
123
+ if (path[0] === '.' || path[0] === '/') {
124
+ const resolved = resolve_specifier(path, dir);
125
+ path_id = resolved.path_id;
126
+ } else {
127
+ if (isBuiltin(path)) continue;
128
+ try {
129
+ path_id = fileURLToPath(import.meta.resolve(path, file.id));
130
+ } catch (error) {
131
+ // If it's imported from an external module, ignore any import errors.
132
+ if (error.code === 'ERR_MODULE_NOT_FOUND' && file.external) {
133
+ continue;
134
+ }
135
+ throw error;
136
+ }
137
+ }
131
138
  dependencies_removed.delete(path_id);
132
139
  if (!dependencies_before.has(path_id)) {
133
140
  const d = this.get_or_create(path_id);
package/src/lib/loader.ts CHANGED
@@ -20,8 +20,6 @@ import {IS_THIS_GRO, paths} from './paths.js';
20
20
  import {JSON_MATCHER, NODE_MODULES_DIRNAME, TS_MATCHER} from './constants.js';
21
21
  import {to_define_import_meta_env, default_ts_transform_options} from './esbuild_helpers.js';
22
22
  import {resolve_specifier} from './resolve_specifier.js';
23
- import {resolve_node_specifier} from './resolve_node_specifier.js';
24
- import type {Package_Json} from './package_json.js';
25
23
  import {map_sveltekit_aliases} from './sveltekit_helpers.js';
26
24
 
27
25
  /*
@@ -80,8 +78,6 @@ const RAW_MATCHER = /(%3Fraw|\.css|\.svg)$/; // TODO others? configurable?
80
78
  const ENV_MATCHER = /src\/lib\/\$env\/(static|dynamic)\/(public|private)$/;
81
79
  const NODE_MODULES_MATCHER = new RegExp(escape_regexp('/' + NODE_MODULES_DIRNAME + '/'), 'u');
82
80
 
83
- const package_json_cache: Record<string, Package_Json> = {};
84
-
85
81
  export const load: LoadHook = async (url, context, nextLoad) => {
86
82
  if (SVELTEKIT_SHIM_APP_PATHS_MATCHER.test(url)) {
87
83
  // SvelteKit `$app/paths` shim
@@ -211,19 +207,10 @@ export const resolve: ResolveHook = async (specifier, context, nextResolve) => {
211
207
  s = map_sveltekit_aliases(s, aliases);
212
208
 
213
209
  // The specifier has now been mapped to its final form, so we can inspect it.
210
+
211
+ // Imports into `node_modules` use the default algorithm, and the rest use use Vite conventions.
214
212
  if (s[0] !== '.' && s[0] !== '/') {
215
- // Resolve to `node_modules`.
216
- if (SVELTE_MATCHER.test(s) || JSON_MATCHER.test(s)) {
217
- // Match the behavior of Vite and esbuild for Svelte and JSON imports.
218
- const resolved = resolve_node_specifier(s, dir, parent_url, package_json_cache)!; // `node:` specifiers shouldn't reach this point, so the assertion is safe
219
- return {
220
- url: pathToFileURL(resolved.path_id_with_querystring).href,
221
- format: 'module',
222
- shortCircuit: true,
223
- };
224
- } else {
225
- return nextResolve(s, context);
226
- }
213
+ return nextResolve(s, context);
227
214
  }
228
215
 
229
216
  const resolved = resolve_specifier(s, dirname(fileURLToPath(parent_url)));
@@ -5,7 +5,7 @@ import type {Src_Json} from './src_json.js';
5
5
 
6
6
  export const package_json = {
7
7
  name: '@ryanatkn/gro',
8
- version: '0.146.2',
8
+ version: '0.147.1',
9
9
  description: 'task runner and toolkit extending SvelteKit',
10
10
  motto: 'generate, run, optimize',
11
11
  glyph: '🌰',
@@ -201,10 +201,6 @@ export const package_json = {
201
201
  default: './dist/reinstall.task.js',
202
202
  },
203
203
  './release.task.js': {types: './dist/release.task.d.ts', default: './dist/release.task.js'},
204
- './resolve_node_specifier.js': {
205
- types: './dist/resolve_node_specifier.d.ts',
206
- default: './dist/resolve_node_specifier.js',
207
- },
208
204
  './resolve_specifier.js': {
209
205
  types: './dist/resolve_specifier.d.ts',
210
206
  default: './dist/resolve_specifier.js',
@@ -270,7 +266,7 @@ export const package_json = {
270
266
 
271
267
  export const src_json = {
272
268
  name: '@ryanatkn/gro',
273
- version: '0.146.2',
269
+ version: '0.147.1',
274
270
  modules: {
275
271
  '.': {
276
272
  path: 'index.ts',
@@ -816,10 +812,6 @@ export const src_json = {
816
812
  {name: 'task', kind: 'variable'},
817
813
  ],
818
814
  },
819
- './resolve_node_specifier.js': {
820
- path: 'resolve_node_specifier.ts',
821
- declarations: [{name: 'resolve_node_specifier', kind: 'function'}],
822
- },
823
815
  './resolve_specifier.js': {
824
816
  path: 'resolve_specifier.ts',
825
817
  declarations: [
@@ -901,6 +893,7 @@ export const src_json = {
901
893
  {name: 'SVELTE_PACKAGE_DEP_NAME', kind: 'variable'},
902
894
  {name: 'VITE_CLI', kind: 'variable'},
903
895
  {name: 'SVELTEKIT_ENV_MATCHER', kind: 'variable'},
896
+ {name: 'SVELTEKIT_GLOBAL_SPECIFIER', kind: 'variable'},
904
897
  {name: 'has_sveltekit_app', kind: 'function'},
905
898
  {name: 'has_sveltekit_library', kind: 'function'},
906
899
  {name: 'sveltekit_sync', kind: 'function'},
@@ -20,6 +20,7 @@ export const SVELTE_PACKAGE_DEP_NAME = '@sveltejs/package';
20
20
  export const VITE_CLI = 'vite';
21
21
 
22
22
  export const SVELTEKIT_ENV_MATCHER = /^\$env\/(static|dynamic)\/(public|private)$/;
23
+ export const SVELTEKIT_GLOBAL_SPECIFIER = /^\$(env|app)\//;
23
24
 
24
25
  export const has_sveltekit_app = (): Result<object, {message: string}> => {
25
26
  if (!existsSync(SVELTEKIT_CONFIG_FILENAME)) {
@@ -7,16 +7,7 @@ import type {
7
7
  enhance as base_enhance,
8
8
  } from '$app/forms';
9
9
  import {noop, noop_async} from '@ryanatkn/belt/function.js';
10
- // TODO better way todo this?
11
- // @ts-expect-error
12
- import * as devalue from 'devalue';
13
10
 
14
11
  export const applyAction: typeof base_applyAction = noop_async;
15
- export const deserialize: typeof base_deserialize = (result) => {
16
- const parsed = JSON.parse(result);
17
- if (parsed.data) {
18
- parsed.data = devalue.parse(parsed.data);
19
- }
20
- return parsed;
21
- };
12
+ export const deserialize: typeof base_deserialize = () => ({}) as any;
22
13
  export const enhance: typeof base_enhance = () => ({destroy: noop});
@@ -1,9 +0,0 @@
1
- import { Package_Json } from './package_json.js';
2
- import type { Resolved_Specifier } from './resolve_specifier.js';
3
- /**
4
- * Ideally Gro would just use `import.meta.resolve`, but it can't be used in custom loaders,
5
- * which Gro relies on for TypeScript.
6
- * This likely has differences from Node - they should be fixed on a case-by-case basis.
7
- */
8
- export declare const resolve_node_specifier: (specifier: string, dir?: string, parent_path?: string, package_json_cache?: Record<string, Package_Json>, throw_on_missing_package?: boolean, exports_conditions?: string[]) => Resolved_Specifier | null;
9
- //# sourceMappingURL=resolve_node_specifier.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolve_node_specifier.d.ts","sourceRoot":"../src/lib/","sources":["resolve_node_specifier.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AAGhF,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,wBAAwB,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,cACvB,MAAM,8BAEH,MAAM,uBACC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,wEAG/C,kBAAkB,GAAG,IAsFvB,CAAC"}
@@ -1,306 +0,0 @@
1
- import { join, extname } from 'node:path';
2
- import { existsSync } from 'node:fs';
3
- import { DEV } from 'esm-env';
4
- import { escape_regexp } from '@ryanatkn/belt/regexp.js';
5
- import { Export_Value, Package_Json, load_package_json } from './package_json.js';
6
- import { paths } from './paths.js';
7
- import { NODE_MODULES_DIRNAME } from './constants.js';
8
- /**
9
- * Ideally Gro would just use `import.meta.resolve`, but it can't be used in custom loaders,
10
- * which Gro relies on for TypeScript.
11
- * This likely has differences from Node - they should be fixed on a case-by-case basis.
12
- */
13
- export const resolve_node_specifier = (specifier, dir = paths.root, parent_path, package_json_cache, throw_on_missing_package = true, exports_conditions = DEV ? ['development', 'node', 'import'] : ['production', 'node', 'import']) => {
14
- const raw = specifier.endsWith('?raw');
15
- const mapped_specifier = raw ? specifier.substring(0, specifier.length - 4) : specifier;
16
- const specifier_slash_path_index = get_specifier_slash_path_index(mapped_specifier);
17
- const pkg_name = specifier_slash_path_index === -1
18
- ? mapped_specifier
19
- : mapped_specifier.substring(0, specifier_slash_path_index);
20
- const module_path = specifier_slash_path_index === -1
21
- ? ''
22
- : mapped_specifier.substring(specifier_slash_path_index + 1);
23
- const subpath = module_path ? './' + module_path : '.';
24
- const package_dir = join(dir, NODE_MODULES_DIRNAME, pkg_name);
25
- // Check package_json cache first
26
- let package_json;
27
- if (package_json_cache?.[pkg_name]) {
28
- package_json = package_json_cache[pkg_name];
29
- }
30
- else if (!existsSync(package_dir)) {
31
- if (throw_on_missing_package) {
32
- throw Error(`Package not found at ${package_dir} for specifier ${specifier}, you may need to install packages or fix the path` +
33
- (parent_path ? ` imported from ${parent_path}` : ''));
34
- }
35
- else {
36
- return null;
37
- }
38
- }
39
- else {
40
- package_json = load_package_json(package_dir, package_json_cache, false);
41
- }
42
- // Handle self-referencing
43
- if (parent_path?.startsWith(package_dir)) {
44
- if (!package_json.exports) {
45
- throw Error(`Self-referencing is only available if package.json has "exports" field: ${specifier}` +
46
- (parent_path ? ` imported from ${parent_path}` : ''));
47
- }
48
- }
49
- const exported = resolve_subpath(package_json, subpath);
50
- if (typeof exported === 'string') {
51
- const validated = validate_export_target(exported, throw_on_missing_package);
52
- if (validated === null) {
53
- return null;
54
- }
55
- }
56
- if (!exported) {
57
- if (throw_on_missing_package) {
58
- throw Error(`[ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath '${subpath}' is not defined by 'exports' in ${package_dir}/package.json` +
59
- (parent_path ? ` imported from ${parent_path}` : ''));
60
- }
61
- else {
62
- return null;
63
- }
64
- }
65
- const exported_value = resolve_exported_value(exported, exports_conditions);
66
- if (exported_value === undefined) {
67
- if (throw_on_missing_package) {
68
- throw Error(`No valid export found for subpath '${subpath}' in ${package_dir}/package.json with the following conditions: ${exports_conditions.join(', ')}` +
69
- (parent_path ? ` imported from ${parent_path}` : ''));
70
- }
71
- else {
72
- return null;
73
- }
74
- }
75
- const path_id = normalize_extension(join(package_dir, exported_value));
76
- return {
77
- path_id,
78
- path_id_with_querystring: raw ? path_id + '?raw' : path_id,
79
- raw,
80
- specifier,
81
- mapped_specifier,
82
- namespace: undefined,
83
- };
84
- };
85
- const replace_wildcards = (pattern, wildcards) => {
86
- if (!pattern.includes('*'))
87
- return pattern;
88
- let result = pattern;
89
- let wildcard_index = 0;
90
- while (result.includes('*') && wildcard_index < wildcards.length) {
91
- result = result.replace('*', wildcards[wildcard_index++]);
92
- }
93
- return result;
94
- };
95
- const resolve_subpath = (package_json, subpath) => {
96
- // If no exports field exists, fallback to main field for the root subpath
97
- if (!package_json.exports) {
98
- return subpath === '.' && package_json.main ? package_json.main : null;
99
- }
100
- const exports = package_json.exports;
101
- // Handle exports sugar syntax
102
- if (typeof exports === 'string') {
103
- return subpath === '.' ? exports : null;
104
- }
105
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
106
- if (typeof exports === 'object' && exports !== null) {
107
- // Check for exact match first
108
- if (subpath in exports) {
109
- return exports[subpath];
110
- }
111
- // TODO some of this may be wrong, will just need to patch as we go
112
- // Sort patterns by specificity
113
- const patterns = Object.entries(exports)
114
- .filter(([pattern]) => pattern.includes('*'))
115
- .map(([pattern, target]) => ({
116
- pattern,
117
- target,
118
- static_prefix: pattern.split('*')[0],
119
- segments: pattern.split('/').length,
120
- wildcards: (pattern.match(/\*/g) ?? []).length,
121
- }))
122
- .sort((a, b) => {
123
- // Sort by static prefix length first
124
- const prefix_diff = b.static_prefix.length - a.static_prefix.length;
125
- if (prefix_diff !== 0)
126
- return prefix_diff;
127
- // Then by number of segments
128
- const segment_diff = b.segments - a.segments;
129
- if (segment_diff !== 0)
130
- return segment_diff;
131
- // Then by number of wildcards (fewer is more specific)
132
- const wildcard_diff = a.wildcards - b.wildcards;
133
- if (wildcard_diff !== 0)
134
- return wildcard_diff;
135
- // Finally by total pattern length
136
- return b.pattern.length - a.pattern.length;
137
- });
138
- // Track matched wildcards for later use
139
- let matched_wildcards = [];
140
- // Check patterns in order of specificity
141
- for (const { pattern, target } of patterns) {
142
- // Convert pattern to regex, handling path segments properly
143
- const regex_pattern = pattern.split('*').map(escape_regexp).join('([^/]+)');
144
- const regex = new RegExp(`^${regex_pattern}$`);
145
- const match = subpath.match(regex);
146
- if (match) {
147
- // If this is a null pattern and it matches, block access
148
- if (target === null)
149
- return null;
150
- // Extract captured wildcards and store them
151
- matched_wildcards = match.slice(1);
152
- if (typeof target === 'string') {
153
- return replace_wildcards(target, matched_wildcards);
154
- }
155
- if (typeof target === 'object' && target !== null) {
156
- // For conditional exports, return an object with resolved wildcards
157
- return Object.fromEntries(Object.entries(target).map(([key, value]) => {
158
- if (typeof value === 'string') {
159
- return [key, replace_wildcards(value, matched_wildcards)];
160
- }
161
- // Handle nested conditions
162
- if (typeof value === 'object' && value !== null) {
163
- return [
164
- key,
165
- Object.fromEntries(Object.entries(value).map(([nested_key, nested_value]) => [
166
- nested_key,
167
- typeof nested_value === 'string'
168
- ? replace_wildcards(nested_value, matched_wildcards)
169
- : nested_value,
170
- ])),
171
- ];
172
- }
173
- return [key, value];
174
- }));
175
- }
176
- }
177
- }
178
- // Handle catch-all patterns for remaining cases
179
- const catch_all_patterns = patterns.filter(({ pattern }) => pattern.endsWith('/*') || pattern === './*');
180
- for (const { pattern, target } of catch_all_patterns) {
181
- const base_pattern = pattern.slice(0, -1); // Remove trailing '*'
182
- if (subpath.startsWith(base_pattern)) {
183
- if (target === null)
184
- return null;
185
- const remainder = subpath.slice(base_pattern.length);
186
- if (typeof target === 'string') {
187
- return target.slice(0, -1) + remainder;
188
- }
189
- }
190
- }
191
- }
192
- return null;
193
- };
194
- const resolve_exported_value = (exported, conditions) => {
195
- if (typeof exported === 'string') {
196
- return exported;
197
- }
198
- if (typeof exported !== 'object' || exported === null) {
199
- return undefined;
200
- }
201
- const exported_obj = exported;
202
- let default_value; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
203
- // For each key in exported_obj, in order
204
- for (const [condition, value] of Object.entries(exported_obj)) {
205
- // Skip invalid conditions
206
- if (!is_valid_condition(condition)) {
207
- continue;
208
- }
209
- if (condition === 'default') {
210
- // Store default value to try last
211
- default_value = value;
212
- }
213
- else if (conditions.includes(condition)) {
214
- const resolved = resolve_exported_value(value, conditions);
215
- if (resolved !== undefined) {
216
- return resolved;
217
- }
218
- }
219
- }
220
- // If no conditions matched, try default
221
- if (default_value !== undefined) {
222
- const resolved = resolve_exported_value(default_value, conditions);
223
- if (resolved !== undefined) {
224
- return resolved;
225
- }
226
- }
227
- return undefined;
228
- };
229
- const is_valid_condition = (condition) => {
230
- if (condition.length === 0 ||
231
- condition.startsWith('.') ||
232
- condition.includes(',') ||
233
- /^\d+$/.test(condition)) {
234
- return false;
235
- }
236
- return /^[a-zA-Z0-9:_\-=]+$/.test(condition);
237
- };
238
- const normalize_extension = (path) => {
239
- if (path.endsWith('.d.ts')) {
240
- return path.slice(0, -5) + '.js';
241
- }
242
- // No extension handling needed if path already has an extension
243
- if (extname(path)) {
244
- return path;
245
- }
246
- // If no extension at all, add .js
247
- return path + '.js';
248
- };
249
- const validate_export_target = (target, throw_on_missing_package) => {
250
- // Must start with './'
251
- if (!target.startsWith('./') && !target.startsWith('../')) {
252
- if (throw_on_missing_package) {
253
- throw new Error('ERR_INVALID_PACKAGE_TARGET: Export target must start with "./" or "../"');
254
- }
255
- else {
256
- return null;
257
- }
258
- }
259
- // Can't contain node_modules
260
- if (target.includes('node_modules')) {
261
- if (throw_on_missing_package) {
262
- throw new Error('ERR_INVALID_PACKAGE_TARGET: Export target cannot contain node_modules');
263
- }
264
- else {
265
- return null;
266
- }
267
- }
268
- // Check for package boundary escape
269
- const parts = target.split('/');
270
- let depth = 0;
271
- for (const part of parts) {
272
- if (part === '..') {
273
- depth--;
274
- // If we go above root, it's escaping the package boundary
275
- if (depth < 0) {
276
- if (throw_on_missing_package) {
277
- throw new Error('ERR_INVALID_PACKAGE_TARGET: Export target cannot escape package boundary');
278
- }
279
- else {
280
- return null;
281
- }
282
- }
283
- }
284
- else if (part !== '.' && part !== '') {
285
- depth++;
286
- }
287
- }
288
- };
289
- const get_specifier_slash_path_index = (mapped_specifier) => {
290
- let index = -1;
291
- if (mapped_specifier[0] === '@') {
292
- let count = 0;
293
- for (let i = 0; i < mapped_specifier.length; i++) {
294
- if (mapped_specifier[i] === '/')
295
- count++;
296
- if (count === 2) {
297
- index = i;
298
- break;
299
- }
300
- }
301
- }
302
- else {
303
- index = mapped_specifier.indexOf('/');
304
- }
305
- return index;
306
- };
@@ -1,369 +0,0 @@
1
- import {join, extname} from 'node:path';
2
- import {existsSync} from 'node:fs';
3
- import {DEV} from 'esm-env';
4
- import {escape_regexp} from '@ryanatkn/belt/regexp.js';
5
-
6
- import {Export_Value, Package_Json, load_package_json} from './package_json.js';
7
- import {paths} from './paths.js';
8
- import {NODE_MODULES_DIRNAME} from './constants.js';
9
- import type {Resolved_Specifier} from './resolve_specifier.js';
10
-
11
- /**
12
- * Ideally Gro would just use `import.meta.resolve`, but it can't be used in custom loaders,
13
- * which Gro relies on for TypeScript.
14
- * This likely has differences from Node - they should be fixed on a case-by-case basis.
15
- */
16
- export const resolve_node_specifier = (
17
- specifier: string,
18
- dir = paths.root,
19
- parent_path?: string,
20
- package_json_cache?: Record<string, Package_Json>,
21
- throw_on_missing_package = true,
22
- exports_conditions = DEV ? ['development', 'node', 'import'] : ['production', 'node', 'import'],
23
- ): Resolved_Specifier | null => {
24
- const raw = specifier.endsWith('?raw');
25
- const mapped_specifier = raw ? specifier.substring(0, specifier.length - 4) : specifier;
26
-
27
- const specifier_slash_path_index = get_specifier_slash_path_index(mapped_specifier);
28
-
29
- const pkg_name =
30
- specifier_slash_path_index === -1
31
- ? mapped_specifier
32
- : mapped_specifier.substring(0, specifier_slash_path_index);
33
- const module_path =
34
- specifier_slash_path_index === -1
35
- ? ''
36
- : mapped_specifier.substring(specifier_slash_path_index + 1);
37
- const subpath = module_path ? './' + module_path : '.';
38
- const package_dir = join(dir, NODE_MODULES_DIRNAME, pkg_name);
39
-
40
- // Check package_json cache first
41
- let package_json: Package_Json | undefined;
42
- if (package_json_cache?.[pkg_name]) {
43
- package_json = package_json_cache[pkg_name];
44
- } else if (!existsSync(package_dir)) {
45
- if (throw_on_missing_package) {
46
- throw Error(
47
- `Package not found at ${package_dir} for specifier ${specifier}, you may need to install packages or fix the path` +
48
- (parent_path ? ` imported from ${parent_path}` : ''),
49
- );
50
- } else {
51
- return null;
52
- }
53
- } else {
54
- package_json = load_package_json(package_dir, package_json_cache, false);
55
- }
56
-
57
- // Handle self-referencing
58
- if (parent_path?.startsWith(package_dir)) {
59
- if (!package_json.exports) {
60
- throw Error(
61
- `Self-referencing is only available if package.json has "exports" field: ${specifier}` +
62
- (parent_path ? ` imported from ${parent_path}` : ''),
63
- );
64
- }
65
- }
66
-
67
- const exported = resolve_subpath(package_json, subpath);
68
-
69
- if (typeof exported === 'string') {
70
- const validated = validate_export_target(exported, throw_on_missing_package);
71
- if (validated === null) {
72
- return null;
73
- }
74
- }
75
-
76
- if (!exported) {
77
- if (throw_on_missing_package) {
78
- throw Error(
79
- `[ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath '${subpath}' is not defined by 'exports' in ${package_dir}/package.json` +
80
- (parent_path ? ` imported from ${parent_path}` : ''),
81
- );
82
- } else {
83
- return null;
84
- }
85
- }
86
-
87
- const exported_value = resolve_exported_value(exported, exports_conditions);
88
- if (exported_value === undefined) {
89
- if (throw_on_missing_package) {
90
- throw Error(
91
- `No valid export found for subpath '${subpath}' in ${package_dir}/package.json with the following conditions: ${exports_conditions.join(', ')}` +
92
- (parent_path ? ` imported from ${parent_path}` : ''),
93
- );
94
- } else {
95
- return null;
96
- }
97
- }
98
-
99
- const path_id = normalize_extension(join(package_dir, exported_value));
100
-
101
- return {
102
- path_id,
103
- path_id_with_querystring: raw ? path_id + '?raw' : path_id,
104
- raw,
105
- specifier,
106
- mapped_specifier,
107
- namespace: undefined,
108
- };
109
- };
110
-
111
- const replace_wildcards = (pattern: string, wildcards: string[]): string => {
112
- if (!pattern.includes('*')) return pattern;
113
-
114
- let result = pattern;
115
- let wildcard_index = 0;
116
- while (result.includes('*') && wildcard_index < wildcards.length) {
117
- result = result.replace('*', wildcards[wildcard_index++]);
118
- }
119
- return result;
120
- };
121
-
122
- const resolve_subpath = (package_json: Package_Json, subpath: string): unknown => {
123
- // If no exports field exists, fallback to main field for the root subpath
124
- if (!package_json.exports) {
125
- return subpath === '.' && package_json.main ? package_json.main : null;
126
- }
127
-
128
- const exports = package_json.exports;
129
-
130
- // Handle exports sugar syntax
131
- if (typeof exports === 'string') {
132
- return subpath === '.' ? exports : null;
133
- }
134
-
135
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
136
- if (typeof exports === 'object' && exports !== null) {
137
- // Check for exact match first
138
- if (subpath in exports) {
139
- return exports[subpath];
140
- }
141
-
142
- // TODO some of this may be wrong, will just need to patch as we go
143
- // Sort patterns by specificity
144
- const patterns = Object.entries(exports)
145
- .filter(([pattern]) => pattern.includes('*'))
146
- .map(([pattern, target]) => ({
147
- pattern,
148
- target,
149
- static_prefix: pattern.split('*')[0],
150
- segments: pattern.split('/').length,
151
- wildcards: (pattern.match(/\*/g) ?? []).length,
152
- }))
153
- .sort((a, b) => {
154
- // Sort by static prefix length first
155
- const prefix_diff = b.static_prefix.length - a.static_prefix.length;
156
- if (prefix_diff !== 0) return prefix_diff;
157
-
158
- // Then by number of segments
159
- const segment_diff = b.segments - a.segments;
160
- if (segment_diff !== 0) return segment_diff;
161
-
162
- // Then by number of wildcards (fewer is more specific)
163
- const wildcard_diff = a.wildcards - b.wildcards;
164
- if (wildcard_diff !== 0) return wildcard_diff;
165
-
166
- // Finally by total pattern length
167
- return b.pattern.length - a.pattern.length;
168
- });
169
-
170
- // Track matched wildcards for later use
171
- let matched_wildcards: string[] = [];
172
-
173
- // Check patterns in order of specificity
174
- for (const {pattern, target} of patterns) {
175
- // Convert pattern to regex, handling path segments properly
176
- const regex_pattern = pattern.split('*').map(escape_regexp).join('([^/]+)');
177
- const regex = new RegExp(`^${regex_pattern}$`);
178
- const match = subpath.match(regex);
179
-
180
- if (match) {
181
- // If this is a null pattern and it matches, block access
182
- if (target === null) return null;
183
-
184
- // Extract captured wildcards and store them
185
- matched_wildcards = match.slice(1);
186
-
187
- if (typeof target === 'string') {
188
- return replace_wildcards(target, matched_wildcards);
189
- }
190
-
191
- if (typeof target === 'object' && target !== null) {
192
- // For conditional exports, return an object with resolved wildcards
193
- return Object.fromEntries(
194
- Object.entries(target).map(([key, value]) => {
195
- if (typeof value === 'string') {
196
- return [key, replace_wildcards(value, matched_wildcards)];
197
- }
198
- // Handle nested conditions
199
- if (typeof value === 'object' && value !== null) {
200
- return [
201
- key,
202
- Object.fromEntries(
203
- Object.entries(value).map(([nested_key, nested_value]) => [
204
- nested_key,
205
- typeof nested_value === 'string'
206
- ? replace_wildcards(nested_value, matched_wildcards)
207
- : nested_value,
208
- ]),
209
- ),
210
- ];
211
- }
212
- return [key, value];
213
- }),
214
- );
215
- }
216
- }
217
- }
218
-
219
- // Handle catch-all patterns for remaining cases
220
- const catch_all_patterns = patterns.filter(
221
- ({pattern}) => pattern.endsWith('/*') || pattern === './*',
222
- );
223
-
224
- for (const {pattern, target} of catch_all_patterns) {
225
- const base_pattern = pattern.slice(0, -1); // Remove trailing '*'
226
- if (subpath.startsWith(base_pattern)) {
227
- if (target === null) return null;
228
-
229
- const remainder = subpath.slice(base_pattern.length);
230
- if (typeof target === 'string') {
231
- return target.slice(0, -1) + remainder;
232
- }
233
- }
234
- }
235
- }
236
-
237
- return null;
238
- };
239
-
240
- const resolve_exported_value = (
241
- exported: Export_Value,
242
- conditions: string[],
243
- ): string | undefined => {
244
- if (typeof exported === 'string') {
245
- return exported;
246
- }
247
-
248
- if (typeof exported !== 'object' || exported === null) {
249
- return undefined;
250
- }
251
-
252
- const exported_obj = exported as Record<string, unknown>;
253
-
254
- let default_value: Export_Value | undefined; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
255
-
256
- // For each key in exported_obj, in order
257
- for (const [condition, value] of Object.entries(exported_obj)) {
258
- // Skip invalid conditions
259
- if (!is_valid_condition(condition)) {
260
- continue;
261
- }
262
-
263
- if (condition === 'default') {
264
- // Store default value to try last
265
- default_value = value;
266
- } else if (conditions.includes(condition)) {
267
- const resolved = resolve_exported_value(value, conditions);
268
- if (resolved !== undefined) {
269
- return resolved;
270
- }
271
- }
272
- }
273
-
274
- // If no conditions matched, try default
275
- if (default_value !== undefined) {
276
- const resolved = resolve_exported_value(default_value, conditions);
277
- if (resolved !== undefined) {
278
- return resolved;
279
- }
280
- }
281
-
282
- return undefined;
283
- };
284
-
285
- const is_valid_condition = (condition: string): boolean => {
286
- if (
287
- condition.length === 0 ||
288
- condition.startsWith('.') ||
289
- condition.includes(',') ||
290
- /^\d+$/.test(condition)
291
- ) {
292
- return false;
293
- }
294
- return /^[a-zA-Z0-9:_\-=]+$/.test(condition);
295
- };
296
-
297
- const normalize_extension = (path: string): string => {
298
- if (path.endsWith('.d.ts')) {
299
- return path.slice(0, -5) + '.js';
300
- }
301
-
302
- // No extension handling needed if path already has an extension
303
- if (extname(path)) {
304
- return path;
305
- }
306
-
307
- // If no extension at all, add .js
308
- return path + '.js';
309
- };
310
-
311
- const validate_export_target = (target: string, throw_on_missing_package: boolean): void | null => {
312
- // Must start with './'
313
- if (!target.startsWith('./') && !target.startsWith('../')) {
314
- if (throw_on_missing_package) {
315
- throw new Error('ERR_INVALID_PACKAGE_TARGET: Export target must start with "./" or "../"');
316
- } else {
317
- return null;
318
- }
319
- }
320
-
321
- // Can't contain node_modules
322
- if (target.includes('node_modules')) {
323
- if (throw_on_missing_package) {
324
- throw new Error('ERR_INVALID_PACKAGE_TARGET: Export target cannot contain node_modules');
325
- } else {
326
- return null;
327
- }
328
- }
329
-
330
- // Check for package boundary escape
331
- const parts = target.split('/');
332
- let depth = 0;
333
-
334
- for (const part of parts) {
335
- if (part === '..') {
336
- depth--;
337
- // If we go above root, it's escaping the package boundary
338
- if (depth < 0) {
339
- if (throw_on_missing_package) {
340
- throw new Error(
341
- 'ERR_INVALID_PACKAGE_TARGET: Export target cannot escape package boundary',
342
- );
343
- } else {
344
- return null;
345
- }
346
- }
347
- } else if (part !== '.' && part !== '') {
348
- depth++;
349
- }
350
- }
351
- };
352
-
353
- const get_specifier_slash_path_index = (mapped_specifier: string): number => {
354
- let index: number = -1;
355
- if (mapped_specifier[0] === '@') {
356
- let count = 0;
357
- for (let i = 0; i < mapped_specifier.length; i++) {
358
- if (mapped_specifier[i] === '/') count++;
359
- if (count === 2) {
360
- index = i;
361
- break;
362
- }
363
- }
364
- } else {
365
- index = mapped_specifier.indexOf('/');
366
- }
367
-
368
- return index;
369
- };