@ryanatkn/gro 0.178.0 → 0.180.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 (108) hide show
  1. package/dist/build.task.d.ts +2 -0
  2. package/dist/build.task.d.ts.map +1 -1
  3. package/dist/build.task.js +14 -10
  4. package/dist/build_cache.d.ts +3 -3
  5. package/dist/build_cache.d.ts.map +1 -1
  6. package/dist/build_cache.js +53 -43
  7. package/dist/changeset.task.js +9 -9
  8. package/dist/clean_fs.d.ts +1 -1
  9. package/dist/clean_fs.d.ts.map +1 -1
  10. package/dist/clean_fs.js +3 -4
  11. package/dist/cli.d.ts +4 -4
  12. package/dist/cli.d.ts.map +1 -1
  13. package/dist/cli.js +11 -12
  14. package/dist/deploy.task.d.ts +7 -0
  15. package/dist/deploy.task.d.ts.map +1 -1
  16. package/dist/deploy.task.js +27 -14
  17. package/dist/esbuild_plugin_external_worker.js +1 -1
  18. package/dist/esbuild_plugin_svelte.js +4 -4
  19. package/dist/esbuild_plugin_sveltekit_local_imports.js +2 -2
  20. package/dist/filer.d.ts.map +1 -1
  21. package/dist/filer.js +103 -52
  22. package/dist/format_file.js +1 -1
  23. package/dist/gen.d.ts +1 -1
  24. package/dist/gen.d.ts.map +1 -1
  25. package/dist/gen.js +28 -22
  26. package/dist/gen.task.js +1 -1
  27. package/dist/gro.config.default.js +1 -1
  28. package/dist/gro_config.js +2 -2
  29. package/dist/gro_plugin_gen.js +1 -1
  30. package/dist/gro_plugin_server.js +2 -2
  31. package/dist/gro_plugin_sveltekit_app.d.ts.map +1 -1
  32. package/dist/gro_plugin_sveltekit_app.js +40 -36
  33. package/dist/gro_plugin_sveltekit_library.js +2 -1
  34. package/dist/input_path.d.ts +3 -3
  35. package/dist/input_path.d.ts.map +1 -1
  36. package/dist/input_path.js +16 -14
  37. package/dist/invoke_task.js +2 -2
  38. package/dist/lint.task.js +1 -1
  39. package/dist/loader.js +1 -1
  40. package/dist/modules.js +2 -2
  41. package/dist/package_json.d.ts +4 -4
  42. package/dist/package_json.d.ts.map +1 -1
  43. package/dist/package_json.js +12 -14
  44. package/dist/publish.task.js +6 -6
  45. package/dist/release.task.js +1 -1
  46. package/dist/resolve.task.js +2 -2
  47. package/dist/resolve_specifier.d.ts +1 -1
  48. package/dist/resolve_specifier.d.ts.map +1 -1
  49. package/dist/resolve_specifier.js +5 -4
  50. package/dist/run.task.js +2 -2
  51. package/dist/run_gen.d.ts.map +1 -1
  52. package/dist/run_gen.js +9 -8
  53. package/dist/run_task.js +4 -4
  54. package/dist/source_json.d.ts +2 -2
  55. package/dist/source_json.d.ts.map +1 -1
  56. package/dist/source_json.js +16 -15
  57. package/dist/sveltekit_helpers.js +3 -3
  58. package/dist/sveltekit_shim_env.js +1 -1
  59. package/dist/task.d.ts +1 -1
  60. package/dist/task.d.ts.map +1 -1
  61. package/dist/task.js +4 -4
  62. package/dist/test.task.d.ts.map +1 -1
  63. package/dist/test.task.js +5 -4
  64. package/dist/typecheck.task.js +3 -3
  65. package/dist/upgrade.task.js +4 -4
  66. package/package.json +7 -7
  67. package/src/lib/build.task.ts +15 -10
  68. package/src/lib/build_cache.ts +79 -63
  69. package/src/lib/changeset.task.ts +10 -10
  70. package/src/lib/clean_fs.ts +4 -4
  71. package/src/lib/cli.ts +15 -14
  72. package/src/lib/deploy.task.ts +30 -13
  73. package/src/lib/esbuild_plugin_external_worker.ts +1 -1
  74. package/src/lib/esbuild_plugin_svelte.ts +4 -4
  75. package/src/lib/esbuild_plugin_sveltekit_local_imports.ts +2 -2
  76. package/src/lib/filer.ts +111 -52
  77. package/src/lib/format_file.ts +1 -1
  78. package/src/lib/gen.task.ts +1 -1
  79. package/src/lib/gen.ts +52 -46
  80. package/src/lib/gro.config.default.ts +1 -1
  81. package/src/lib/gro_config.ts +2 -2
  82. package/src/lib/gro_plugin_gen.ts +1 -1
  83. package/src/lib/gro_plugin_server.ts +2 -2
  84. package/src/lib/gro_plugin_sveltekit_app.ts +49 -41
  85. package/src/lib/gro_plugin_sveltekit_library.ts +2 -2
  86. package/src/lib/input_path.ts +20 -21
  87. package/src/lib/invoke_task.ts +2 -2
  88. package/src/lib/lint.task.ts +1 -1
  89. package/src/lib/loader.ts +1 -1
  90. package/src/lib/modules.ts +2 -2
  91. package/src/lib/package_json.ts +16 -20
  92. package/src/lib/publish.task.ts +6 -6
  93. package/src/lib/release.task.ts +1 -1
  94. package/src/lib/resolve.task.ts +2 -2
  95. package/src/lib/resolve_specifier.ts +8 -4
  96. package/src/lib/run.task.ts +2 -2
  97. package/src/lib/run_gen.ts +15 -10
  98. package/src/lib/run_task.ts +4 -4
  99. package/src/lib/source_json.ts +25 -19
  100. package/src/lib/sveltekit_helpers.ts +3 -3
  101. package/src/lib/task.ts +11 -9
  102. package/src/lib/test.task.ts +4 -3
  103. package/src/lib/typecheck.task.ts +3 -3
  104. package/src/lib/upgrade.task.ts +4 -4
  105. package/dist/search_fs.d.ts +0 -26
  106. package/dist/search_fs.d.ts.map +0 -1
  107. package/dist/search_fs.js +0 -52
  108. package/src/lib/search_fs.ts +0 -100
