@ryanatkn/gro 0.148.0 → 0.149.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 (111) hide show
  1. package/README.md +2 -2
  2. package/dist/args.d.ts.map +1 -1
  3. package/dist/build.task.d.ts.map +1 -1
  4. package/dist/changelog.d.ts.map +1 -1
  5. package/dist/changeset.task.d.ts.map +1 -1
  6. package/dist/changeset_helpers.d.ts.map +1 -1
  7. package/dist/check.task.d.ts.map +1 -1
  8. package/dist/child_process_logging.d.ts +10 -0
  9. package/dist/child_process_logging.d.ts.map +1 -0
  10. package/dist/child_process_logging.js +26 -0
  11. package/dist/clean.task.d.ts.map +1 -1
  12. package/dist/clean_fs.d.ts.map +1 -1
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/commit.task.d.ts.map +1 -1
  15. package/dist/constants.d.ts +2 -0
  16. package/dist/constants.d.ts.map +1 -1
  17. package/dist/constants.js +2 -0
  18. package/dist/deploy.task.d.ts +2 -2
  19. package/dist/deploy.task.d.ts.map +1 -1
  20. package/dist/dev.task.d.ts.map +1 -1
  21. package/dist/env.d.ts.map +1 -1
  22. package/dist/esbuild_helpers.d.ts.map +1 -1
  23. package/dist/esbuild_helpers.js +1 -1
  24. package/dist/esbuild_plugin_external_worker.d.ts.map +1 -1
  25. package/dist/esbuild_plugin_svelte.d.ts.map +1 -1
  26. package/dist/esbuild_plugin_sveltekit_local_imports.d.ts.map +1 -1
  27. package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts.map +1 -1
  28. package/dist/esbuild_plugin_sveltekit_shim_app.d.ts.map +1 -1
  29. package/dist/esbuild_plugin_sveltekit_shim_env.d.ts.map +1 -1
  30. package/dist/filer.d.ts.map +1 -1
  31. package/dist/format.task.d.ts.map +1 -1
  32. package/dist/format_directory.d.ts.map +1 -1
  33. package/dist/format_file.d.ts.map +1 -1
  34. package/dist/fs.d.ts.map +1 -1
  35. package/dist/gen.d.ts.map +1 -1
  36. package/dist/gen.task.d.ts.map +1 -1
  37. package/dist/git.d.ts.map +1 -1
  38. package/dist/github.d.ts.map +1 -1
  39. package/dist/gro.config.default.d.ts.map +1 -1
  40. package/dist/gro.d.ts.map +1 -1
  41. package/dist/gro.js +1 -1
  42. package/dist/gro_config.d.ts.map +1 -1
  43. package/dist/gro_helpers.d.ts.map +1 -1
  44. package/dist/gro_plugin_gen.d.ts.map +1 -1
  45. package/dist/gro_plugin_moss.d.ts.map +1 -1
  46. package/dist/gro_plugin_moss.js +1 -1
  47. package/dist/gro_plugin_server.d.ts.map +1 -1
  48. package/dist/gro_plugin_sveltekit_app.d.ts.map +1 -1
  49. package/dist/gro_plugin_sveltekit_library.d.ts.map +1 -1
  50. package/dist/hash.d.ts.map +1 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/input_path.d.ts.map +1 -1
  53. package/dist/invoke.d.ts.map +1 -1
  54. package/dist/invoke_task.d.ts.map +1 -1
  55. package/dist/lint.task.d.ts.map +1 -1
  56. package/dist/loader.d.ts.map +1 -1
  57. package/dist/module.d.ts.map +1 -1
  58. package/dist/modules.d.ts.map +1 -1
  59. package/dist/package.d.ts +11 -0
  60. package/dist/package.d.ts.map +1 -1
  61. package/dist/package.gen.d.ts.map +1 -1
  62. package/dist/package.js +42 -30
  63. package/dist/package_json.d.ts.map +1 -1
  64. package/dist/package_meta.d.ts.map +1 -1
  65. package/dist/parse_imports.d.ts.map +1 -1
  66. package/dist/parse_imports.js +122 -12
  67. package/dist/path.d.ts.map +1 -1
  68. package/dist/paths.d.ts.map +1 -1
  69. package/dist/plugin.d.ts.map +1 -1
  70. package/dist/publish.task.d.ts.map +1 -1
  71. package/dist/register.d.ts.map +1 -1
  72. package/dist/reinstall.task.d.ts.map +1 -1
  73. package/dist/release.task.d.ts.map +1 -1
  74. package/dist/resolve.task.d.ts.map +1 -1
  75. package/dist/resolve_specifier.d.ts.map +1 -1
  76. package/dist/run.task.d.ts.map +1 -1
  77. package/dist/run_gen.d.ts.map +1 -1
  78. package/dist/run_task.d.ts.map +1 -1
  79. package/dist/search_fs.d.ts.map +1 -1
  80. package/dist/src_json.d.ts.map +1 -1
  81. package/dist/svelte_helpers.d.ts.map +1 -1
  82. package/dist/sveltekit_config.d.ts.map +1 -1
  83. package/dist/sveltekit_helpers.d.ts.map +1 -1
  84. package/dist/sveltekit_shim_app.d.ts.map +1 -1
  85. package/dist/sveltekit_shim_app_environment.d.ts.map +1 -1
  86. package/dist/sveltekit_shim_app_forms.d.ts.map +1 -1
  87. package/dist/sveltekit_shim_app_navigation.d.ts.map +1 -1
  88. package/dist/sveltekit_shim_app_paths.d.ts.map +1 -1
  89. package/dist/sveltekit_shim_app_stores.d.ts.map +1 -1
  90. package/dist/sveltekit_shim_env.d.ts.map +1 -1
  91. package/dist/sync.task.d.ts.map +1 -1
  92. package/dist/task.d.ts.map +1 -1
  93. package/dist/task_logging.d.ts.map +1 -1
  94. package/dist/task_logging.js +2 -2
  95. package/dist/test.task.d.ts.map +1 -1
  96. package/dist/typecheck.task.d.ts +6 -0
  97. package/dist/typecheck.task.d.ts.map +1 -1
  98. package/dist/typecheck.task.js +20 -5
  99. package/dist/upgrade.task.d.ts.map +1 -1
  100. package/dist/watch_dir.d.ts.map +1 -1
  101. package/package.json +33 -29
  102. package/src/lib/child_process_logging.ts +38 -0
  103. package/src/lib/constants.ts +2 -0
  104. package/src/lib/esbuild_helpers.ts +1 -1
  105. package/src/lib/gro.ts +1 -1
  106. package/src/lib/gro_plugin_moss.ts +1 -1
  107. package/src/lib/package.ts +42 -30
  108. package/src/lib/parse_imports.ts +149 -12
  109. package/src/lib/sveltekit_shim_app_stores.ts +3 -0
  110. package/src/lib/task_logging.ts +2 -2
  111. package/src/lib/typecheck.task.ts +24 -5
