@ryanatkn/gro 0.179.0 → 0.181.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 (196) hide show
  1. package/README.md +1 -1
  2. package/dist/build.task.d.ts +2 -0
  3. package/dist/build.task.d.ts.map +1 -1
  4. package/dist/build.task.js +15 -11
  5. package/dist/build_cache.d.ts +4 -4
  6. package/dist/build_cache.d.ts.map +1 -1
  7. package/dist/build_cache.js +54 -44
  8. package/dist/changelog.d.ts +2 -2
  9. package/dist/changelog.d.ts.map +1 -1
  10. package/dist/changeset.task.js +11 -11
  11. package/dist/check.task.js +2 -2
  12. package/dist/child_process_logging.js +1 -1
  13. package/dist/clean.task.js +2 -2
  14. package/dist/clean_fs.d.ts +1 -1
  15. package/dist/clean_fs.d.ts.map +1 -1
  16. package/dist/clean_fs.js +3 -4
  17. package/dist/cli.d.ts +7 -7
  18. package/dist/cli.d.ts.map +1 -1
  19. package/dist/cli.js +11 -12
  20. package/dist/commit.task.js +2 -2
  21. package/dist/deploy.task.d.ts +7 -0
  22. package/dist/deploy.task.d.ts.map +1 -1
  23. package/dist/deploy.task.js +30 -17
  24. package/dist/disknode.d.ts +1 -1
  25. package/dist/disknode.d.ts.map +1 -1
  26. package/dist/esbuild_helpers.d.ts +1 -1
  27. package/dist/esbuild_helpers.d.ts.map +1 -1
  28. package/dist/esbuild_plugin_external_worker.d.ts +1 -1
  29. package/dist/esbuild_plugin_external_worker.d.ts.map +1 -1
  30. package/dist/esbuild_plugin_external_worker.js +1 -1
  31. package/dist/esbuild_plugin_svelte.js +4 -4
  32. package/dist/esbuild_plugin_sveltekit_local_imports.js +2 -2
  33. package/dist/esbuild_plugin_sveltekit_shim_alias.js +1 -1
  34. package/dist/filer.d.ts +4 -4
  35. package/dist/filer.d.ts.map +1 -1
  36. package/dist/filer.js +105 -54
  37. package/dist/format.task.js +1 -1
  38. package/dist/format_directory.d.ts +2 -2
  39. package/dist/format_directory.d.ts.map +1 -1
  40. package/dist/format_file.js +1 -1
  41. package/dist/gen.d.ts +5 -5
  42. package/dist/gen.d.ts.map +1 -1
  43. package/dist/gen.js +28 -22
  44. package/dist/gen.task.js +3 -3
  45. package/dist/gen_helpers.d.ts +3 -3
  46. package/dist/gen_helpers.d.ts.map +1 -1
  47. package/dist/github.d.ts +2 -2
  48. package/dist/github.d.ts.map +1 -1
  49. package/dist/github.js +1 -1
  50. package/dist/gro.config.default.js +1 -1
  51. package/dist/gro_config.d.ts +1 -1
  52. package/dist/gro_config.d.ts.map +1 -1
  53. package/dist/gro_config.js +4 -4
  54. package/dist/gro_helpers.d.ts +1 -1
  55. package/dist/gro_helpers.d.ts.map +1 -1
  56. package/dist/gro_helpers.js +1 -1
  57. package/dist/gro_plugin_gen.js +4 -4
  58. package/dist/gro_plugin_server.d.ts +2 -2
  59. package/dist/gro_plugin_server.d.ts.map +1 -1
  60. package/dist/gro_plugin_server.js +7 -7
  61. package/dist/gro_plugin_sveltekit_app.d.ts.map +1 -1
  62. package/dist/gro_plugin_sveltekit_app.js +40 -36
  63. package/dist/gro_plugin_sveltekit_library.js +3 -2
  64. package/dist/input_path.d.ts +5 -5
  65. package/dist/input_path.d.ts.map +1 -1
  66. package/dist/input_path.js +17 -15
  67. package/dist/invoke.js +2 -2
  68. package/dist/invoke_task.d.ts +2 -2
  69. package/dist/invoke_task.d.ts.map +1 -1
  70. package/dist/invoke_task.js +5 -5
  71. package/dist/lint.task.js +2 -2
  72. package/dist/loader.js +2 -2
  73. package/dist/modules.d.ts +3 -3
  74. package/dist/modules.d.ts.map +1 -1
  75. package/dist/modules.js +4 -4
  76. package/dist/package_json.d.ts +6 -6
  77. package/dist/package_json.d.ts.map +1 -1
  78. package/dist/package_json.js +14 -16
  79. package/dist/parse_exports.d.ts +4 -4
  80. package/dist/parse_exports.d.ts.map +1 -1
  81. package/dist/parse_exports_context.d.ts +1 -1
  82. package/dist/parse_exports_context.d.ts.map +1 -1
  83. package/dist/parse_imports.d.ts +2 -2
  84. package/dist/parse_imports.d.ts.map +1 -1
  85. package/dist/parse_imports.js +1 -1
  86. package/dist/paths.d.ts +1 -1
  87. package/dist/paths.d.ts.map +1 -1
  88. package/dist/paths.js +1 -1
  89. package/dist/publish.task.js +8 -8
  90. package/dist/reinstall.task.js +1 -1
  91. package/dist/release.task.js +1 -1
  92. package/dist/resolve.task.js +2 -2
  93. package/dist/resolve_specifier.d.ts +2 -2
  94. package/dist/resolve_specifier.d.ts.map +1 -1
  95. package/dist/resolve_specifier.js +5 -4
  96. package/dist/run.task.js +2 -2
  97. package/dist/run_gen.d.ts +2 -2
  98. package/dist/run_gen.d.ts.map +1 -1
  99. package/dist/run_gen.js +10 -9
  100. package/dist/run_task.d.ts +2 -2
  101. package/dist/run_task.d.ts.map +1 -1
  102. package/dist/run_task.js +4 -4
  103. package/dist/source_json.d.ts +5 -5
  104. package/dist/source_json.d.ts.map +1 -1
  105. package/dist/source_json.js +18 -17
  106. package/dist/svelte_config.js +1 -1
  107. package/dist/sveltekit_helpers.d.ts +3 -3
  108. package/dist/sveltekit_helpers.d.ts.map +1 -1
  109. package/dist/sveltekit_helpers.js +4 -4
  110. package/dist/sveltekit_shim_app_forms.js +1 -1
  111. package/dist/sveltekit_shim_app_navigation.js +1 -1
  112. package/dist/sveltekit_shim_app_paths.js +1 -1
  113. package/dist/sveltekit_shim_env.js +1 -1
  114. package/dist/sync.task.js +1 -1
  115. package/dist/task.d.ts +5 -5
  116. package/dist/task.d.ts.map +1 -1
  117. package/dist/task.js +5 -5
  118. package/dist/task_logging.d.ts +1 -1
  119. package/dist/task_logging.d.ts.map +1 -1
  120. package/dist/task_logging.js +2 -2
  121. package/dist/test.task.d.ts.map +1 -1
  122. package/dist/test.task.js +5 -4
  123. package/dist/typecheck.task.js +4 -4
  124. package/dist/upgrade.task.js +6 -6
  125. package/dist/watch_dir.d.ts +1 -1
  126. package/dist/watch_dir.d.ts.map +1 -1
  127. package/dist/watch_dir.js +2 -2
  128. package/package.json +8 -8
  129. package/src/lib/build.task.ts +16 -11
  130. package/src/lib/build_cache.ts +81 -65
  131. package/src/lib/changelog.ts +2 -2
  132. package/src/lib/changeset.task.ts +12 -12
  133. package/src/lib/check.task.ts +2 -2
  134. package/src/lib/child_process_logging.ts +1 -1
  135. package/src/lib/clean.task.ts +2 -2
  136. package/src/lib/clean_fs.ts +4 -4
  137. package/src/lib/cli.ts +18 -17
  138. package/src/lib/commit.task.ts +2 -2
  139. package/src/lib/deploy.task.ts +33 -16
  140. package/src/lib/disknode.ts +1 -1
  141. package/src/lib/esbuild_helpers.ts +1 -1
  142. package/src/lib/esbuild_plugin_external_worker.ts +3 -3
  143. package/src/lib/esbuild_plugin_svelte.ts +4 -4
  144. package/src/lib/esbuild_plugin_sveltekit_local_imports.ts +2 -2
  145. package/src/lib/esbuild_plugin_sveltekit_shim_alias.ts +1 -1
  146. package/src/lib/filer.ts +117 -58
  147. package/src/lib/format.task.ts +1 -1
  148. package/src/lib/format_directory.ts +2 -2
  149. package/src/lib/format_file.ts +1 -1
  150. package/src/lib/gen.task.ts +3 -3
  151. package/src/lib/gen.ts +56 -50
  152. package/src/lib/gen_helpers.ts +3 -3
  153. package/src/lib/github.ts +2 -2
  154. package/src/lib/gro.config.default.ts +1 -1
  155. package/src/lib/gro_config.ts +5 -5
  156. package/src/lib/gro_helpers.ts +1 -1
  157. package/src/lib/gro_plugin_gen.ts +4 -4
  158. package/src/lib/gro_plugin_server.ts +9 -9
  159. package/src/lib/gro_plugin_sveltekit_app.ts +44 -40
  160. package/src/lib/gro_plugin_sveltekit_library.ts +3 -3
  161. package/src/lib/input_path.ts +23 -24
  162. package/src/lib/invoke.ts +2 -2
  163. package/src/lib/invoke_task.ts +5 -5
  164. package/src/lib/lint.task.ts +2 -2
  165. package/src/lib/loader.ts +2 -2
  166. package/src/lib/modules.ts +7 -7
  167. package/src/lib/package_json.ts +19 -23
  168. package/src/lib/parse_exports.ts +4 -4
  169. package/src/lib/parse_exports_context.ts +2 -2
  170. package/src/lib/parse_imports.ts +3 -3
  171. package/src/lib/paths.ts +2 -2
  172. package/src/lib/publish.task.ts +8 -8
  173. package/src/lib/reinstall.task.ts +1 -1
  174. package/src/lib/release.task.ts +1 -1
  175. package/src/lib/resolve.task.ts +2 -2
  176. package/src/lib/resolve_specifier.ts +9 -5
  177. package/src/lib/run.task.ts +2 -2
  178. package/src/lib/run_gen.ts +18 -13
  179. package/src/lib/run_task.ts +6 -6
  180. package/src/lib/source_json.ts +26 -22
  181. package/src/lib/svelte_config.ts +1 -1
  182. package/src/lib/sveltekit_helpers.ts +7 -7
  183. package/src/lib/sveltekit_shim_app_forms.ts +1 -1
  184. package/src/lib/sveltekit_shim_app_navigation.ts +1 -1
  185. package/src/lib/sveltekit_shim_app_paths.ts +1 -1
  186. package/src/lib/sync.task.ts +1 -1
  187. package/src/lib/task.ts +16 -14
  188. package/src/lib/task_logging.ts +3 -3
  189. package/src/lib/test.task.ts +4 -3
  190. package/src/lib/typecheck.task.ts +4 -4
  191. package/src/lib/upgrade.task.ts +6 -6
  192. package/src/lib/watch_dir.ts +3 -3
  193. package/dist/search_fs.d.ts +0 -26
  194. package/dist/search_fs.d.ts.map +0 -1
  195. package/dist/search_fs.js +0 -52
  196. package/src/lib/search_fs.ts +0 -100