@@ -2,6 +2,7 @@ import {styleText as st} from 'node:util';
2
2
  import {print_error} from '@ryanatkn/belt/print.js';
3
3
  import type {Timings} from '@ryanatkn/belt/timings.js';
4
4
  import type {Logger} from '@ryanatkn/belt/log.js';
5
+ import {map_concurrent} from '@ryanatkn/belt/async.js';
5
6
 
6
7
  import {
7
8
  type GenResults,
@@ -33,8 +34,9 @@ export const run_gen = async (
33
34
  let input_count = 0;
34
35
  let output_count = 0;
35
36
  const timing_for_run_gen = timings.start('run_gen');
36
- const results = await Promise.all(
37
- gen_modules.map(async (module_meta): Promise<GenfileModuleResult> => {
37
+ const results = await map_concurrent(
38
+ gen_modules,
39
+ async (module_meta): Promise<GenfileModuleResult> => {
38
40
  input_count++;
39
41
  const {id} = module_meta;
40
42
  const timing_for_module = timings.start(id);
@@ -54,11 +56,11 @@ export const run_gen = async (
54
56
  let raw_gen_result: RawGenResult;
55
57
  try {
56
58
  raw_gen_result = await gen_config.generate(gen_ctx);
57
- } catch (err) {
59
+ } catch (error) {
58
60
  return {
59
61
  ok: false,
60
62
  id,
61
- error: err,
63
+ error,
62
64
  reason: st('red', `Error generating ${print_path(id)}`),
63
65
  elapsed: timing_for_module(),
64
66
  };
@@ -69,19 +71,21 @@ export const run_gen = async (
69
71
 
70
72
  // Format the files if needed.
71
73
  const files = format_file
72
- ? await Promise.all(
73
- gen_result.files.map(async (file) => {
74
+ ? await map_concurrent(
75
+ gen_result.files,
76
+ async (file) => {
74
77
  if (!file.format) return file;
75
78
  try {
76
79
  return {...file, content: await format_file(file.content, {filepath: file.id})};
77
- } catch (err) {
80
+ } catch (error) {
78
81
  log.error(
79
82
  st('red', `Error formatting ${print_path(file.id)} via ${print_path(id)}`),
80
- print_error(err),
83
+ print_error(error),
81
84
  );
82
85
  return file;
83
86
  }
84
- }),
87
+ },
88
+ 10,
85
89
  )
86
90
  : gen_result.files;
87
91
 
@@ -92,7 +96,8 @@ export const run_gen = async (
92
96
  files,
93
97
  elapsed: timing_for_module(),
94
98
  };
95
- }),
99
+ },
100
+ 10,
96
101
  );
97
102
  return {
98
103
  results,
@@ -63,19 +63,19 @@ export const run_task = async (
63
63
  invoke_task: (invoked_task_name, invoked_args, invoked_config) =>
64
64
  invoke_task(invoked_task_name, invoked_args, invoked_config ?? config, filer, timings, log),
65
65
  });
66
- } catch (err) {
66
+ } catch (error) {
67
67
  return {
68
68
  ok: false,
69
69
  reason: st(
70
70
  'red',
71
- err?.constructor?.name === 'TaskError'
72
- ? (err.message as string)
71
+ error?.constructor?.name === 'TaskError'
72
+ ? (error.message as string)
73
73
  : `Unexpected error running task ${st(
74
74
  'cyan',
75
75
  task_meta.name,
76
76
  )}. If this is unexpected try running \`${config.pm_cli} install\` and \`gro clean\`.`,
77
77
  ),
78
- error: err,
78
+ error,
79
79
  };
80
80
  }
81
81
  return {ok: true, output};
@@ -1,6 +1,6 @@
1
1
  import {join} from 'node:path';
2
2
  import {ensure_end, strip_start} from '@ryanatkn/belt/string.js';
3
- import {existsSync} from 'node:fs';
3
+ import {fs_exists, fs_search} from '@ryanatkn/belt/fs.js';
4
4
  import ts from 'typescript';
5
5
  import type {PackageJson, PackageJsonExports} from '@ryanatkn/belt/package_json.js';
6
6
  import {SourceJson, type ModuleJson, type DeclarationKind} from '@ryanatkn/belt/source_json.js';
@@ -9,19 +9,20 @@ import type {Logger} from '@ryanatkn/belt/log.js';
9
9
  import {paths, replace_extension} from './paths.ts';
10
10
  import {parse_exports} from './parse_exports.ts';
11
11
  import {TS_MATCHER, SVELTE_MATCHER, JSON_MATCHER, CSS_MATCHER} from './constants.ts';
12
- import {search_fs} from './search_fs.ts';
13
12
 
14
- export type SourceJsonMapper = (source_json: SourceJson) => SourceJson | null | Promise<SourceJson | null>;
13
+ export type SourceJsonMapper = (
14
+ source_json: SourceJson,
15
+ ) => SourceJson | null | Promise<SourceJson | null>;
15
16
 
16
- export const source_json_create = (
17
+ export const source_json_create = async (
17
18
  package_json: PackageJson,
18
19
  lib_path?: string,
19
20
  log?: Logger,
20
- ): SourceJson =>
21
+ ): Promise<SourceJson> =>
21
22
  SourceJson.parse({
22
23
  name: package_json.name,
23
24
  version: package_json.version,
24
- modules: source_modules_create(package_json.exports, lib_path, log),
25
+ modules: await source_modules_create(package_json.exports, lib_path, log),
25
26
  });
26
27
 
27
28
  export const source_json_serialize = (source_json: SourceJson): string => {
@@ -29,14 +30,14 @@ export const source_json_serialize = (source_json: SourceJson): string => {
29
30
  return JSON.stringify(parsed, null, 2) + '\n';
30
31
  };
31
32
 
32
- export const source_modules_create = (
33
+ export const source_modules_create = async (
33
34
  exports: PackageJsonExports | undefined,
34
35
  lib_path = paths.lib,
35
36
  log?: Logger,
36
- ): Array<ModuleJson> | undefined => {
37
+ ): Promise<Array<ModuleJson> | undefined> => {
37
38
  if (!exports) return;
38
39
 
39
- const file_paths = collect_file_paths(exports, lib_path);
40
+ const file_paths = await collect_file_paths(exports, lib_path);
40
41
 
41
42
  // Create a TypeScript program for all TypeScript files
42
43
  const ts_files = file_paths
@@ -83,15 +84,15 @@ export const source_modules_create = (
83
84
  return result;
84
85
  };
85
86
 
86
- const collect_file_paths = (
87
+ const collect_file_paths = async (
87
88
  exports: PackageJsonExports,
88
89
  lib_path: string,
89
- ): Array<{export_key: string; file_path: string}> => {
90
+ ): Promise<Array<{export_key: string; file_path: string}>> => {
90
91
  const file_paths: Array<{export_key: string; file_path: string}> = [];
91
92
 
92
93
  // Handle string exports (single default export)
93
94
  if (typeof exports === 'string') {
94
- const source_file = infer_source_from_export(exports, lib_path);
95
+ const source_file = await infer_source_from_export(exports, lib_path);
95
96
  if (source_file) {
96
97
  file_paths.push({export_key: '.', file_path: source_file});
97
98
  } else {
@@ -110,7 +111,8 @@ const collect_file_paths = (
110
111
  // Check if this is a pattern export
111
112
  if (k.includes('*')) {
112
113
  // Handle pattern exports by finding matching files in lib
113
- const matching_files = search_fs(lib_path, {
114
+ // eslint-disable-next-line no-await-in-loop
115
+ const matching_files = await fs_search(lib_path, {
114
116
  file_filter: (path) => {
115
117
  const p = path.replace(ensure_end(lib_path, '/'), '');
116
118
  // Only match files in the root directory (no subdirectories)
@@ -142,7 +144,8 @@ const collect_file_paths = (
142
144
  }
143
145
  } else {
144
146
  // Handle explicit exports (non-patterns)
145
- const source_file = infer_source_from_export(k, lib_path);
147
+ // eslint-disable-next-line no-await-in-loop
148
+ const source_file = await infer_source_from_export(k, lib_path);
146
149
  if (source_file) {
147
150
  file_paths.push({export_key: k, file_path: source_file});
148
151
  } else {
@@ -156,13 +159,16 @@ const collect_file_paths = (
156
159
  return file_paths;
157
160
  };
158
161
 
159
- const infer_source_from_export = (export_path: string, lib_path: string): string | null => {
162
+ const infer_source_from_export = async (
163
+ export_path: string,
164
+ lib_path: string,
165
+ ): Promise<string | null> => {
160
166
  // Handle index specially
161
167
  if (export_path === '.' || export_path === './') {
162
168
  const index_ts = join(lib_path, 'index.ts');
163
- if (existsSync(index_ts)) return index_ts;
169
+ if (await fs_exists(index_ts)) return index_ts;
164
170
  const index_js = join(lib_path, 'index.js');
165
- if (existsSync(index_js)) return index_js;
171
+ if (await fs_exists(index_js)) return index_js;
166
172
  return null;
167
173
  }
168
174
 
@@ -171,12 +177,12 @@ const infer_source_from_export = (export_path: string, lib_path: string): string
171
177
  // For .js exports, try .ts first
172
178
  if (clean_path.endsWith('.js')) {
173
179
  const ts_path = join(lib_path, replace_extension(clean_path, '.ts'));
174
- if (existsSync(ts_path)) return ts_path;
180
+ if (await fs_exists(ts_path)) return ts_path;
175
181
  }
176
182
 
177
183
  // Try the exact path
178
184
  const exact_path = join(lib_path, clean_path);
179
- if (existsSync(exact_path)) return exact_path;
185
+ if (await fs_exists(exact_path)) return exact_path;
180
186
 
181
187
  return null;
182
188
  };
@@ -73,7 +73,7 @@ export const sveltekit_sync_if_available = async (
73
73
  sveltekit_cli: string | Cli = SVELTEKIT_CLI,
74
74
  ): Promise<void> => {
75
75
  const found_sveltekit_cli =
76
- typeof sveltekit_cli === 'string' ? find_cli(sveltekit_cli) : sveltekit_cli;
76
+ typeof sveltekit_cli === 'string' ? await find_cli(sveltekit_cli) : sveltekit_cli;
77
77
  if (found_sveltekit_cli) {
78
78
  return sveltekit_sync(found_sveltekit_cli);
79
79
  }
@@ -89,7 +89,7 @@ export const sveltekit_sync_if_obviously_needed = async (
89
89
  return;
90
90
  }
91
91
  const found_sveltekit_cli =
92
- typeof sveltekit_cli === 'string' ? find_cli(sveltekit_cli) : sveltekit_cli;
92
+ typeof sveltekit_cli === 'string' ? await find_cli(sveltekit_cli) : sveltekit_cli;
93
93
  if (!found_sveltekit_cli) {
94
94
  return;
95
95
  }
@@ -160,7 +160,7 @@ export const run_svelte_package = async (
160
160
  );
161
161
  }
162
162
  const cli_name = typeof cli === 'string' ? cli : cli.name;
163
- const found_svelte_package_cli = cli === cli_name ? find_cli(cli) : (cli as Cli);
163
+ const found_svelte_package_cli = cli === cli_name ? await find_cli(cli) : (cli as Cli);
164
164
  if (found_svelte_package_cli?.kind !== 'local') {
165
165
  throw new TaskError(
166
166
  `Failed to find SvelteKit packaging CLI \`${cli_name}\`, do you need to run \`${pm_cli} install\`?`,
package/src/lib/task.ts CHANGED
@@ -6,6 +6,7 @@ import {styleText as st} from 'node:util';
6
6
  import type {Result} from '@ryanatkn/belt/result.js';
7
7
  import {isAbsolute, join, relative} from 'node:path';
8
8
  import type {PathId} from '@ryanatkn/belt/path.js';
9
+ import {fs_search} from '@ryanatkn/belt/fs.js';
9
10
 
10
11
  import type {Args} from './args.ts';
11
12
  import type {GroConfig} from './gro_config.ts';
@@ -18,7 +19,6 @@ import {
18
19
  type ResolvedInputPath,
19
20
  } from './input_path.ts';
20
21
  import {GRO_DIST_DIR, print_path} from './paths.ts';
21
- import {search_fs} from './search_fs.ts';
22
22
  import {load_modules, type LoadModulesFailure, type ModuleMeta} from './modules.ts';
23
23
  import type {Filer} from './filer.ts';
24
24
 
@@ -126,15 +126,15 @@ export type FindModulesFailure =
126
126
  /**
127
127
  * Finds modules from input paths. (see `src/lib/input_path.ts` for more)
128
128
  */
129
- export const find_tasks = (
129
+ export const find_tasks = async (
130
130
  input_paths: Array<InputPath>,
131
131
  task_root_dirs: Array<PathId>,
132
132
  config: GroConfig,
133
133
  timings?: Timings,
134
- ): FindTasksResult => {
134
+ ): Promise<FindTasksResult> => {
135
135
  // Check which extension variation works - if it's a directory, prefer others first!
136
136
  const timing_to_resolve_input_paths = timings?.start('resolve input paths');
137
- const {resolved_input_paths, unmapped_input_paths} = resolve_input_paths(
137
+ const {resolved_input_paths, unmapped_input_paths} = await resolve_input_paths(
138
138
  input_paths,
139
139
  task_root_dirs,
140
140
  TASK_FILE_SUFFIXES,
@@ -159,11 +159,13 @@ export const find_tasks = (
159
159
  // Find all of the files for any directories.
160
160
  const timing_to_resolve_input_files = timings?.start('resolve input files');
161
161
  const {resolved_input_files, resolved_input_files_by_root_dir, input_directories_with_no_files} =
162
- resolve_input_files(resolved_input_paths, (id) =>
163
- search_fs(id, {
164
- filter: config.search_filters,
165
- file_filter: (p) => TASK_FILE_SUFFIXES.some((s) => p.endsWith(s)),
166
- }),
162
+ await resolve_input_files(
163
+ resolved_input_paths,
164
+ async (id) =>
165
+ await fs_search(id, {
166
+ filter: config.search_filters,
167
+ file_filter: (p) => TASK_FILE_SUFFIXES.some((s) => p.endsWith(s)),
168
+ }),
167
169
  );
168
170
  timing_to_resolve_input_files?.();
169
171
 
@@ -3,7 +3,7 @@ import {spawn_cli} from '@ryanatkn/gro/cli.js';
3
3
 
4
4
  import {TaskError, type Task} from './task.ts';
5
5
  import {find_cli} from './cli.ts';
6
- import {has_dep} from './package_json.ts';
6
+ import {has_dep, load_package_json} from './package_json.ts';
7
7
  import {serialize_args, to_implicit_forwarded_args} from './args.ts';
8
8
  import {VITEST_CLI} from './constants.ts';
9
9
  import {paths} from './paths.ts';
@@ -30,11 +30,12 @@ export const task: Task<Args> = {
30
30
  run: async ({args}): Promise<void> => {
31
31
  const {_: patterns, dir, fail_without_tests, t} = args;
32
32
 
33
- if (!has_dep(VITEST_CLI)) {
33
+ const package_json = await load_package_json();
34
+ if (!has_dep(VITEST_CLI, package_json)) {
34
35
  throw new TaskError('no test runner found, install vitest');
35
36
  }
36
37
 
37
- if (!find_cli(VITEST_CLI)) {
38
+ if (!(await find_cli(VITEST_CLI))) {
38
39
  throw new TaskError('vitest is a dependency but not installed; run `npm i`?');
39
40
  }
40
41
 
@@ -37,10 +37,10 @@ export const task: Task<Args> = {
37
37
  await sveltekit_sync_if_available();
38
38
 
39
39
  // Prefer svelte-check if available.
40
- const found_svelte_check_cli = find_cli(svelte_check_cli);
40
+ const found_svelte_check_cli = await find_cli(svelte_check_cli);
41
41
  if (found_svelte_check_cli) {
42
42
  const serialized = serialize_args(to_forwarded_args(svelte_check_cli));
43
- const spawned = spawn_cli_process(found_svelte_check_cli, serialized, undefined, {
43
+ const spawned = await spawn_cli_process(found_svelte_check_cli, serialized, undefined, {
44
44
  stdio: ['inherit', 'pipe', 'pipe'],
45
45
  env: {...process.env, FORCE_COLOR: '1'}, // Needed for colors (maybe make an option)
46
46
  });
@@ -61,7 +61,7 @@ export const task: Task<Args> = {
61
61
  }
62
62
 
63
63
  // Fall back to tsc.
64
- const found_typescript_cli = find_cli(typescript_cli);
64
+ const found_typescript_cli = await find_cli(typescript_cli);
65
65
  if (found_typescript_cli) {
66
66
  const forwarded = to_forwarded_args(typescript_cli);
67
67
  if (!forwarded.noEmit) forwarded.noEmit = true;
@@ -1,6 +1,6 @@
1
1
  import {spawn} from '@ryanatkn/belt/process.js';
2
2
  import {z} from 'zod';
3
- import {rmSync} from 'node:fs';
3
+ import {rm} from 'node:fs/promises';
4
4
  import {GitOrigin, git_pull} from '@ryanatkn/belt/git.js';
5
5
 
6
6
  import {TaskError, type Task} from './task.ts';
@@ -75,15 +75,15 @@ export const task: Task<Args> = {
75
75
 
76
76
  if (delete_node_modules) {
77
77
  log.info(`deleting node_modules at `, node_modules_path);
78
- rmSync(node_modules_path, {recursive: true, force: true});
78
+ await rm(node_modules_path, {recursive: true, force: true});
79
79
  }
80
80
 
81
81
  if (delete_lockfile) {
82
82
  log.info(`deleting lockfile at`, lockfile_path);
83
- rmSync(lockfile_path, {force: true});
83
+ await rm(lockfile_path, {force: true});
84
84
  }
85
85
 
86
- const package_json = load_package_json();
86
+ const package_json = await load_package_json();
87
87
 
88
88
  const all_deps = extract_deps(package_json);
89
89
 
@@ -1,26 +0,0 @@
1
- import type { FileFilter, ResolvedPath, PathFilter } from '@ryanatkn/belt/path.js';
2
- export interface SearchFsOptions {
3
- /**
4
- * One or more filter functions, any of which can short-circuit the search by returning `false`.
5
- */
6
- filter?: PathFilter | Array<PathFilter>;
7
- /**
8
- * One or more file filter functions. Every filter must pass for a file to be included.
9
- */
10
- file_filter?: FileFilter | Array<FileFilter>;
11
- /**
12
- * Pass `null` or `false` to speed things up at the cost of volatile ordering.
13
- */
14
- sort?: boolean | null | ((a: ResolvedPath, b: ResolvedPath) => number);
15
- /**
16
- * Set to `true` to include directories. Defaults to `false`.
17
- */
18
- include_directories?: boolean;
19
- /**
20
- * Sets the cwd for `dir` unless it's an absolute path or `null`.
21
- */
22
- cwd?: string | null;
23
- }
24
- export declare const search_fs: (dir: string, options?: SearchFsOptions) => Array<ResolvedPath>;
25
- export declare const find_first_existing_file: (paths: Array<string>) => string | null;
26
- //# sourceMappingURL=search_fs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"search_fs.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/search_fs.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,UAAU,EAAE,YAAY,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAEjF,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;IAC7C;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,KAAK,MAAM,CAAC,CAAC;IACvE;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,GACrB,KAAK,MAAM,EACX,UAAS,eAA8B,KACrC,KAAK,CAAC,YAAY,CAwBpB,CAAC;AAmCF,eAAO,MAAM,wBAAwB,GAAI,OAAO,KAAK,CAAC,MAAM,CAAC,KAAG,MAAM,GAAG,IAOxE,CAAC"}
package/dist/search_fs.js DELETED
@@ -1,52 +0,0 @@
1
- import { EMPTY_OBJECT } from '@ryanatkn/belt/object.js';
2
- import { to_array } from '@ryanatkn/belt/array.js';
3
- import { ensure_end } from '@ryanatkn/belt/string.js';
4
- import { isAbsolute, join } from 'node:path';
5
- import { existsSync, readdirSync } from 'node:fs';
6
- export const search_fs = (dir, options = EMPTY_OBJECT) => {
7
- const { filter, file_filter, sort = default_sort, include_directories = false, cwd = process.cwd(), } = options;
8
- const final_dir = ensure_end(cwd && !isAbsolute(dir) ? join(cwd, dir) : dir, '/');
9
- const filters = !filter || (Array.isArray(filter) && !filter.length) ? undefined : to_array(filter);
10
- const file_filters = !file_filter || (Array.isArray(file_filter) && !file_filter.length)
11
- ? undefined
12
- : to_array(file_filter);
13
- if (!existsSync(final_dir))
14
- return [];
15
- const paths = [];
16
- crawl(final_dir, paths, filters, file_filters, include_directories, null);
17
- return sort ? paths.sort(typeof sort === 'boolean' ? default_sort : sort) : paths;
18
- };
19
- const default_sort = (a, b) => a.path.localeCompare(b.path);
20
- const crawl = (dir, paths, filters, file_filter, include_directories, base_dir) => {
21
- // This sync version is significantly faster than using the `fs/promises` version -
22
- // it doesn't parallelize but that's not the common case in Gro.
23
- const dirents = readdirSync(dir, { withFileTypes: true });
24
- for (const dirent of dirents) {
25
- const { name, parentPath } = dirent;
26
- const is_directory = dirent.isDirectory();
27
- const id = parentPath + name;
28
- const include = !filters || filters.every((f) => f(id, is_directory));
29
- if (!include)
30
- continue;
31
- const path = base_dir === null ? name : base_dir + '/' + name;
32
- if (is_directory) {
33
- const dir_id = id + '/';
34
- if (include_directories) {
35
- paths.push({ path, id: dir_id, is_directory: true });
36
- }
37
- crawl(dir_id, paths, filters, file_filter, include_directories, path);
38
- }
39
- else if (!file_filter || file_filter.every((f) => f(id))) {
40
- paths.push({ path, id, is_directory: false });
41
- }
42
- }
43
- return paths;
44
- };
45
- export const find_first_existing_file = (paths) => {
46
- for (const path of paths) {
47
- if (existsSync(path)) {
48
- return path;
49
- }
50
- }
51
- return null;
52
- };
@@ -1,100 +0,0 @@
1
- import {EMPTY_OBJECT} from '@ryanatkn/belt/object.js';
2
- import {to_array} from '@ryanatkn/belt/array.js';
3
- import {ensure_end} from '@ryanatkn/belt/string.js';
4
- import {isAbsolute, join} from 'node:path';
5
- import {existsSync, readdirSync} from 'node:fs';
6
- import type {FileFilter, ResolvedPath, PathFilter} from '@ryanatkn/belt/path.js';
7
-
8
- export interface SearchFsOptions {
9
- /**
10
- * One or more filter functions, any of which can short-circuit the search by returning `false`.
11
- */
12
- filter?: PathFilter | Array<PathFilter>;
13
- /**
14
- * One or more file filter functions. Every filter must pass for a file to be included.
15
- */
16
- file_filter?: FileFilter | Array<FileFilter>;
17
- /**
18
- * Pass `null` or `false` to speed things up at the cost of volatile ordering.
19
- */
20
- sort?: boolean | null | ((a: ResolvedPath, b: ResolvedPath) => number);
21
- /**
22
- * Set to `true` to include directories. Defaults to `false`.
23
- */
24
- include_directories?: boolean;
25
- /**
26
- * Sets the cwd for `dir` unless it's an absolute path or `null`.
27
- */
28
- cwd?: string | null;
29
- }
30
-
31
- export const search_fs = (
32
- dir: string,
33
- options: SearchFsOptions = EMPTY_OBJECT,
34
- ): Array<ResolvedPath> => {
35
- const {
36
- filter,
37
- file_filter,
38
- sort = default_sort,
39
- include_directories = false,
40
- cwd = process.cwd(),
41
- } = options;
42
-
43
- const final_dir = ensure_end(cwd && !isAbsolute(dir) ? join(cwd, dir) : dir, '/');
44
-
45
- const filters =
46
- !filter || (Array.isArray(filter) && !filter.length) ? undefined : to_array(filter);
47
- const file_filters =
48
- !file_filter || (Array.isArray(file_filter) && !file_filter.length)
49
- ? undefined
50
- : to_array(file_filter);
51
-
52
- if (!existsSync(final_dir)) return [];
53
-
54
- const paths: Array<ResolvedPath> = [];
55
- crawl(final_dir, paths, filters, file_filters, include_directories, null);
56
-
57
- return sort ? paths.sort(typeof sort === 'boolean' ? default_sort : sort) : paths;
58
- };
59
-
60
- const default_sort = (a: ResolvedPath, b: ResolvedPath): number => a.path.localeCompare(b.path);
61
-
62
- const crawl = (
63
- dir: string,
64
- paths: Array<ResolvedPath>,
65
- filters: Array<PathFilter> | undefined,
66
- file_filter: Array<FileFilter> | undefined,
67
- include_directories: boolean,
68
- base_dir: string | null,
69
- ): Array<ResolvedPath> => {
70
- // This sync version is significantly faster than using the `fs/promises` version -
71
- // it doesn't parallelize but that's not the common case in Gro.
72
- const dirents = readdirSync(dir, {withFileTypes: true});
73
- for (const dirent of dirents) {
74
- const {name, parentPath} = dirent;
75
- const is_directory = dirent.isDirectory();
76
- const id = parentPath + name;
77
- const include = !filters || filters.every((f) => f(id, is_directory));
78
- if (!include) continue;
79
- const path = base_dir === null ? name : base_dir + '/' + name;
80
- if (is_directory) {
81
- const dir_id = id + '/';
82
- if (include_directories) {
83
- paths.push({path, id: dir_id, is_directory: true});
84
- }
85
- crawl(dir_id, paths, filters, file_filter, include_directories, path);
86
- } else if (!file_filter || file_filter.every((f) => f(id))) {
87
- paths.push({path, id, is_directory: false});
88
- }
89
- }
90
- return paths;
91
- };
92
-
93
- export const find_first_existing_file = (paths: Array<string>): string | null => {
94
- for (const path of paths) {
95
- if (existsSync(path)) {
96
- return path;
97
- }
98
- }
99
- return null;
100
- };