@@ -2,8 +2,10 @@ import { print_spawn_result } from '@ryanatkn/belt/process.js';
2
2
  import { z } from 'zod';
3
3
  import { Task_Error } from './task.js';
4
4
  import { serialize_args, to_forwarded_args } from './args.js';
5
- import { find_cli, spawn_cli } from './cli.js';
5
+ import { find_cli, spawn_cli, spawn_cli_process } from './cli.js';
6
6
  import { SVELTE_CHECK_CLI, sveltekit_sync_if_available } from './sveltekit_helpers.js';
7
+ import { configure_colored_output_with_path_replacement } from './child_process_logging.js';
8
+ import { paths } from './paths.js';
7
9
  export const Args = z
8
10
  .object({
9
11
  svelte_check_cli: z
@@ -12,21 +14,34 @@ export const Args = z
12
14
  typescript_cli: z
13
15
  .string({ description: 'the TypeScript CLI to use as a fallback to svelte-check' })
14
16
  .default('tsc'),
17
+ path_replacement: z
18
+ .string({ description: 'replacement string for current working directory in output' })
19
+ .default('.'),
20
+ cwd: z.string({ description: 'current working directory' }).default(paths.root),
15
21
  })
16
22
  .strict();
17
23
  export const task = {
18
24
  summary: 'run tsc on the project without emitting any files',
19
25
  Args,
20
26
  run: async ({ args, log }) => {
21
- const { svelte_check_cli, typescript_cli } = args;
27
+ const { svelte_check_cli, typescript_cli, path_replacement, cwd } = args;
22
28
  await sveltekit_sync_if_available();
23
29
  // Prefer svelte-check if available.
24
30
  const found_svelte_check_cli = find_cli(svelte_check_cli);
25
31
  if (found_svelte_check_cli) {
26
32
  const serialized = serialize_args(to_forwarded_args(svelte_check_cli));
27
- const svelte_check_result = await spawn_cli(found_svelte_check_cli, serialized, log);
28
- if (!svelte_check_result?.ok) {
29
- throw new Task_Error(`Failed to typecheck. ${print_spawn_result(svelte_check_result)}`);
33
+ const spawned = spawn_cli_process(found_svelte_check_cli, serialized, undefined, {
34
+ stdio: ['inherit', 'pipe', 'pipe'],
35
+ env: { ...process.env, FORCE_COLOR: '1' }, // Needed for colors (maybe make an option)
36
+ });
37
+ const svelte_check_process = spawned?.child;
38
+ if (svelte_check_process) {
39
+ // Configure process output with path replacement while preserving colors
40
+ configure_colored_output_with_path_replacement(svelte_check_process, path_replacement, cwd);
41
+ const svelte_check_result = await spawned.closed;
42
+ if (!svelte_check_result.ok) {
43
+ throw new Task_Error(`Failed to typecheck. ${print_spawn_result(svelte_check_result)}`);
44
+ }
30
45
  }
31
46
  return;
32
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.task.d.ts","sourceRoot":"../src/lib/","sources":["upgrade.task.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAa,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAMhD,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;EAeP,CAAC;AACX,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CA+C3B,CAAC"}
1
+ {"version":3,"file":"upgrade.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/upgrade.task.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAa,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAMhD,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;EAeP,CAAC;AACX,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CA+C3B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"watch_dir.d.ts","sourceRoot":"../src/lib/","sources":["watch_dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,eAAe,EAAiB,MAAM,UAAU,CAAC;AAKrE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAI3C,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACtB;AACD,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC9D,MAAM,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,oDAMnB,iBAAiB,KAAG,aA6CtB,CAAC"}
1
+ {"version":3,"file":"watch_dir.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/watch_dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,eAAe,EAAiB,MAAM,UAAU,CAAC;AAKrE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAI3C,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;CACtB;AACD,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC9D,MAAM,MAAM,uBAAuB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,iDAMvB,iBAAiB,KAAG,aA6CtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryanatkn/gro",
3
- "version": "0.148.0",
3
+ "version": "0.149.0",
4
4
  "description": "task runner and toolkit extending SvelteKit",
5
5
  "motto": "generate, run, optimize",
6
6
  "glyph": "🌰",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "type": "module",
34
34
  "engines": {
35
- "node": ">=20.17"
35
+ "node": ">=22.11"
36
36
  },
37
37
  "bin": {
38
38
  "gro": "dist/gro.js"
@@ -49,40 +49,40 @@
49
49
  "typescript"
50
50
  ],
51
51
  "dependencies": {
52
- "@ryanatkn/belt": "^0.29.0",
53
- "chokidar": "^4.0.1",
54
- "dotenv": "^16.4.5",
55
- "esm-env": "^1.1.4",
52
+ "@ryanatkn/belt": "^0.30.0",
53
+ "chokidar": "^4.0.3",
54
+ "dotenv": "^16.4.7",
55
+ "esm-env": "^1.2.2",
56
56
  "mri": "^1.2.0",
57
- "oxc-parser": "^0.36.0",
58
- "prettier": "^3.3.3",
59
- "prettier-plugin-svelte": "^3.2.8",
60
- "ts-morph": "^24.0.0",
57
+ "oxc-parser": "^0.62.0",
58
+ "prettier": "^3.5.3",
59
+ "prettier-plugin-svelte": "^3.3.3",
60
+ "ts-morph": "^25.0.1",
61
61
  "tslib": "^2.8.1",
62
- "zod": "^3.23.8"
62
+ "zod": "^3.24.2"
63
63
  },
64
64
  "peerDependencies": {
65
- "esbuild": "^0.21.0",
65
+ "esbuild": "^0.25",
66
66
  "svelte": "^5"
67
67
  },
68
68
  "devDependencies": {
69
- "@changesets/changelog-git": "^0.2.0",
70
- "@changesets/types": "^6.0.0",
71
- "@ryanatkn/eslint-config": "^0.6.0",
72
- "@ryanatkn/fuz": "^0.131.1",
73
- "@ryanatkn/moss": "^0.20.2",
74
- "@sveltejs/adapter-static": "^3.0.6",
75
- "@sveltejs/kit": "^2.9.0",
76
- "@sveltejs/package": "^2.3.7",
77
- "@sveltejs/vite-plugin-svelte": "^4.0.1",
78
- "@types/node": "^22.9.1",
79
- "esbuild": "^0.21.5",
80
- "eslint": "^9.16.0",
81
- "eslint-plugin-svelte": "^2.46.1",
82
- "svelte": "^5.8.1",
83
- "svelte-check": "^4.1.1",
84
- "typescript": "^5.7.2",
85
- "typescript-eslint": "^8.17.0",
69
+ "@changesets/changelog-git": "^0.2.1",
70
+ "@changesets/types": "^6.1.0",
71
+ "@ryanatkn/eslint-config": "^0.8.0",
72
+ "@ryanatkn/fuz": "^0.135.0",
73
+ "@ryanatkn/moss": "^0.24.2",
74
+ "@sveltejs/adapter-static": "^3.0.8",
75
+ "@sveltejs/kit": "^2.20.4",
76
+ "@sveltejs/package": "^2.3.10",
77
+ "@sveltejs/vite-plugin-svelte": "^5.0.3",
78
+ "@types/node": "^22.14.0",
79
+ "esbuild": "^0.25.2",
80
+ "eslint": "^9.24.0",
81
+ "eslint-plugin-svelte": "^3.5.1",
82
+ "svelte": "^5.25.6",
83
+ "svelte-check": "^4.1.5",
84
+ "typescript": "^5.8.2",
85
+ "typescript-eslint": "^8.29.0",
86
86
  "uvu": "^0.5.6"
87
87
  },
88
88
  "prettier": {
@@ -141,6 +141,10 @@
141
141
  "types": "./dist/check.task.d.ts",
142
142
  "default": "./dist/check.task.js"
143
143
  },
144
+ "./child_process_logging.js": {
145
+ "types": "./dist/child_process_logging.d.ts",
146
+ "default": "./dist/child_process_logging.js"
147
+ },
144
148
  "./clean_fs.js": {
145
149
  "types": "./dist/clean_fs.d.ts",
146
150
  "default": "./dist/clean_fs.js"
@@ -0,0 +1,38 @@
1
+ import type {ChildProcess} from 'node:child_process';
2
+ import {strip_end} from '@ryanatkn/belt/string.js';
3
+
4
+ /**
5
+ * Maps child process output through a transform function.
6
+ */
7
+ export const map_child_process_output = (
8
+ child_process: ChildProcess,
9
+ transform: (data: string) => string,
10
+ ): void => {
11
+ if (child_process.stdout) {
12
+ child_process.stdout.on('data', (data) => {
13
+ process.stdout.write(transform(data.toString()));
14
+ });
15
+ }
16
+
17
+ if (child_process.stderr) {
18
+ child_process.stderr.on('data', (data) => {
19
+ process.stderr.write(transform(data.toString()));
20
+ });
21
+ }
22
+ };
23
+
24
+ /**
25
+ * Configures process output handling with path replacements while preserving ANSI colors.
26
+ */
27
+ export const configure_colored_output_with_path_replacement = (
28
+ child_process: ChildProcess,
29
+ replacement: string = '.',
30
+ cwd: string = process.cwd(),
31
+ ): void => {
32
+ // Escape special characters in the cwd for regex safety
33
+ const cwd_escaped = strip_end(cwd, '/').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
34
+ const cwd_reg_exp = new RegExp(cwd_escaped, 'g');
35
+
36
+ // Use the generic mapper with a path replacement transform
37
+ map_child_process_output(child_process, (data) => data.replace(cwd_reg_exp, replacement));
38
+ };
@@ -32,6 +32,8 @@ export const TSCONFIG_FILENAME = 'tsconfig.json';
32
32
  export const TS_MATCHER = /\.(ts|tsx|mts|cts)$/;
33
33
  export const JS_MATCHER = /\.(js|jsx|mjs|cjs)$/;
34
34
  export const JSON_MATCHER = /\.json$/;
35
+ /** Extracts the script content from Svelte files. */
36
+ export const SVELTE_SCRIPT_MATCHER = /<script(?:\s+[^>]*)?>([\s\S]*?)<\/script>/gim; // TODO maybe this shouldnt be global? or make a getter?
35
37
  export const EVERYTHING_MATCHER = /.*/;
36
38
 
37
39
  export const JS_CLI_DEFAULT = 'node';
@@ -38,7 +38,7 @@ export const to_define_import_meta_env = (
38
38
  [import_meta_env + 'SSR']: JSON.stringify(ssr),
39
39
  [import_meta_env + 'MODE']: JSON.stringify(mode),
40
40
  // it appears SvelteKit's `''` translates to Vite's `'/'`, so this intentionally falls back for falsy values, not just undefined
41
- [import_meta_env + 'BASE_URL']: JSON.stringify(base_url || '/'), // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing
41
+ [import_meta_env + 'BASE_URL']: JSON.stringify(base_url || '/'),
42
42
  });
43
43
 
44
44
  export const default_ts_transform_options: esbuild.TransformOptions = {
package/src/lib/gro.ts CHANGED
@@ -21,5 +21,5 @@ const loader_path = join(invoke_path, '../loader.js');
21
21
 
22
22
  const spawned = await spawn_with_loader(loader_path, invoke_path, process.argv.slice(2));
23
23
  if (!spawned.ok) {
24
- process.exitCode = spawned.code || 1; // eslint-disable-line @typescript-eslint/prefer-nullish-coalescing
24
+ process.exitCode = spawned.code || 1;
25
25
  }
@@ -53,7 +53,7 @@ export const gro_plugin_moss = ({
53
53
  };
54
54
  const flush_gen_queue = throttle(
55
55
  async () => {
56
- const css = generate_classes_css(css_classes.get_sorted_array(), css_classes_by_name);
56
+ const css = generate_classes_css(css_classes.get(), css_classes_by_name);
57
57
  const contents = `/* ${banner} */\n\n${css}\n\n/* ${banner} */`;
58
58
  const output = await format_file(contents, {filepath: outfile});
59
59
  // TODO think about using gen to implement this, would have some nice benefits like automatic change detection
@@ -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.148.0',
8
+ version: '0.149.0',
9
9
  description: 'task runner and toolkit extending SvelteKit',
10
10
  motto: 'generate, run, optimize',
11
11
  glyph: '🌰',
@@ -30,7 +30,7 @@ export const package_json = {
30
30
  deploy: 'gro deploy',
31
31
  },
32
32
  type: 'module',
33
- engines: {node: '>=20.17'},
33
+ engines: {node: '>=22.11'},
34
34
  bin: {gro: 'dist/gro.js'},
35
35
  keywords: [
36
36
  'web',
@@ -44,37 +44,37 @@ export const package_json = {
44
44
  'typescript',
45
45
  ],
46
46
  dependencies: {
47
- '@ryanatkn/belt': '^0.29.0',
48
- chokidar: '^4.0.1',
49
- dotenv: '^16.4.5',
50
- 'esm-env': '^1.1.4',
47
+ '@ryanatkn/belt': '^0.30.0',
48
+ chokidar: '^4.0.3',
49
+ dotenv: '^16.4.7',
50
+ 'esm-env': '^1.2.2',
51
51
  mri: '^1.2.0',
52
- 'oxc-parser': '^0.36.0',
53
- prettier: '^3.3.3',
54
- 'prettier-plugin-svelte': '^3.2.8',
55
- 'ts-morph': '^24.0.0',
52
+ 'oxc-parser': '^0.62.0',
53
+ prettier: '^3.5.3',
54
+ 'prettier-plugin-svelte': '^3.3.3',
55
+ 'ts-morph': '^25.0.1',
56
56
  tslib: '^2.8.1',
57
- zod: '^3.23.8',
57
+ zod: '^3.24.2',
58
58
  },
59
- peerDependencies: {esbuild: '^0.21.0', svelte: '^5'},
59
+ peerDependencies: {esbuild: '^0.25', svelte: '^5'},
60
60
  devDependencies: {
61
- '@changesets/changelog-git': '^0.2.0',
62
- '@changesets/types': '^6.0.0',
63
- '@ryanatkn/eslint-config': '^0.6.0',
64
- '@ryanatkn/fuz': '^0.131.1',
65
- '@ryanatkn/moss': '^0.20.2',
66
- '@sveltejs/adapter-static': '^3.0.6',
67
- '@sveltejs/kit': '^2.9.0',
68
- '@sveltejs/package': '^2.3.7',
69
- '@sveltejs/vite-plugin-svelte': '^4.0.1',
70
- '@types/node': '^22.9.1',
71
- esbuild: '^0.21.5',
72
- eslint: '^9.16.0',
73
- 'eslint-plugin-svelte': '^2.46.1',
74
- svelte: '^5.8.1',
75
- 'svelte-check': '^4.1.1',
76
- typescript: '^5.7.2',
77
- 'typescript-eslint': '^8.17.0',
61
+ '@changesets/changelog-git': '^0.2.1',
62
+ '@changesets/types': '^6.1.0',
63
+ '@ryanatkn/eslint-config': '^0.8.0',
64
+ '@ryanatkn/fuz': '^0.135.0',
65
+ '@ryanatkn/moss': '^0.24.2',
66
+ '@sveltejs/adapter-static': '^3.0.8',
67
+ '@sveltejs/kit': '^2.20.4',
68
+ '@sveltejs/package': '^2.3.10',
69
+ '@sveltejs/vite-plugin-svelte': '^5.0.3',
70
+ '@types/node': '^22.14.0',
71
+ esbuild: '^0.25.2',
72
+ eslint: '^9.24.0',
73
+ 'eslint-plugin-svelte': '^3.5.1',
74
+ svelte: '^5.25.6',
75
+ 'svelte-check': '^4.1.5',
76
+ typescript: '^5.8.2',
77
+ 'typescript-eslint': '^8.29.0',
78
78
  uvu: '^0.5.6',
79
79
  },
80
80
  prettier: {
@@ -102,6 +102,10 @@ export const package_json = {
102
102
  default: './dist/changeset.task.js',
103
103
  },
104
104
  './check.task.js': {types: './dist/check.task.d.ts', default: './dist/check.task.js'},
105
+ './child_process_logging.js': {
106
+ types: './dist/child_process_logging.d.ts',
107
+ default: './dist/child_process_logging.js',
108
+ },
105
109
  './clean_fs.js': {types: './dist/clean_fs.d.ts', default: './dist/clean_fs.js'},
106
110
  './clean.task.js': {types: './dist/clean.task.d.ts', default: './dist/clean.task.js'},
107
111
  './cli.js': {types: './dist/cli.d.ts', default: './dist/cli.js'},
@@ -265,7 +269,7 @@ export const package_json = {
265
269
 
266
270
  export const src_json = {
267
271
  name: '@ryanatkn/gro',
268
- version: '0.148.0',
272
+ version: '0.149.0',
269
273
  modules: {
270
274
  '.': {
271
275
  path: 'index.ts',
@@ -334,6 +338,13 @@ export const src_json = {
334
338
  {name: 'task', kind: 'variable'},
335
339
  ],
336
340
  },
341
+ './child_process_logging.js': {
342
+ path: 'child_process_logging.ts',
343
+ declarations: [
344
+ {name: 'map_child_process_output', kind: 'function'},
345
+ {name: 'configure_colored_output_with_path_replacement', kind: 'function'},
346
+ ],
347
+ },
337
348
  './clean_fs.js': {path: 'clean_fs.ts', declarations: [{name: 'clean_fs', kind: 'function'}]},
338
349
  './clean.task.js': {
339
350
  path: 'clean.task.ts',
@@ -387,6 +398,7 @@ export const src_json = {
387
398
  {name: 'TS_MATCHER', kind: 'variable'},
388
399
  {name: 'JS_MATCHER', kind: 'variable'},
389
400
  {name: 'JSON_MATCHER', kind: 'variable'},
401
+ {name: 'SVELTE_SCRIPT_MATCHER', kind: 'variable'},
390
402
  {name: 'EVERYTHING_MATCHER', kind: 'variable'},
391
403
  {name: 'JS_CLI_DEFAULT', kind: 'variable'},
392
404
  {name: 'PM_CLI_DEFAULT', kind: 'variable'},
@@ -1,13 +1,35 @@
1
- import {moduleLexerSync} from 'oxc-parser';
1
+ import {parseSync, type ImportDeclaration} from 'oxc-parser';
2
2
  import type {Flavored} from '@ryanatkn/belt/types.js';
3
+ import {Unreachable_Error} from '@ryanatkn/belt/error.js';
3
4
 
4
5
  import type {Path_Id} from './path.js';
5
6
  import {SVELTE_MATCHER} from './svelte_helpers.js';
6
- import {JS_MATCHER, TS_MATCHER} from './constants.js';
7
+ import {JS_MATCHER, TS_MATCHER, SVELTE_SCRIPT_MATCHER} from './constants.js';
7
8
 
8
9
  export type Import_Specifier = Flavored<string, 'Import_Specifier'>;
9
10
 
10
- const script_matcher = /<script.*?>(.*?)<\/script>/gimsu;
11
+ // TODO this is probably way more complicated that it should be, maybe report the issues upstream unless I made a mistake here
12
+
13
+ /**
14
+ * Extracts the string value from a module request, handling different quote styles.
15
+ * Returns null if the value is not a valid string literal.
16
+ */
17
+ const extract_string_literal = (content: string, start: number, end: number): string | null => {
18
+ const value = content.substring(start, end);
19
+
20
+ // Check if it's a string literal (starts and ends with quotes)
21
+ if (
22
+ (value.startsWith("'") && value.endsWith("'")) ||
23
+ (value.startsWith('"') && value.endsWith('"')) ||
24
+ (value.startsWith('`') && value.endsWith('`'))
25
+ ) {
26
+ // Remove the quotes
27
+ return value.slice(1, -1);
28
+ }
29
+
30
+ // Not a valid string literal
31
+ return null;
32
+ };
11
33
 
12
34
  export const parse_imports = (
13
35
  id: Path_Id,
@@ -15,26 +37,141 @@ export const parse_imports = (
15
37
  ignore_types = true,
16
38
  ): Array<Import_Specifier> => {
17
39
  const specifiers: Array<string> = [];
18
-
19
40
  const is_svelte = SVELTE_MATCHER.test(id);
20
41
 
21
42
  const parse_from = (s: string): void => {
22
- const parsed = moduleLexerSync(s, {sourceFilename: is_svelte ? id + '.ts' : id});
23
- for (const p of parsed.imports) {
43
+ const parsed = parseSync(is_svelte ? id + '.ts' : id, s, {});
44
+
45
+ // Process static imports
46
+ for (const static_import of parsed.module.staticImports) {
47
+ // Get the module source node
48
+ const import_decl = parsed.program.body.find(
49
+ (node) => node.type === 'ImportDeclaration' && node.start === static_import.start,
50
+ ) as ImportDeclaration | undefined;
51
+
52
+ if (!import_decl?.source) continue;
53
+
54
+ // Extract the module request string value
55
+ const value = extract_string_literal(s, import_decl.source.start, import_decl.source.end);
56
+
57
+ if (!value) continue;
58
+
59
+ // Skip type-only imports if ignore_types is true
24
60
  if (ignore_types) {
25
- const import_statement = s.slice(p.ss, p.se);
26
- if (import_statement.startsWith('import type')) {
61
+ // Handle import type {...} (type-only imports)
62
+ if (import_decl.importKind === 'type') {
63
+ continue;
64
+ }
65
+
66
+ // Handle inline type imports ({type foo})
67
+ if (static_import.entries.length > 0) {
68
+ // If all imports are type imports, skip this import
69
+ const has_non_type_specifier = static_import.entries.some((entry) => !entry.isType);
70
+ if (!has_non_type_specifier) {
71
+ continue;
72
+ }
73
+ }
74
+ }
75
+
76
+ specifiers.push(value);
77
+ }
78
+
79
+ // Process dynamic imports
80
+ for (const dynamic_import of parsed.module.dynamicImports) {
81
+ // Find the corresponding AST node
82
+ let found = false;
83
+ for (const node of parsed.program.body) {
84
+ if (
85
+ node.type === 'ExpressionStatement' &&
86
+ node.expression.type === 'AwaitExpression' &&
87
+ node.expression.argument.type === 'ImportExpression'
88
+ ) {
89
+ const import_expr = node.expression.argument;
90
+ if (import_expr.start === dynamic_import.start) {
91
+ // Only process string literals (not expressions or variables)
92
+ if (import_expr.source.type === 'Literal') {
93
+ const value = String(import_expr.source.value);
94
+ if (value) {
95
+ specifiers.push(value);
96
+ }
97
+ }
98
+ found = true;
99
+ break;
100
+ }
101
+ }
102
+ }
103
+
104
+ // If we didn't find a match through AST, fall back to the original approach
105
+ // but only for simple string literals
106
+ if (!found) {
107
+ const value = extract_string_literal(
108
+ s,
109
+ dynamic_import.moduleRequest.start,
110
+ dynamic_import.moduleRequest.end,
111
+ );
112
+ if (value) {
113
+ specifiers.push(value);
114
+ }
115
+ }
116
+ }
117
+
118
+ // Process re-exports
119
+ for (const node of parsed.program.body) {
120
+ if (node.type === 'ExportNamedDeclaration' && node.source) {
121
+ // Skip type-only exports if ignore_types is true
122
+ if (ignore_types && node.exportKind === 'type') {
27
123
  continue;
28
124
  }
125
+
126
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
127
+ if (node.source.type === 'Literal') {
128
+ const value = String(node.source.value);
129
+ if (value) {
130
+ specifiers.push(value);
131
+ }
132
+ } else {
133
+ throw new Unreachable_Error(node.source.type);
134
+ }
29
135
  }
30
- if (p.n) specifiers.push(p.n);
31
136
  }
32
137
  };
33
138
 
34
139
  if (is_svelte) {
35
- const matches = contents.matchAll(script_matcher);
36
- for (const m of matches) {
37
- parse_from(m[1]);
140
+ // Reset the regex state between calls
141
+ SVELTE_SCRIPT_MATCHER.lastIndex = 0;
142
+
143
+ // Capture script tags at the top level (not nested in HTML)
144
+ let last_index = 0;
145
+ const script_blocks: Array<{content: string; start: number; end: number}> = [];
146
+
147
+ // First collect all script blocks
148
+ let match;
149
+ while ((match = SVELTE_SCRIPT_MATCHER.exec(contents)) !== null) {
150
+ // Save position of the script tag
151
+ const start = match.index;
152
+ const end = SVELTE_SCRIPT_MATCHER.lastIndex;
153
+
154
+ // Only process top-level script tags (skip nested ones)
155
+ // A nested script would be inside another HTML tag between lastIndex and start
156
+ const text_between = contents.substring(last_index, start);
157
+ const contains_opening_tag = /<[a-z][^>]*>/i.test(text_between);
158
+ const contains_closing_tag = /<\/[a-z][^>]*>/i.test(text_between);
159
+
160
+ // If we're not nested (no HTML tag nesting), process this script
161
+ if (!(contains_opening_tag && !contains_closing_tag)) {
162
+ script_blocks.push({
163
+ content: match[1],
164
+ start,
165
+ end,
166
+ });
167
+ }
168
+
169
+ last_index = end;
170
+ }
171
+
172
+ // Process all the collected script blocks
173
+ for (const block of script_blocks) {
174
+ parse_from(block.content);
38
175
  }
39
176
  } else if (TS_MATCHER.test(id) || JS_MATCHER.test(id)) {
40
177
  parse_from(contents);
@@ -1,6 +1,9 @@
1
1
  // shim for $app/stores
2
2
  // @see https://github.com/sveltejs/kit/issues/1485
3
3
 
4
+ // TODO support `$app/state`
5
+ /* eslint-disable @typescript-eslint/no-deprecated */
6
+
4
7
  import type {
5
8
  getStores as base_getStores,
6
9
  navigating as base_navigating,
@@ -131,11 +131,11 @@ const to_args_schema_type = ({_def}: ZodTypeAny): Arg_Schema['type'] => {
131
131
  case ZodFirstPartyTypeKind.ZodNumber:
132
132
  return 'number';
133
133
  case ZodFirstPartyTypeKind.ZodArray:
134
- return 'string[]'; // TODO support arrays of arbitrary types, or more hardcoded ones as needed
134
+ return 'Array<string>'; // TODO support arrays of arbitrary types, or more hardcoded ones as needed
135
135
  case ZodFirstPartyTypeKind.ZodEnum:
136
136
  return _def.values.map((v: string) => `'${v}'`).join(' | ');
137
137
  case ZodFirstPartyTypeKind.ZodUnion:
138
- return 'string | string[]'; // TODO support unions of arbitrary types, or more hardcoded ones as needed
138
+ return 'string | Array<string>'; // TODO support unions of arbitrary types, or more hardcoded ones as needed
139
139
  default: {
140
140
  const subschema = to_subschema(_def);
141
141
  if (subschema) {
@@ -3,8 +3,10 @@ import {z} from 'zod';
3
3
 
4
4
  import {Task_Error, type Task} from './task.js';
5
5
  import {serialize_args, to_forwarded_args} from './args.js';
6
- import {find_cli, spawn_cli} from './cli.js';
6
+ import {find_cli, spawn_cli, spawn_cli_process} from './cli.js';
7
7
  import {SVELTE_CHECK_CLI, sveltekit_sync_if_available} from './sveltekit_helpers.js';
8
+ import {configure_colored_output_with_path_replacement} from './child_process_logging.js';
9
+ import {paths} from './paths.js';
8
10
 
9
11
  export const Args = z
10
12
  .object({
@@ -14,6 +16,10 @@ export const Args = z
14
16
  typescript_cli: z
15
17
  .string({description: 'the TypeScript CLI to use as a fallback to svelte-check'})
16
18
  .default('tsc'),
19
+ path_replacement: z
20
+ .string({description: 'replacement string for current working directory in output'})
21
+ .default('.'),
22
+ cwd: z.string({description: 'current working directory'}).default(paths.root),
17
23
  })
18
24
  .strict();
19
25
  export type Args = z.infer<typeof Args>;
@@ -22,7 +28,7 @@ export const task: Task<Args> = {
22
28
  summary: 'run tsc on the project without emitting any files',
23
29
  Args,
24
30
  run: async ({args, log}): Promise<void> => {
25
- const {svelte_check_cli, typescript_cli} = args;
31
+ const {svelte_check_cli, typescript_cli, path_replacement, cwd} = args;
26
32
 
27
33
  await sveltekit_sync_if_available();
28
34
 
@@ -30,10 +36,23 @@ export const task: Task<Args> = {
30
36
  const found_svelte_check_cli = find_cli(svelte_check_cli);
31
37
  if (found_svelte_check_cli) {
32
38
  const serialized = serialize_args(to_forwarded_args(svelte_check_cli));
33
- const svelte_check_result = await spawn_cli(found_svelte_check_cli, serialized, log);
34
- if (!svelte_check_result?.ok) {
35
- throw new Task_Error(`Failed to typecheck. ${print_spawn_result(svelte_check_result!)}`);
39
+ const spawned = spawn_cli_process(found_svelte_check_cli, serialized, undefined, {
40
+ stdio: ['inherit', 'pipe', 'pipe'],
41
+ env: {...process.env, FORCE_COLOR: '1'}, // Needed for colors (maybe make an option)
42
+ });
43
+
44
+ const svelte_check_process = spawned?.child;
45
+ if (svelte_check_process) {
46
+ // Configure process output with path replacement while preserving colors
47
+ configure_colored_output_with_path_replacement(svelte_check_process, path_replacement, cwd);
48
+
49
+ const svelte_check_result = await spawned.closed;
50
+
51
+ if (!svelte_check_result.ok) {
52
+ throw new Task_Error(`Failed to typecheck. ${print_spawn_result(svelte_check_result)}`);
53
+ }
36
54
  }
55
+
37
56
  return;
38
57
  }
39
58