@fuzdev/gro 0.192.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 (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +283 -0
  3. package/dist/args.d.ts +37 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +102 -0
  6. package/dist/build.task.d.ts +20 -0
  7. package/dist/build.task.d.ts.map +1 -0
  8. package/dist/build.task.js +119 -0
  9. package/dist/build_cache.d.ts +100 -0
  10. package/dist/build_cache.d.ts.map +1 -0
  11. package/dist/build_cache.js +299 -0
  12. package/dist/changelog.d.ts +11 -0
  13. package/dist/changelog.d.ts.map +1 -0
  14. package/dist/changelog.js +47 -0
  15. package/dist/changeset.task.d.ts +35 -0
  16. package/dist/changeset.task.d.ts.map +1 -0
  17. package/dist/changeset.task.js +151 -0
  18. package/dist/changeset_helpers.d.ts +17 -0
  19. package/dist/changeset_helpers.d.ts.map +1 -0
  20. package/dist/changeset_helpers.js +7 -0
  21. package/dist/check.task.d.ts +28 -0
  22. package/dist/check.task.d.ts.map +1 -0
  23. package/dist/check.task.js +104 -0
  24. package/dist/child_process_logging.d.ts +10 -0
  25. package/dist/child_process_logging.d.ts.map +1 -0
  26. package/dist/child_process_logging.js +26 -0
  27. package/dist/clean.task.d.ts +15 -0
  28. package/dist/clean.task.d.ts.map +1 -0
  29. package/dist/clean.task.js +40 -0
  30. package/dist/clean_fs.d.ts +9 -0
  31. package/dist/clean_fs.d.ts.map +1 -0
  32. package/dist/clean_fs.js +28 -0
  33. package/dist/cli.d.ts +34 -0
  34. package/dist/cli.d.ts.map +1 -0
  35. package/dist/cli.js +61 -0
  36. package/dist/commit.task.d.ts +11 -0
  37. package/dist/commit.task.d.ts.map +1 -0
  38. package/dist/commit.task.js +24 -0
  39. package/dist/constants.d.ts +46 -0
  40. package/dist/constants.d.ts.map +1 -0
  41. package/dist/constants.js +52 -0
  42. package/dist/deploy.task.d.ts +29 -0
  43. package/dist/deploy.task.d.ts.map +1 -0
  44. package/dist/deploy.task.js +217 -0
  45. package/dist/dev.task.d.ts +16 -0
  46. package/dist/dev.task.d.ts.map +1 -0
  47. package/dist/dev.task.js +44 -0
  48. package/dist/disknode.d.ts +23 -0
  49. package/dist/disknode.d.ts.map +1 -0
  50. package/dist/disknode.js +1 -0
  51. package/dist/env.d.ts +11 -0
  52. package/dist/env.d.ts.map +1 -0
  53. package/dist/env.js +49 -0
  54. package/dist/esbuild_helpers.d.ts +16 -0
  55. package/dist/esbuild_helpers.d.ts.map +1 -0
  56. package/dist/esbuild_helpers.js +36 -0
  57. package/dist/esbuild_plugin_external_worker.d.ts +23 -0
  58. package/dist/esbuild_plugin_external_worker.d.ts.map +1 -0
  59. package/dist/esbuild_plugin_external_worker.js +55 -0
  60. package/dist/esbuild_plugin_svelte.d.ts +15 -0
  61. package/dist/esbuild_plugin_svelte.d.ts.map +1 -0
  62. package/dist/esbuild_plugin_svelte.js +83 -0
  63. package/dist/esbuild_plugin_sveltekit_local_imports.d.ts +8 -0
  64. package/dist/esbuild_plugin_sveltekit_local_imports.d.ts.map +1 -0
  65. package/dist/esbuild_plugin_sveltekit_local_imports.js +30 -0
  66. package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts +7 -0
  67. package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts.map +1 -0
  68. package/dist/esbuild_plugin_sveltekit_shim_alias.js +18 -0
  69. package/dist/esbuild_plugin_sveltekit_shim_app.d.ts +9 -0
  70. package/dist/esbuild_plugin_sveltekit_shim_app.d.ts.map +1 -0
  71. package/dist/esbuild_plugin_sveltekit_shim_app.js +22 -0
  72. package/dist/esbuild_plugin_sveltekit_shim_env.d.ts +11 -0
  73. package/dist/esbuild_plugin_sveltekit_shim_env.d.ts.map +1 -0
  74. package/dist/esbuild_plugin_sveltekit_shim_env.js +18 -0
  75. package/dist/filer.d.ts +33 -0
  76. package/dist/filer.d.ts.map +1 -0
  77. package/dist/filer.js +385 -0
  78. package/dist/format.task.d.ts +11 -0
  79. package/dist/format.task.d.ts.map +1 -0
  80. package/dist/format.task.js +27 -0
  81. package/dist/format_directory.d.ts +13 -0
  82. package/dist/format_directory.d.ts.map +1 -0
  83. package/dist/format_directory.js +40 -0
  84. package/dist/format_file.d.ts +9 -0
  85. package/dist/format_file.d.ts.map +1 -0
  86. package/dist/format_file.js +42 -0
  87. package/dist/gen.d.ts +142 -0
  88. package/dist/gen.d.ts.map +1 -0
  89. package/dist/gen.js +199 -0
  90. package/dist/gen.task.d.ts +12 -0
  91. package/dist/gen.task.d.ts.map +1 -0
  92. package/dist/gen.task.js +149 -0
  93. package/dist/gen_helpers.d.ts +11 -0
  94. package/dist/gen_helpers.d.ts.map +1 -0
  95. package/dist/gen_helpers.js +76 -0
  96. package/dist/github.d.ts +19 -0
  97. package/dist/github.d.ts.map +1 -0
  98. package/dist/github.js +33 -0
  99. package/dist/gro.config.default.d.ts +13 -0
  100. package/dist/gro.config.default.d.ts.map +1 -0
  101. package/dist/gro.config.default.js +33 -0
  102. package/dist/gro.d.ts +3 -0
  103. package/dist/gro.d.ts.map +1 -0
  104. package/dist/gro.js +21 -0
  105. package/dist/gro_config.d.ts +115 -0
  106. package/dist/gro_config.d.ts.map +1 -0
  107. package/dist/gro_config.js +114 -0
  108. package/dist/gro_helpers.d.ts +49 -0
  109. package/dist/gro_helpers.d.ts.map +1 -0
  110. package/dist/gro_helpers.js +97 -0
  111. package/dist/gro_plugin_gen.d.ts +12 -0
  112. package/dist/gro_plugin_gen.d.ts.map +1 -0
  113. package/dist/gro_plugin_gen.js +101 -0
  114. package/dist/gro_plugin_server.d.ts +80 -0
  115. package/dist/gro_plugin_server.d.ts.map +1 -0
  116. package/dist/gro_plugin_server.js +167 -0
  117. package/dist/gro_plugin_sveltekit_app.d.ts +9 -0
  118. package/dist/gro_plugin_sveltekit_app.d.ts.map +1 -0
  119. package/dist/gro_plugin_sveltekit_app.js +42 -0
  120. package/dist/gro_plugin_sveltekit_library.d.ts +16 -0
  121. package/dist/gro_plugin_sveltekit_library.d.ts.map +1 -0
  122. package/dist/gro_plugin_sveltekit_library.js +34 -0
  123. package/dist/index.d.ts +9 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +4 -0
  126. package/dist/input_path.d.ts +64 -0
  127. package/dist/input_path.d.ts.map +1 -0
  128. package/dist/input_path.js +199 -0
  129. package/dist/invoke.d.ts +2 -0
  130. package/dist/invoke.d.ts.map +1 -0
  131. package/dist/invoke.js +28 -0
  132. package/dist/invoke_task.d.ts +30 -0
  133. package/dist/invoke_task.d.ts.map +1 -0
  134. package/dist/invoke_task.js +104 -0
  135. package/dist/lint.task.d.ts +11 -0
  136. package/dist/lint.task.d.ts.map +1 -0
  137. package/dist/lint.task.js +32 -0
  138. package/dist/loader.d.ts +6 -0
  139. package/dist/loader.d.ts.map +1 -0
  140. package/dist/loader.js +192 -0
  141. package/dist/module.d.ts +4 -0
  142. package/dist/module.d.ts.map +1 -0
  143. package/dist/module.js +6 -0
  144. package/dist/modules.d.ts +36 -0
  145. package/dist/modules.d.ts.map +1 -0
  146. package/dist/modules.js +71 -0
  147. package/dist/package_json.d.ts +32 -0
  148. package/dist/package_json.d.ts.map +1 -0
  149. package/dist/package_json.js +178 -0
  150. package/dist/parse_exports.d.ts +20 -0
  151. package/dist/parse_exports.d.ts.map +1 -0
  152. package/dist/parse_exports.js +65 -0
  153. package/dist/parse_exports_context.d.ts +21 -0
  154. package/dist/parse_exports_context.d.ts.map +1 -0
  155. package/dist/parse_exports_context.js +332 -0
  156. package/dist/parse_imports.d.ts +5 -0
  157. package/dist/parse_imports.d.ts.map +1 -0
  158. package/dist/parse_imports.js +140 -0
  159. package/dist/paths.d.ts +41 -0
  160. package/dist/paths.d.ts.map +1 -0
  161. package/dist/paths.js +69 -0
  162. package/dist/plugin.d.ts +36 -0
  163. package/dist/plugin.d.ts.map +1 -0
  164. package/dist/plugin.js +78 -0
  165. package/dist/publish.task.d.ts +26 -0
  166. package/dist/publish.task.d.ts.map +1 -0
  167. package/dist/publish.task.js +176 -0
  168. package/dist/register.d.ts +2 -0
  169. package/dist/register.d.ts.map +1 -0
  170. package/dist/register.js +2 -0
  171. package/dist/reinstall.task.d.ts +8 -0
  172. package/dist/reinstall.task.d.ts.map +1 -0
  173. package/dist/reinstall.task.js +35 -0
  174. package/dist/release.task.d.ts +8 -0
  175. package/dist/release.task.d.ts.map +1 -0
  176. package/dist/release.task.js +20 -0
  177. package/dist/resolve.task.d.ts +11 -0
  178. package/dist/resolve.task.d.ts.map +1 -0
  179. package/dist/resolve.task.js +38 -0
  180. package/dist/resolve_specifier.d.ts +22 -0
  181. package/dist/resolve_specifier.d.ts.map +1 -0
  182. package/dist/resolve_specifier.js +57 -0
  183. package/dist/run.task.d.ts +16 -0
  184. package/dist/run.task.d.ts.map +1 -0
  185. package/dist/run.task.js +52 -0
  186. package/dist/run_gen.d.ts +10 -0
  187. package/dist/run_gen.d.ts.map +1 -0
  188. package/dist/run_gen.js +73 -0
  189. package/dist/run_task.d.ts +17 -0
  190. package/dist/run_task.d.ts.map +1 -0
  191. package/dist/run_task.js +45 -0
  192. package/dist/source_json.d.ts +7 -0
  193. package/dist/source_json.d.ts.map +1 -0
  194. package/dist/source_json.js +145 -0
  195. package/dist/svelte_config.d.ts +57 -0
  196. package/dist/svelte_config.d.ts.map +1 -0
  197. package/dist/svelte_config.js +81 -0
  198. package/dist/sveltekit_helpers.d.ts +75 -0
  199. package/dist/sveltekit_helpers.d.ts.map +1 -0
  200. package/dist/sveltekit_helpers.js +94 -0
  201. package/dist/sveltekit_shim_app.d.ts +11 -0
  202. package/dist/sveltekit_shim_app.d.ts.map +1 -0
  203. package/dist/sveltekit_shim_app.js +31 -0
  204. package/dist/sveltekit_shim_app_environment.d.ts +13 -0
  205. package/dist/sveltekit_shim_app_environment.d.ts.map +1 -0
  206. package/dist/sveltekit_shim_app_environment.js +14 -0
  207. package/dist/sveltekit_shim_app_forms.d.ts +5 -0
  208. package/dist/sveltekit_shim_app_forms.d.ts.map +1 -0
  209. package/dist/sveltekit_shim_app_forms.js +6 -0
  210. package/dist/sveltekit_shim_app_navigation.d.ts +10 -0
  211. package/dist/sveltekit_shim_app_navigation.d.ts.map +1 -0
  212. package/dist/sveltekit_shim_app_navigation.js +11 -0
  213. package/dist/sveltekit_shim_app_paths.d.ts +17 -0
  214. package/dist/sveltekit_shim_app_paths.d.ts.map +1 -0
  215. package/dist/sveltekit_shim_app_paths.js +10 -0
  216. package/dist/sveltekit_shim_app_state.d.ts +5 -0
  217. package/dist/sveltekit_shim_app_state.d.ts.map +1 -0
  218. package/dist/sveltekit_shim_app_state.js +26 -0
  219. package/dist/sveltekit_shim_env.d.ts +5 -0
  220. package/dist/sveltekit_shim_env.d.ts.map +1 -0
  221. package/dist/sveltekit_shim_env.js +23 -0
  222. package/dist/sync.task.d.ts +16 -0
  223. package/dist/sync.task.d.ts.map +1 -0
  224. package/dist/sync.task.js +39 -0
  225. package/dist/task.d.ts +98 -0
  226. package/dist/task.d.ts.map +1 -0
  227. package/dist/task.js +109 -0
  228. package/dist/task_logging.d.ts +6 -0
  229. package/dist/task_logging.d.ts.map +1 -0
  230. package/dist/task_logging.js +201 -0
  231. package/dist/test.task.d.ts +13 -0
  232. package/dist/test.task.d.ts.map +1 -0
  233. package/dist/test.task.js +53 -0
  234. package/dist/typecheck.task.d.ts +13 -0
  235. package/dist/typecheck.task.d.ts.map +1 -0
  236. package/dist/typecheck.task.js +68 -0
  237. package/dist/upgrade.task.d.ts +20 -0
  238. package/dist/upgrade.task.d.ts.map +1 -0
  239. package/dist/upgrade.task.js +111 -0
  240. package/dist/watch_dir.d.ts +36 -0
  241. package/dist/watch_dir.d.ts.map +1 -0
  242. package/dist/watch_dir.js +69 -0
  243. package/package.json +149 -0
  244. package/src/lib/args.ts +115 -0
  245. package/src/lib/build.task.ts +151 -0
  246. package/src/lib/build_cache.ts +378 -0
  247. package/src/lib/changelog.ts +69 -0
  248. package/src/lib/changeset.task.ts +228 -0
  249. package/src/lib/changeset_helpers.ts +14 -0
  250. package/src/lib/check.task.ts +132 -0
  251. package/src/lib/child_process_logging.ts +38 -0
  252. package/src/lib/clean.task.ts +48 -0
  253. package/src/lib/clean_fs.ts +54 -0
  254. package/src/lib/cli.ts +98 -0
  255. package/src/lib/commit.task.ts +34 -0
  256. package/src/lib/constants.ts +56 -0
  257. package/src/lib/deploy.task.ts +287 -0
  258. package/src/lib/dev.task.ts +52 -0
  259. package/src/lib/disknode.ts +26 -0
  260. package/src/lib/env.ts +78 -0
  261. package/src/lib/esbuild_helpers.ts +49 -0
  262. package/src/lib/esbuild_plugin_external_worker.ts +94 -0
  263. package/src/lib/esbuild_plugin_svelte.ts +134 -0
  264. package/src/lib/esbuild_plugin_sveltekit_local_imports.ts +38 -0
  265. package/src/lib/esbuild_plugin_sveltekit_shim_alias.ts +27 -0
  266. package/src/lib/esbuild_plugin_sveltekit_shim_app.ts +42 -0
  267. package/src/lib/esbuild_plugin_sveltekit_shim_env.ts +47 -0
  268. package/src/lib/filer.ts +458 -0
  269. package/src/lib/format.task.ts +44 -0
  270. package/src/lib/format_directory.ts +65 -0
  271. package/src/lib/format_file.ts +49 -0
  272. package/src/lib/gen.task.ts +206 -0
  273. package/src/lib/gen.ts +406 -0
  274. package/src/lib/gen_helpers.ts +131 -0
  275. package/src/lib/github.ts +46 -0
  276. package/src/lib/gro.config.default.ts +42 -0
  277. package/src/lib/gro.ts +29 -0
  278. package/src/lib/gro_config.ts +254 -0
  279. package/src/lib/gro_helpers.ts +108 -0
  280. package/src/lib/gro_plugin_gen.ts +149 -0
  281. package/src/lib/gro_plugin_server.ts +288 -0
  282. package/src/lib/gro_plugin_sveltekit_app.ts +58 -0
  283. package/src/lib/gro_plugin_sveltekit_library.ts +63 -0
  284. package/src/lib/index.ts +8 -0
  285. package/src/lib/input_path.ts +254 -0
  286. package/src/lib/invoke.ts +34 -0
  287. package/src/lib/invoke_task.ts +139 -0
  288. package/src/lib/lint.task.ts +39 -0
  289. package/src/lib/loader.ts +229 -0
  290. package/src/lib/module.ts +13 -0
  291. package/src/lib/modules.ts +117 -0
  292. package/src/lib/package_json.ts +255 -0
  293. package/src/lib/parse_exports.ts +100 -0
  294. package/src/lib/parse_exports_context.ts +395 -0
  295. package/src/lib/parse_imports.ts +180 -0
  296. package/src/lib/paths.ts +111 -0
  297. package/src/lib/plugin.ts +106 -0
  298. package/src/lib/publish.task.ts +228 -0
  299. package/src/lib/register.ts +3 -0
  300. package/src/lib/reinstall.task.ts +45 -0
  301. package/src/lib/release.task.ts +26 -0
  302. package/src/lib/resolve.task.ts +43 -0
  303. package/src/lib/resolve_specifier.ts +81 -0
  304. package/src/lib/run.task.ts +65 -0
  305. package/src/lib/run_gen.ts +110 -0
  306. package/src/lib/run_task.ts +82 -0
  307. package/src/lib/source_json.ts +183 -0
  308. package/src/lib/svelte_config.ts +140 -0
  309. package/src/lib/sveltekit_helpers.ts +193 -0
  310. package/src/lib/sveltekit_shim_app.ts +41 -0
  311. package/src/lib/sveltekit_shim_app_environment.ts +16 -0
  312. package/src/lib/sveltekit_shim_app_forms.ts +13 -0
  313. package/src/lib/sveltekit_shim_app_navigation.ts +23 -0
  314. package/src/lib/sveltekit_shim_app_paths.ts +26 -0
  315. package/src/lib/sveltekit_shim_app_state.ts +35 -0
  316. package/src/lib/sveltekit_shim_env.ts +45 -0
  317. package/src/lib/sync.task.ts +47 -0
  318. package/src/lib/task.ts +245 -0
  319. package/src/lib/task_logging.ts +255 -0
  320. package/src/lib/test.task.ts +63 -0
  321. package/src/lib/typecheck.task.ts +81 -0
  322. package/src/lib/upgrade.task.ts +148 -0
  323. package/src/lib/watch_dir.ts +115 -0
@@ -0,0 +1,106 @@
1
+ import type {TaskContext} from './task.ts';
2
+
3
+ /**
4
+ * Gro `Plugin`s enable custom behavior during `gro dev` and `gro build`.
5
+ * In contrast, `Adapter`s use the results of `gro build` to produce final artifacts.
6
+ */
7
+ export interface Plugin<TPluginContext extends PluginContext = PluginContext> {
8
+ name: string;
9
+ setup?: (ctx: TPluginContext) => void | Promise<void>;
10
+ adapt?: (ctx: TPluginContext) => void | Promise<void>;
11
+ teardown?: (ctx: TPluginContext) => void | Promise<void>;
12
+ }
13
+
14
+ export type PluginsCreateConfig<TPluginContext extends PluginContext = PluginContext> = (
15
+ ctx: TPluginContext,
16
+ ) => Array<Plugin<TPluginContext>> | Promise<Array<Plugin<TPluginContext>>>;
17
+
18
+ export interface PluginContext<TArgs = object> extends TaskContext<TArgs> {
19
+ dev: boolean;
20
+ watch: boolean;
21
+ }
22
+
23
+ /** See `Plugins.create` for a usage example. */
24
+ export class Plugins<TPluginContext extends PluginContext> {
25
+ readonly ctx: TPluginContext;
26
+ readonly instances: Array<Plugin<TPluginContext>>;
27
+
28
+ constructor(ctx: TPluginContext, instances: Array<Plugin>) {
29
+ this.ctx = ctx;
30
+ this.instances = instances;
31
+ }
32
+
33
+ static async create<TPluginContext extends PluginContext>(
34
+ ctx: TPluginContext,
35
+ ): Promise<Plugins<TPluginContext>> {
36
+ const {timings} = ctx;
37
+ const timing_to_create = timings.start('plugins.create');
38
+ const instances: Array<Plugin> = await ctx.config.plugins(ctx);
39
+ const plugins = new Plugins(ctx, instances);
40
+ timing_to_create();
41
+ return plugins;
42
+ }
43
+
44
+ async setup(): Promise<void> {
45
+ const {ctx, instances} = this;
46
+ if (!instances.length) return;
47
+ const {timings, log} = ctx;
48
+ const timing_to_setup = timings.start('plugins.setup');
49
+ for (const plugin of instances) {
50
+ if (!plugin.setup) continue;
51
+ log.debug('setup plugin', plugin.name);
52
+ const timing = timings.start(`setup:${plugin.name}`);
53
+ await plugin.setup(ctx); // eslint-disable-line no-await-in-loop
54
+ timing();
55
+ }
56
+ timing_to_setup();
57
+ }
58
+
59
+ async adapt(): Promise<void> {
60
+ const {ctx, instances} = this;
61
+ const {timings} = ctx;
62
+ const timing_to_run_adapters = timings.start('plugins.adapt');
63
+ for (const plugin of instances) {
64
+ if (!plugin.adapt) continue;
65
+ const timing = timings.start(`adapt:${plugin.name}`);
66
+ await plugin.adapt(ctx); // eslint-disable-line no-await-in-loop
67
+ timing();
68
+ }
69
+ timing_to_run_adapters();
70
+ }
71
+
72
+ async teardown(): Promise<void> {
73
+ const {ctx, instances} = this;
74
+ if (!instances.length) return;
75
+ const {timings, log} = ctx;
76
+ const timing_to_teardown = timings.start('plugins.teardown');
77
+ for (const plugin of instances) {
78
+ if (!plugin.teardown) continue;
79
+ log.debug('teardown plugin', plugin.name);
80
+ const timing = timings.start(`teardown:${plugin.name}`);
81
+ await plugin.teardown(ctx); // eslint-disable-line no-await-in-loop
82
+ timing();
83
+ }
84
+ timing_to_teardown();
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Replaces a plugin by name in `plugins` without mutating the param.
90
+ * Throws if the plugin name cannot be found.
91
+ * @param plugins - accepts the same types as the return value of `PluginsCreateConfig`
92
+ * @param new_plugin
93
+ * @param name - @default new_plugin.name
94
+ * @returns `plugins` with `new_plugin` at the index of the plugin with `name`
95
+ */
96
+ export const plugin_replace = (
97
+ plugins: Array<Plugin>,
98
+ new_plugin: Plugin,
99
+ name = new_plugin.name,
100
+ ): Array<Plugin> => {
101
+ const index = plugins.findIndex((p) => p.name === name);
102
+ if (index === -1) throw Error('Failed to find plugin to replace: ' + name);
103
+ const replaced = plugins.slice();
104
+ replaced[index] = new_plugin;
105
+ return replaced;
106
+ };
@@ -0,0 +1,228 @@
1
+ import {spawn} from '@fuzdev/fuz_util/process.js';
2
+ import {z} from 'zod';
3
+ import {styleText as st} from 'node:util';
4
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
5
+ import {
6
+ GitBranch,
7
+ GitOrigin,
8
+ git_check_clean_workspace,
9
+ git_checkout,
10
+ git_fetch,
11
+ git_pull,
12
+ } from '@fuzdev/fuz_util/git.js';
13
+
14
+ import {TaskError, type Task} from './task.ts';
15
+ import {package_json_load, package_json_parse_repo_url} from './package_json.ts';
16
+ import {find_cli, spawn_cli} from './cli.ts';
17
+ import {has_sveltekit_library} from './sveltekit_helpers.ts';
18
+ import {update_changelog} from './changelog.ts';
19
+ import {load_from_env} from './env.ts';
20
+ import {CHANGESET_CLI} from './changeset_helpers.ts';
21
+
22
+ /** @nodocs */
23
+ export const Args = z.strictObject({
24
+ branch: GitBranch.describe('branch to publish from').default('main'),
25
+ origin: GitOrigin.describe('git origin to publish from').default('origin'),
26
+ changelog: z
27
+ .string()
28
+ .meta({description: 'file name and path of the changelog'})
29
+ .default('CHANGELOG.md'),
30
+ preserve_changelog: z
31
+ .boolean()
32
+ .meta({
33
+ description:
34
+ 'opt out of linkifying and formatting the changelog from @changesets/changelog-git',
35
+ })
36
+ .default(false),
37
+ optional: z
38
+ .boolean()
39
+ .meta({description: 'exit gracefully if there are no changesets'})
40
+ .default(false),
41
+ dry: z
42
+ .boolean()
43
+ .meta({description: 'build and prepare to publish without actually publishing'})
44
+ .default(false),
45
+ check: z.boolean().meta({description: 'dual of no-check'}).default(true),
46
+ 'no-check': z
47
+ .boolean()
48
+ .meta({description: 'opt out of checking before publishing'})
49
+ .default(false),
50
+ build: z.boolean().meta({description: 'dual of no-build'}).default(true),
51
+ 'no-build': z.boolean().meta({description: 'opt out of building'}).default(false),
52
+ pull: z.boolean().meta({description: 'dual of no-pull'}).default(true),
53
+ 'no-pull': z.boolean().meta({description: 'opt out of git pull'}).default(false),
54
+ sync: z.boolean().meta({description: 'dual of no-sync'}).default(true),
55
+ 'no-sync': z.boolean().meta({description: 'opt out of gro sync'}).default(false),
56
+ install: z.boolean().meta({description: 'dual of no-install'}).default(true),
57
+ 'no-install': z
58
+ .boolean()
59
+ .meta({description: 'opt out of installing packages before publishing'})
60
+ .default(false),
61
+ changeset_cli: z.string().meta({description: 'the changeset CLI to use'}).default(CHANGESET_CLI),
62
+ });
63
+ export type Args = z.infer<typeof Args>;
64
+
65
+ /** @nodocs */
66
+ export const task: Task<Args> = {
67
+ summary: 'bump version, publish to the configured registry, and git push',
68
+ Args,
69
+ run: async ({args, log, invoke_task, config}): Promise<void> => {
70
+ const {
71
+ branch,
72
+ origin,
73
+ changelog,
74
+ preserve_changelog,
75
+ dry,
76
+ check,
77
+ build,
78
+ pull,
79
+ sync,
80
+ install,
81
+ optional,
82
+ changeset_cli,
83
+ } = args;
84
+ if (dry) {
85
+ log.info(st('green', 'dry run!'));
86
+ }
87
+
88
+ const package_json = await package_json_load();
89
+
90
+ const has_sveltekit_library_result = await has_sveltekit_library(package_json);
91
+ if (!has_sveltekit_library_result.ok) {
92
+ throw new TaskError(
93
+ 'Failed to find SvelteKit library: ' + has_sveltekit_library_result.message,
94
+ );
95
+ }
96
+
97
+ const changelog_exists = await fs_exists(changelog);
98
+
99
+ const found_changeset_cli = await find_cli(changeset_cli);
100
+ if (!found_changeset_cli) {
101
+ throw new TaskError(
102
+ 'changeset command not found, install @changesets/cli locally or globally',
103
+ );
104
+ }
105
+
106
+ // Make sure we're on the right branch:
107
+ await git_fetch(origin, branch);
108
+ await git_checkout(branch);
109
+ if (pull) {
110
+ if (await git_check_clean_workspace()) {
111
+ throw new TaskError('The git workspace is not clean, pass --no-pull to bypass git pull');
112
+ }
113
+ await git_pull(origin, branch);
114
+ }
115
+
116
+ // Install packages to ensure deps are current.
117
+ // Handles cases like branch switches where package.json changed.
118
+ // Skip gen because it will run after version bump.
119
+ if (sync || install) {
120
+ if (!sync) log.warn('sync is false but install is true, so running sync for install only');
121
+ await invoke_task('sync', {install, gen: false});
122
+ }
123
+
124
+ // Check before proceeding, defaults to true.
125
+ if (check) {
126
+ await invoke_task('check', {workspace: true, sync: false});
127
+ }
128
+
129
+ let version!: string;
130
+ let optional_and_version_unchanged = false;
131
+
132
+ // Bump the version so the package.json is updated before building:
133
+ // TODO problem here is build may fail and put us in a bad state,
134
+ // but I don't see how we could do this to robustly
135
+ // have the new version in the build without building twice -
136
+ // maybe the code should catch the error and revert the version and delete the tag?
137
+ if (dry) {
138
+ log.info('dry run, skipping changeset version');
139
+ } else {
140
+ if (typeof package_json.version !== 'string') {
141
+ throw new TaskError('Failed to find package.json version');
142
+ }
143
+ const parsed_repo_url = package_json_parse_repo_url(package_json);
144
+ if (!parsed_repo_url) {
145
+ throw new TaskError(
146
+ 'package.json `repository` must contain a repo url (and GitHub only for now, sorry),' +
147
+ ' like `git+https://github.com/fuzdev/gro.git` or `https://github.com/fuzdev/gro`' +
148
+ ' or an object with the `url` key',
149
+ );
150
+ }
151
+
152
+ // This is the first line that alters the repo.
153
+
154
+ const changeset_version_result = await spawn_cli(found_changeset_cli, ['version'], log);
155
+ if (!changeset_version_result?.ok) {
156
+ throw Error('changeset version failed: no commits were made: see the error above');
157
+ }
158
+
159
+ if (!preserve_changelog) {
160
+ const token = load_from_env('SECRET_GITHUB_API_TOKEN');
161
+ if (!token) {
162
+ log.warn(
163
+ 'the env var SECRET_GITHUB_API_TOKEN was not found, so API calls with be unauthorized',
164
+ );
165
+ }
166
+ await update_changelog(parsed_repo_url.owner, parsed_repo_url.repo, changelog, token, log);
167
+ }
168
+
169
+ // Update package-lock.json to reflect the new version.
170
+ if (install) {
171
+ const install_result = await spawn(config.pm_cli, ['install']);
172
+ if (!install_result.ok) {
173
+ throw new TaskError(`Failed \`${config.pm_cli} install\` after version bump`);
174
+ }
175
+ }
176
+
177
+ // Regenerate files that depend on package.json version.
178
+ // The check above ensures gen is updated.
179
+ await invoke_task('gen');
180
+
181
+ const package_json_after_versioning = await package_json_load();
182
+ version = package_json_after_versioning.version!;
183
+ if (package_json.version === version) {
184
+ // The version didn't change.
185
+ // For now this is the best detection we have for a no-op `changeset version`.
186
+ if (optional) {
187
+ optional_and_version_unchanged = true;
188
+ } else {
189
+ // Doesn't build if the version didn't change and publishing isn't optional.
190
+ throw new TaskError(`\`${changeset_cli} version\` failed: are there any changes?`);
191
+ }
192
+ }
193
+ }
194
+
195
+ // Build after the version is bumped so the new version is in the build as needed.
196
+ // Skip sync and install because we already handled both above.
197
+ if (build) {
198
+ await invoke_task('build', {sync: false, install: false});
199
+ }
200
+
201
+ // Return early if there are no changes and publishing is optional, but after building,
202
+ // so if callers want to optimize away building
203
+ // they need to do so manually like in `gro release`.
204
+ // TODO this could be cleaned up if tasks had a return value to callers, it could specifiy that it didn't build
205
+ if (optional_and_version_unchanged) return;
206
+
207
+ if (dry) {
208
+ log.info('publishing branch ' + branch);
209
+ log.info(st('green', 'dry run complete!'));
210
+ return;
211
+ }
212
+
213
+ const changeset_publish_result = await spawn_cli(found_changeset_cli, ['publish'], log);
214
+ if (!changeset_publish_result?.ok) {
215
+ throw new TaskError(
216
+ `\`${changeset_cli} publish\` failed - continue manually or try again after running \`git reset --hard\``,
217
+ );
218
+ }
219
+
220
+ if (!changelog_exists && (await fs_exists(changelog))) {
221
+ await spawn('git', ['add', changelog]);
222
+ }
223
+ await spawn('git', ['commit', '-a', '-m', `publish v${version}`]);
224
+ await spawn('git', ['push', '--follow-tags']);
225
+
226
+ log.info(st('green', `published to branch ${st('cyan', branch)}!`));
227
+ },
228
+ };
@@ -0,0 +1,3 @@
1
+ import {register} from 'node:module';
2
+
3
+ register('./loader.js', import.meta.url);
@@ -0,0 +1,45 @@
1
+ import {z} from 'zod';
2
+ import {spawn} from '@fuzdev/fuz_util/process.js';
3
+ import {rm} from 'node:fs/promises';
4
+
5
+ import {TaskError, type Task} from './task.ts';
6
+ import {LOCKFILE_FILENAME, NODE_MODULES_DIRNAME} from './constants.ts';
7
+
8
+ /** @nodocs */
9
+ export const Args = z.strictObject({});
10
+ export type Args = z.infer<typeof Args>;
11
+
12
+ /** @nodocs */
13
+ export const task: Task<Args> = {
14
+ summary: `refreshes ${LOCKFILE_FILENAME} with the latest and cleanest deps`,
15
+ Args,
16
+ run: async ({log, config}): Promise<void> => {
17
+ log.info(`running the initial \`${config.pm_cli} install\``);
18
+ const initial_install_result = await spawn(config.pm_cli, ['install']);
19
+ if (!initial_install_result.ok) {
20
+ throw new TaskError(`Failed initial \`${config.pm_cli} install\``);
21
+ }
22
+
23
+ // Deleting both the lockfile and node_modules upgrades to the latest minor/patch versions.
24
+ await Promise.all([rm(LOCKFILE_FILENAME), rm(NODE_MODULES_DIRNAME, {recursive: true})]);
25
+ log.info(
26
+ `running \`${config.pm_cli} install\` after deleting ${LOCKFILE_FILENAME} and ${NODE_MODULES_DIRNAME}, this can take a while...`,
27
+ );
28
+ const second_install_result = await spawn(config.pm_cli, ['install']);
29
+ if (!second_install_result.ok) {
30
+ throw new TaskError(
31
+ `Failed \`${config.pm_cli} install\` after deleting ${LOCKFILE_FILENAME} and ${NODE_MODULES_DIRNAME}`,
32
+ );
33
+ }
34
+
35
+ // TODO @many this relies on npm behavior that changed in v11
36
+ // Deleting the lockfile and reinstalling cleans the lockfile of unnecessary dep noise,
37
+ // like esbuild's many packages for each platform.
38
+ await rm(LOCKFILE_FILENAME);
39
+ log.info(`running \`${config.pm_cli} install\` one last time to clean ${LOCKFILE_FILENAME}`);
40
+ const final_install_result = await spawn(config.pm_cli, ['install']);
41
+ if (!final_install_result.ok) {
42
+ throw new TaskError(`Failed \`${config.pm_cli} install\``);
43
+ }
44
+ },
45
+ };
@@ -0,0 +1,26 @@
1
+ import {z} from 'zod';
2
+
3
+ import type {Task} from './task.ts';
4
+ import {has_sveltekit_library, has_sveltekit_app} from './sveltekit_helpers.ts';
5
+ import {package_json_load} from './package_json.ts';
6
+
7
+ /** @nodocs */
8
+ export const Args = z.strictObject({});
9
+ export type Args = z.infer<typeof Args>;
10
+
11
+ /** @nodocs */
12
+ export const task: Task<Args> = {
13
+ summary: 'publish and deploy',
14
+ Args,
15
+ run: async ({invoke_task}) => {
16
+ const package_json = await package_json_load();
17
+
18
+ const publish = (await has_sveltekit_library(package_json)).ok;
19
+ if (publish) {
20
+ await invoke_task('publish', {optional: true});
21
+ }
22
+ if ((await has_sveltekit_app()).ok) {
23
+ await invoke_task('deploy', {build: !publish});
24
+ }
25
+ },
26
+ };
@@ -0,0 +1,43 @@
1
+ import {z} from 'zod';
2
+ import {styleText as st} from 'node:util';
3
+
4
+ import {TASK_FILE_SUFFIXES, type Task} from './task.ts';
5
+ import {resolve_input_paths, to_input_paths} from './input_path.ts';
6
+
7
+ /** @nodocs */
8
+ export const Args = z.strictObject({
9
+ _: z.array(z.string()).meta({description: 'the input paths to resolve'}).default(['']),
10
+ verbose: z.boolean().meta({description: 'log diagnostics'}).default(false),
11
+ });
12
+ export type Args = z.infer<typeof Args>;
13
+
14
+ /** @nodocs */
15
+ export const task: Task<Args> = {
16
+ summary: 'diagnostic that logs resolved filesystem info for the given input paths',
17
+ Args,
18
+ run: async ({args, config, log}): Promise<void> => {
19
+ const {_, verbose} = args;
20
+
21
+ if (verbose) log.info('raw input paths:', _);
22
+
23
+ const input_paths = to_input_paths(_);
24
+ if (verbose) log.info('input paths:', input_paths);
25
+
26
+ const {task_root_dirs} = config;
27
+ if (verbose) log.info('task root paths:', task_root_dirs);
28
+
29
+ const {resolved_input_paths, possible_paths_by_input_path, unmapped_input_paths} =
30
+ await resolve_input_paths(input_paths, task_root_dirs, TASK_FILE_SUFFIXES);
31
+ if (verbose) log.info('resolved_input_paths:', resolved_input_paths);
32
+ if (verbose) log.info('possible_paths_by_input_path:', possible_paths_by_input_path);
33
+ if (verbose) log.info('unmapped_input_paths:', unmapped_input_paths);
34
+
35
+ for (const p of resolved_input_paths) {
36
+ log.info('resolved:', st('green', p.id));
37
+ }
38
+
39
+ if (!resolved_input_paths.length) {
40
+ log.warn(st('yellow', 'no input paths were resolved'));
41
+ }
42
+ },
43
+ };
@@ -0,0 +1,81 @@
1
+ import {extname, isAbsolute, join, relative} from 'node:path';
2
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
3
+ import type {PathId} from '@fuzdev/fuz_util/path.js';
4
+
5
+ import {replace_extension} from './paths.ts';
6
+
7
+ // TODO ideally this module doesnt exist, but import.meta.resolve doesn't work in loaders last I tried
8
+
9
+ export interface ResolvedSpecifier {
10
+ /**
11
+ * The resolved filesystem path for the specifier.
12
+ */
13
+ path_id: PathId;
14
+ /**
15
+ * Same as `path_id` but includes `?raw` and other querystrings. (currently none)
16
+ */
17
+ path_id_with_querystring: string;
18
+ specifier: string;
19
+ mapped_specifier: string;
20
+ namespace: undefined | 'sveltekit_local_imports_ts' | 'sveltekit_local_imports_js';
21
+ raw: boolean;
22
+ }
23
+
24
+ /**
25
+ * Maps an import `specifier` relative to `dir`,
26
+ * and infer the correct extension following Vite conventions.
27
+ * If no `.js` file is found for the specifier on the filesystem, it assumes `.ts`.
28
+ */
29
+ export const resolve_specifier = async (
30
+ specifier: string,
31
+ dir: string,
32
+ ): Promise<ResolvedSpecifier> => {
33
+ const raw = specifier.endsWith('?raw'); // TODO more robust detection? other values?
34
+ const final_specifier = raw ? specifier.substring(0, specifier.length - 4) : specifier;
35
+ const absolute_path = isAbsolute(final_specifier) ? final_specifier : join(dir, final_specifier);
36
+
37
+ let mapped_path;
38
+ let path_id;
39
+ let namespace: ResolvedSpecifier['namespace'];
40
+
41
+ const ext = extname(absolute_path);
42
+ const is_js = ext === '.js';
43
+ const is_ts = ext === '.ts';
44
+
45
+ if (!is_js && !is_ts && (await fs_exists(absolute_path))) {
46
+ // unrecognized extension and the file exists
47
+ mapped_path = absolute_path;
48
+ path_id = absolute_path;
49
+ } else if (is_ts) {
50
+ // explicitly ts
51
+ mapped_path = replace_extension(absolute_path, '.js');
52
+ path_id = absolute_path;
53
+ namespace = 'sveltekit_local_imports_ts';
54
+ } else {
55
+ // extensionless, or js that points to ts, or just js
56
+ const js_id = is_js ? absolute_path : absolute_path + '.js';
57
+ const ts_id = is_js ? replace_extension(absolute_path, '.ts') : absolute_path + '.ts';
58
+ const [ts_exists, js_exists] = await Promise.all([fs_exists(ts_id), fs_exists(js_id)]);
59
+ if (!ts_exists && js_exists) {
60
+ mapped_path = js_id;
61
+ path_id = js_id;
62
+ namespace = 'sveltekit_local_imports_js';
63
+ } else {
64
+ mapped_path = js_id;
65
+ path_id = ts_id;
66
+ namespace = 'sveltekit_local_imports_ts';
67
+ }
68
+ }
69
+
70
+ let mapped_specifier = relative(dir, mapped_path);
71
+ if (mapped_specifier[0] !== '.') mapped_specifier = './' + mapped_specifier;
72
+
73
+ return {
74
+ path_id,
75
+ path_id_with_querystring: raw ? path_id + '?raw' : path_id,
76
+ raw,
77
+ specifier,
78
+ mapped_specifier,
79
+ namespace,
80
+ };
81
+ };
@@ -0,0 +1,65 @@
1
+ import {args_serialize} from '@fuzdev/fuz_util/args.js';
2
+ import {fs_exists} from '@fuzdev/fuz_util/fs.js';
3
+ import {spawn_result_to_message} from '@fuzdev/fuz_util/process.js';
4
+ import {styleText as st} from 'node:util';
5
+ import {z} from 'zod';
6
+
7
+ import {to_implicit_forwarded_args} from './args.ts';
8
+ import {resolve_gro_module_path, spawn_with_loader} from './gro_helpers.ts';
9
+ import {TaskError, type Task} from './task.ts';
10
+
11
+ /**
12
+ * Runs a TypeScript file with Gro's loader, forwarding all args to the script.
13
+ * Useful for scripts that need SvelteKit shims ($lib, $env, etc).
14
+ *
15
+ * @module
16
+ */
17
+
18
+ /** @nodocs */
19
+ export const Args = z
20
+ .object({
21
+ _: z.array(z.string()).meta({description: 'the file path to run'}).default([]),
22
+ })
23
+ .catchall(
24
+ z.union([
25
+ z.string(),
26
+ z.number(),
27
+ z.boolean(),
28
+ z.array(z.union([z.string(), z.number(), z.boolean()])),
29
+ ]),
30
+ );
31
+ export type Args = z.infer<typeof Args>;
32
+
33
+ /** @nodocs */
34
+ export const task: Task<Args> = {
35
+ summary: 'execute a file with the loader, like `node` but works for TypeScript',
36
+ Args,
37
+ run: async ({args, log}) => {
38
+ const {_, ...forwarded_args} = args;
39
+ const [path, ...positional_argv] = _;
40
+
41
+ if (!path) {
42
+ log.info(st('green', '\n\nUsage: ') + st('cyan', 'gro run path/to/file.ts [...args]\n'));
43
+ return;
44
+ }
45
+
46
+ if (!(await fs_exists(path))) {
47
+ throw new TaskError('Cannot find file to run at path: ' + path);
48
+ }
49
+
50
+ // Get args after `--` without requiring a command name.
51
+ // This allows `gro run script.ts -- --help` to pass --help to the script.
52
+ const implicit_args = to_implicit_forwarded_args();
53
+
54
+ // Reconstruct argv: positional args + explicit named args + implicit args after --
55
+ const named_argv = args_serialize({...forwarded_args, ...implicit_args});
56
+ const full_argv = [...positional_argv, ...named_argv];
57
+
58
+ const loader_path = resolve_gro_module_path('loader.js');
59
+
60
+ const spawned = await spawn_with_loader(loader_path, path, full_argv);
61
+ if (!spawned.ok) {
62
+ throw new TaskError(`\`gro run ${path}\` failed: ${spawn_result_to_message(spawned)}`);
63
+ }
64
+ },
65
+ };