@@ -1,8 +1,9 @@
1
1
  import {z} from 'zod';
2
2
  import {styleText as st} from 'node:util';
3
- import {git_check_clean_workspace, git_current_commit_hash} from '@ryanatkn/belt/git.js';
4
- import {rmSync, existsSync} from 'node:fs';
3
+ import {git_check_clean_workspace, git_current_commit_hash} from '@fuzdev/fuz_util/git.js';
4
+ import {rm} from 'node:fs/promises';
5
5
  import {join} from 'node:path';
6
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
6
7
 
7
8
  import {TaskError, type Task} from './task.ts';
8
9
  import {Plugins} from './plugin.ts';
@@ -19,6 +20,8 @@ import {paths} from './paths.ts';
19
20
  export const Args = z.strictObject({
20
21
  sync: z.boolean().meta({description: 'dual of no-sync'}).default(true),
21
22
  'no-sync': z.boolean().meta({description: 'opt out of gro sync'}).default(false),
23
+ gen: z.boolean().meta({description: 'dual of no-gen'}).default(true),
24
+ 'no-gen': z.boolean().meta({description: 'opt out of gro gen'}).default(false),
22
25
  install: z.boolean().meta({description: 'dual of no-install'}).default(true),
23
26
  'no-install': z // convenience, same as `gro build -- gro sync --no-install` but the latter takes precedence
24
27
  .boolean()
@@ -49,11 +52,15 @@ export const task: Task<Args> = {
49
52
  Args,
50
53
  run: async (ctx): Promise<void> => {
51
54
  const {args, invoke_task, log, config} = ctx;
52
- const {sync, install, force_build} = args;
55
+ const {sync, gen, install, force_build} = args;
53
56
 
54
57
  if (sync || install) {
55
58
  if (!sync) log.warn('sync is false but install is true, so ignoring the sync option');
56
- await invoke_task('sync', {install});
59
+ await invoke_task('sync', {install, gen: false});
60
+ }
61
+
62
+ if (gen) {
63
+ await invoke_task('gen');
57
64
  }
58
65
 
59
66
  // Batch git calls upfront for performance (spawning processes is expensive)
@@ -81,15 +88,13 @@ export const task: Task<Args> = {
81
88
  // Rationale: Uncommitted changes could be reverted, leaving cached outputs from reverted code.
82
89
  // This conservative approach prioritizes safety over convenience during development.
83
90
  const cache_path = join(paths.build, 'build.json');
84
- if (existsSync(cache_path)) {
85
- rmSync(cache_path, {force: true});
91
+ if (await fs_exists(cache_path)) {
92
+ await rm(cache_path, {force: true});
86
93
  }
87
94
 
88
95
  // Delete all build output directories
89
- build_dirs = discover_build_output_dirs();
90
- for (const dir of build_dirs) {
91
- rmSync(dir, {recursive: true, force: true});
92
- }
96
+ build_dirs = await discover_build_output_dirs();
97
+ await Promise.all(build_dirs.map((dir) => rm(dir, {recursive: true, force: true})));
93
98
 
94
99
  log.info(st('yellow', 'workspace has uncommitted changes - skipping build cache'));
95
100
  // Skip clean_fs - already manually cleaned cache and all build outputs above
@@ -138,7 +143,7 @@ export const task: Task<Args> = {
138
143
  } else {
139
144
  // Commit is stable - safe to save cache
140
145
  const metadata = await create_build_cache_metadata(config, log, initial_commit, build_dirs);
141
- save_build_cache_metadata(metadata, log);
146
+ await save_build_cache_metadata(metadata, log);
142
147
  log.debug('Build cache metadata saved');
143
148
  }
144
149
  }
@@ -1,16 +1,10 @@
1
- import {
2
- existsSync,
3
- mkdirSync,
4
- readdirSync,
5
- readFileSync,
6
- rmSync,
7
- statSync,
8
- writeFileSync,
9
- } from 'node:fs';
1
+ import {mkdir, readdir, readFile, rm, stat, writeFile} from 'node:fs/promises';
10
2
  import {join} from 'node:path';
11
- import type {Logger} from '@ryanatkn/belt/log.js';
3
+ import type {Logger} from '@fuzdev/fuz_util/log.js';
12
4
  import {styleText as st} from 'node:util';
13
- import {git_current_commit_hash} from '@ryanatkn/belt/git.js';
5
+ import {git_current_commit_hash} from '@fuzdev/fuz_util/git.js';
6
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
7
+ import {map_concurrent} from '@fuzdev/fuz_util/async.js';
14
8
  import {z} from 'zod';
15
9
 
16
10
  import {to_hash} from './hash.ts';
@@ -89,15 +83,15 @@ export const compute_build_cache_key = async (
89
83
  * Loads build cache metadata from .gro/ directory.
90
84
  * Invalid or corrupted cache files are automatically deleted.
91
85
  */
92
- export const load_build_cache_metadata = (): BuildCacheMetadata | null => {
86
+ export const load_build_cache_metadata = async (): Promise<BuildCacheMetadata | null> => {
93
87
  const metadata_path = join(paths.build, BUILD_CACHE_METADATA_FILENAME);
94
88
 
95
- if (!existsSync(metadata_path)) {
89
+ if (!(await fs_exists(metadata_path))) {
96
90
  return null;
97
91
  }
98
92
 
99
93
  try {
100
- const contents = readFileSync(metadata_path, 'utf-8');
94
+ const contents = await readFile(metadata_path, 'utf-8');
101
95
  const parsed = JSON.parse(contents);
102
96
 
103
97
  // Validate structure with Zod
@@ -107,7 +101,7 @@ export const load_build_cache_metadata = (): BuildCacheMetadata | null => {
107
101
  if (metadata.version !== BUILD_CACHE_VERSION) {
108
102
  // Clean up stale cache with old schema version
109
103
  try {
110
- rmSync(metadata_path, {force: true});
104
+ await rm(metadata_path, {force: true});
111
105
  } catch {
112
106
  // Ignore cleanup errors
113
107
  }
@@ -119,7 +113,7 @@ export const load_build_cache_metadata = (): BuildCacheMetadata | null => {
119
113
  // Clean up corrupted/invalid cache file
120
114
  // (catches JSON.parse, Zod validation, and version errors)
121
115
  try {
122
- rmSync(metadata_path, {force: true});
116
+ await rm(metadata_path, {force: true});
123
117
  } catch {
124
118
  // Ignore cleanup errors
125
119
  }
@@ -131,13 +125,16 @@ export const load_build_cache_metadata = (): BuildCacheMetadata | null => {
131
125
  * Saves build cache metadata to .gro/ directory.
132
126
  * Errors are logged but don't fail the build (cache is optional).
133
127
  */
134
- export const save_build_cache_metadata = (metadata: BuildCacheMetadata, log?: Logger): void => {
128
+ export const save_build_cache_metadata = async (
129
+ metadata: BuildCacheMetadata,
130
+ log?: Logger,
131
+ ): Promise<void> => {
135
132
  try {
136
133
  // Ensure .gro directory exists
137
- mkdirSync(paths.build, {recursive: true});
134
+ await mkdir(paths.build, {recursive: true});
138
135
 
139
136
  const metadata_path = join(paths.build, BUILD_CACHE_METADATA_FILENAME);
140
- writeFileSync(metadata_path, JSON.stringify(metadata, null, '\t'), 'utf-8');
137
+ await writeFile(metadata_path, JSON.stringify(metadata, null, '\t'), 'utf-8');
141
138
  } catch (error) {
142
139
  // Cache writes are optional - log warning but don't fail the build
143
140
  log?.warn(
@@ -154,33 +151,38 @@ export const save_build_cache_metadata = (metadata: BuildCacheMetadata, log?: Lo
154
151
  */
155
152
  export const validate_build_cache = async (metadata: BuildCacheMetadata): Promise<boolean> => {
156
153
  // Verify all tracked output files exist and have matching size
154
+ // Sequential checks with early return for performance
157
155
  for (const output of metadata.outputs) {
158
- if (!existsSync(output.path)) {
156
+ // eslint-disable-next-line no-await-in-loop
157
+ if (!(await fs_exists(output.path))) {
159
158
  return false;
160
159
  }
161
160
 
162
161
  // Fast negative check: size mismatch = definitely invalid
163
162
  // This avoids expensive file reads and hashing for files that have clearly changed
164
- const stats = statSync(output.path);
163
+ // eslint-disable-next-line no-await-in-loop
164
+ const stats = await stat(output.path);
165
165
  if (stats.size !== output.size) {
166
166
  return false;
167
167
  }
168
168
  }
169
169
 
170
170
  // Size matches for all files - now verify content with cryptographic hashing
171
- // Hash all files in parallel for performance
172
- const hash_promises = metadata.outputs.map(async (output) => {
173
- try {
174
- const contents = readFileSync(output.path);
175
- const actual_hash = await to_hash(contents);
176
- return actual_hash === output.hash;
177
- } catch {
178
- // File deleted/inaccessible between checks = cache invalid
179
- return false;
180
- }
181
- });
182
-
183
- const results = await Promise.all(hash_promises);
171
+ // Hash files with controlled concurrency (could be 10k+ files)
172
+ const results = await map_concurrent(
173
+ metadata.outputs,
174
+ async (output) => {
175
+ try {
176
+ const contents = await readFile(output.path);
177
+ const actual_hash = await to_hash(contents);
178
+ return actual_hash === output.hash;
179
+ } catch {
180
+ // File deleted/inaccessible between checks = cache invalid
181
+ return false;
182
+ }
183
+ },
184
+ 20,
185
+ );
184
186
  return results.every((valid) => valid);
185
187
  };
186
188
 
@@ -198,7 +200,7 @@ export const is_build_cache_valid = async (
198
200
  git_commit?: string | null,
199
201
  ): Promise<boolean> => {
200
202
  // Load existing metadata
201
- const metadata = load_build_cache_metadata();
203
+ const metadata = await load_build_cache_metadata();
202
204
  if (!metadata) {
203
205
  log.debug('No build cache metadata found');
204
206
  return false;
@@ -250,8 +252,12 @@ export const collect_build_outputs = async (
250
252
  const files_to_hash: Array<FileEntry> = [];
251
253
 
252
254
  // Recursively collect files
253
- const collect_files = (dir: string, relative_base: string, dir_prefix: string): void => {
254
- const entries = readdirSync(dir, {withFileTypes: true});
255
+ const collect_files = async (
256
+ dir: string,
257
+ relative_base: string,
258
+ dir_prefix: string,
259
+ ): Promise<void> => {
260
+ const entries = await readdir(dir, {withFileTypes: true});
255
261
 
256
262
  for (const entry of entries) {
257
263
  // Skip metadata file itself
@@ -264,7 +270,8 @@ export const collect_build_outputs = async (
264
270
  const cache_key = join(dir_prefix, relative_path);
265
271
 
266
272
  if (entry.isDirectory()) {
267
- collect_files(full_path, relative_path, dir_prefix);
273
+ // eslint-disable-next-line no-await-in-loop
274
+ await collect_files(full_path, relative_path, dir_prefix);
268
275
  } else if (entry.isFile()) {
269
276
  files_to_hash.push({full_path, cache_key});
270
277
  }
@@ -272,19 +279,22 @@ export const collect_build_outputs = async (
272
279
  }
273
280
  };
274
281
 
275
- // Collect files from all build directories
282
+ // Collect files from all build directories sequentially
276
283
  for (const build_dir of build_dirs) {
277
- if (!existsSync(build_dir)) {
284
+ // eslint-disable-next-line no-await-in-loop
285
+ if (!(await fs_exists(build_dir))) {
278
286
  continue; // Skip non-existent directories
279
287
  }
280
- collect_files(build_dir, '', build_dir);
288
+ // eslint-disable-next-line no-await-in-loop
289
+ await collect_files(build_dir, '', build_dir);
281
290
  }
282
291
 
283
- // Hash all files in parallel and collect stats
284
- const hash_promises = files_to_hash.map(
292
+ // Hash files with controlled concurrency and collect stats (could be 10k+ files)
293
+ return map_concurrent(
294
+ files_to_hash,
285
295
  async ({full_path, cache_key}): Promise<BuildOutputEntry> => {
286
- const stats = statSync(full_path);
287
- const contents = readFileSync(full_path);
296
+ const stats = await stat(full_path);
297
+ const contents = await readFile(full_path);
288
298
  const hash = await to_hash(contents);
289
299
 
290
300
  return {
@@ -296,40 +306,46 @@ export const collect_build_outputs = async (
296
306
  mode: stats.mode,
297
307
  };
298
308
  },
309
+ 20,
299
310
  );
300
-
301
- return await Promise.all(hash_promises);
302
311
  };
303
312
 
304
313
  /**
305
314
  * Discovers all build output directories in the current working directory.
306
315
  * Returns an array of directory names that exist: build/, dist/, dist_*
307
316
  */
308
- export const discover_build_output_dirs = (): Array<string> => {
317
+ export const discover_build_output_dirs = async (): Promise<Array<string>> => {
309
318
  const build_dirs: Array<string> = [];
310
319
 
311
- // Check for SvelteKit app output (build/)
312
- if (existsSync(SVELTEKIT_BUILD_DIRNAME)) {
320
+ // Check for SvelteKit app output (build/) and library output (dist/) in parallel
321
+ const [build_exists, dist_exists] = await Promise.all([
322
+ fs_exists(SVELTEKIT_BUILD_DIRNAME),
323
+ fs_exists(SVELTEKIT_DIST_DIRNAME),
324
+ ]);
325
+
326
+ if (build_exists) {
313
327
  build_dirs.push(SVELTEKIT_BUILD_DIRNAME);
314
328
  }
315
-
316
- // Check for SvelteKit library output (dist/)
317
- if (existsSync(SVELTEKIT_DIST_DIRNAME)) {
329
+ if (dist_exists) {
318
330
  build_dirs.push(SVELTEKIT_DIST_DIRNAME);
319
331
  }
320
332
 
321
333
  // Check for server and other plugin outputs (dist_*)
322
- const root_entries = readdirSync('.');
323
- const dist_dirs = root_entries.filter((p) => {
324
- if (!p.startsWith(GRO_DIST_PREFIX)) return false;
325
- try {
326
- return statSync(p).isDirectory();
327
- } catch {
328
- // File was deleted/moved during iteration - skip it
329
- return false;
330
- }
331
- });
332
- build_dirs.push(...dist_dirs);
334
+ const root_entries = await readdir('.');
335
+ const dist_dir_checks = await Promise.all(
336
+ root_entries
337
+ .filter((p) => p.startsWith(GRO_DIST_PREFIX))
338
+ .map(async (p) => {
339
+ try {
340
+ const s = await stat(p);
341
+ return s.isDirectory() ? p : null;
342
+ } catch {
343
+ // File was deleted/moved during iteration - skip it
344
+ return null;
345
+ }
346
+ }),
347
+ );
348
+ build_dirs.push(...dist_dir_checks.filter((p): p is string => p !== null));
333
349
 
334
350
  return build_dirs;
335
351
  };
@@ -350,7 +366,7 @@ export const create_build_cache_metadata = async (
350
366
  build_dirs?: Array<string>,
351
367
  ): Promise<BuildCacheMetadata> => {
352
368
  const cache_key = await compute_build_cache_key(config, log, git_commit);
353
- const dirs = build_dirs ?? discover_build_output_dirs();
369
+ const dirs = build_dirs ?? (await discover_build_output_dirs());
354
370
  const outputs = await collect_build_outputs(dirs);
355
371
 
356
372
  return {
@@ -1,7 +1,7 @@
1
1
  import {readFile, writeFile} from 'node:fs/promises';
2
2
  import {z} from 'zod';
3
- import type {Logger} from '@ryanatkn/belt/log.js';
4
- import type {FetchValueCache} from '@ryanatkn/belt/fetch.js';
3
+ import type {Logger} from '@fuzdev/fuz_util/log.js';
4
+ import type {FetchValueCache} from '@fuzdev/fuz_util/fetch.js';
5
5
 
6
6
  import {github_fetch_commit_prs} from './github.ts';
7
7
 
@@ -1,15 +1,15 @@
1
1
  import {z} from 'zod';
2
- import {spawn} from '@ryanatkn/belt/process.js';
2
+ import {spawn} from '@fuzdev/fuz_util/process.js';
3
3
  import {styleText as st} from 'node:util';
4
4
  import type {WrittenConfig} from '@changesets/types';
5
- import {readFile, writeFile} from 'node:fs/promises';
5
+ import {readdir, readFile, writeFile} from 'node:fs/promises';
6
6
  import {join} from 'node:path';
7
- import {existsSync, readdirSync} from 'node:fs';
7
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
8
8
  import {
9
9
  GitOrigin,
10
10
  git_check_fully_staged_workspace,
11
11
  git_push_to_create,
12
- } from '@ryanatkn/belt/git.js';
12
+ } from '@fuzdev/fuz_util/git.js';
13
13
 
14
14
  import {TaskError, type Task} from './task.ts';
15
15
  import {find_cli, spawn_cli} from './cli.ts';
@@ -92,14 +92,14 @@ export const task: Task<Args> = {
92
92
 
93
93
  const bump: ChangesetBump = minor ? 'minor' : major ? 'major' : 'patch';
94
94
 
95
- const found_changeset_cli = find_cli(changeset_cli);
95
+ const found_changeset_cli = await find_cli(changeset_cli);
96
96
  if (!found_changeset_cli) {
97
97
  throw new TaskError(
98
98
  'changeset command not found: install @changesets/cli locally or globally',
99
99
  );
100
100
  }
101
101
 
102
- const package_json = load_package_json();
102
+ const package_json = await load_package_json();
103
103
 
104
104
  const has_sveltekit_library_result = await has_sveltekit_library(package_json, svelte_config);
105
105
  if (!has_sveltekit_library_result.ok) {
@@ -110,7 +110,7 @@ export const task: Task<Args> = {
110
110
 
111
111
  const path = join(dir, 'config.json');
112
112
 
113
- const inited = existsSync(path);
113
+ const inited = await fs_exists(path);
114
114
 
115
115
  if (!inited) {
116
116
  await spawn_cli(found_changeset_cli, ['init'], log);
@@ -143,7 +143,7 @@ export const task: Task<Args> = {
143
143
 
144
144
  if (message) {
145
145
  // TODO see the helper below, simplify this to CLI flags when support is added to Changesets
146
- const changeset_adder = create_changeset_adder(package_json.name, dir, message, bump);
146
+ const changeset_adder = await create_changeset_adder(package_json.name, dir, message, bump);
147
147
  await spawn_cli(found_changeset_cli, ['add', '--empty'], log);
148
148
  await changeset_adder();
149
149
  if (!(await git_check_fully_staged_workspace())) {
@@ -161,15 +161,15 @@ export const task: Task<Args> = {
161
161
  * TODO ideally this wouldn't exist and we'd use CLI flags, but they doesn't exist yet
162
162
  * @see https://github.com/changesets/changesets/pull/1121
163
163
  */
164
- const create_changeset_adder = (
164
+ const create_changeset_adder = async (
165
165
  repo_name: string,
166
166
  dir: string,
167
167
  message: string,
168
168
  bump: ChangesetBump,
169
- ) => {
170
- const filenames_before = readdirSync(dir);
169
+ ): Promise<() => Promise<void>> => {
170
+ const filenames_before = await readdir(dir);
171
171
  return async () => {
172
- const filenames_after = readdirSync(dir);
172
+ const filenames_after = await readdir(dir);
173
173
  const filenames_added = filenames_after.filter((p) => !filenames_before.includes(p));
174
174
  if (!filenames_added.length) {
175
175
  throw Error('expected to find a new changeset file');
@@ -1,7 +1,7 @@
1
1
  import {z} from 'zod';
2
- import {spawn} from '@ryanatkn/belt/process.js';
2
+ import {spawn} from '@fuzdev/fuz_util/process.js';
3
3
  import {styleText as st} from 'node:util';
4
- import {git_check_clean_workspace} from '@ryanatkn/belt/git.js';
4
+ import {git_check_clean_workspace} from '@fuzdev/fuz_util/git.js';
5
5
 
6
6
  import {TaskError, type Task} from './task.ts';
7
7
  import {sync_package_json} from './package_json.ts';
@@ -1,5 +1,5 @@
1
1
  import type {ChildProcess} from 'node:child_process';
2
- import {strip_end} from '@ryanatkn/belt/string.js';
2
+ import {strip_end} from '@fuzdev/fuz_util/string.js';
3
3
 
4
4
  /**
5
5
  * Maps child process output through a transform function.
@@ -1,6 +1,6 @@
1
- import {spawn} from '@ryanatkn/belt/process.js';
1
+ import {spawn} from '@fuzdev/fuz_util/process.js';
2
2
  import {z} from 'zod';
3
- import {GitOrigin} from '@ryanatkn/belt/git.js';
3
+ import {GitOrigin} from '@fuzdev/fuz_util/git.js';
4
4
 
5
5
  import type {Task} from './task.ts';
6
6
  import {clean_fs} from './clean_fs.ts';
@@ -1,5 +1,5 @@
1
- import {rm} from 'node:fs/promises';
2
- import {readdirSync, type RmOptions} from 'node:fs';
1
+ import {readdir, rm} from 'node:fs/promises';
2
+ import type {RmOptions} from 'node:fs';
3
3
 
4
4
  import {paths} from './paths.ts';
5
5
  import {
@@ -35,8 +35,8 @@ export const clean_fs = async (
35
35
  promises.push(rm(paths.build_dev, rm_options));
36
36
  }
37
37
  if (build || build_dist) {
38
- const paths = readdirSync('.').filter((p) => p.startsWith(GRO_DIST_PREFIX));
39
- for (const path of paths) {
38
+ const dir_paths = (await readdir('.')).filter((p) => p.startsWith(GRO_DIST_PREFIX));
39
+ for (const path of dir_paths) {
40
40
  promises.push(rm(path, rm_options));
41
41
  }
42
42
  }
package/src/lib/cli.ts CHANGED
@@ -1,15 +1,16 @@
1
- import {spawnSync, type SpawnOptions} from 'node:child_process';
1
+ import type {SpawnOptions} from 'node:child_process';
2
2
  import {
3
3
  spawn,
4
+ spawn_out,
4
5
  spawn_process,
5
6
  type SpawnResult,
6
7
  type SpawnedProcess,
7
- } from '@ryanatkn/belt/process.js';
8
+ } from '@fuzdev/fuz_util/process.js';
8
9
  import {join} from 'node:path';
9
- import {existsSync} from 'node:fs';
10
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
10
11
  import {fileURLToPath, type URL} from 'node:url';
11
- import type {Logger} from '@ryanatkn/belt/log.js';
12
- import type {PathId} from '@ryanatkn/belt/path.js';
12
+ import type {Logger} from '@fuzdev/fuz_util/log.js';
13
+ import type {PathId} from '@fuzdev/fuz_util/path.js';
13
14
 
14
15
  import {NODE_MODULES_DIRNAME} from './constants.ts';
15
16
  import {print_command_args} from './args.ts';
@@ -24,18 +25,18 @@ export type Cli =
24
25
  * Searches the filesystem for the CLI `name`, first local to the cwd and then globally.
25
26
  * @returns `null` if not found locally or globally
26
27
  */
27
- export const find_cli = (
28
+ export const find_cli = async (
28
29
  name: string,
29
30
  cwd: string | URL = process.cwd(),
30
31
  options?: SpawnOptions,
31
- ): Cli | null => {
32
+ ): Promise<Cli | null> => {
32
33
  const final_cwd = typeof cwd === 'string' ? cwd : fileURLToPath(cwd);
33
34
  const local_id = join(final_cwd, NODE_MODULES_DIRNAME, `.bin/${name}`);
34
- if (existsSync(local_id)) {
35
+ if (await fs_exists(local_id)) {
35
36
  return {name, id: local_id, kind: 'local'};
36
37
  }
37
- const {stdout} = spawnSync('which', [name], options);
38
- const global_id = stdout.toString().trim();
38
+ const {stdout} = await spawn_out('which', [name], options);
39
+ const global_id = stdout?.trim();
39
40
  if (!global_id) return null;
40
41
  return {name, id: global_id, kind: 'global'};
41
42
  };
@@ -51,7 +52,7 @@ export const spawn_cli = async (
51
52
  log?: Logger,
52
53
  options?: SpawnOptions,
53
54
  ): Promise<SpawnResult | undefined> => {
54
- const cli = resolve_cli(name_or_cli, args, options?.cwd, log, options);
55
+ const cli = await resolve_cli(name_or_cli, args, options?.cwd, log, options);
55
56
  if (!cli) return;
56
57
  return spawn(cli.id, args, options);
57
58
  };
@@ -61,27 +62,27 @@ export const spawn_cli = async (
61
62
  * If a string is provided for `name_or_cli`, it checks first local to the cwd and then globally.
62
63
  * @returns `undefined` if no CLI is found, or the spawn result
63
64
  */
64
- export const spawn_cli_process = (
65
+ export const spawn_cli_process = async (
65
66
  name_or_cli: string | Cli,
66
67
  args: Array<string> = [],
67
68
  log?: Logger,
68
69
  options?: SpawnOptions,
69
- ): SpawnedProcess | undefined => {
70
- const cli = resolve_cli(name_or_cli, args, options?.cwd, log, options);
70
+ ): Promise<SpawnedProcess | undefined> => {
71
+ const cli = await resolve_cli(name_or_cli, args, options?.cwd, log, options);
71
72
  if (!cli) return;
72
73
  return spawn_process(cli.id, args, options);
73
74
  };
74
75
 
75
- export const resolve_cli = (
76
+ export const resolve_cli = async (
76
77
  name_or_cli: string | Cli,
77
78
  args: Array<string> = [],
78
79
  cwd: string | URL | undefined,
79
80
  log?: Logger,
80
81
  options?: SpawnOptions,
81
- ): Cli | undefined => {
82
+ ): Promise<Cli | undefined> => {
82
83
  let final_cli;
83
84
  if (typeof name_or_cli === 'string') {
84
- const found = find_cli(name_or_cli, cwd, options);
85
+ const found = await find_cli(name_or_cli, cwd, options);
85
86
  if (!found) return;
86
87
  final_cli = found;
87
88
  } else {
@@ -1,6 +1,6 @@
1
- import {spawn} from '@ryanatkn/belt/process.js';
1
+ import {spawn} from '@fuzdev/fuz_util/process.js';
2
2
  import {z} from 'zod';
3
- import {GitOrigin, git_current_branch_name, git_push} from '@ryanatkn/belt/git.js';
3
+ import {GitOrigin, git_current_branch_name, git_push} from '@fuzdev/fuz_util/git.js';
4
4
 
5
5
  import type {Task} from './task.ts';
6
6