@ryanatkn/gro 0.117.0 → 0.118.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 (63) hide show
  1. package/README.md +31 -15
  2. package/dist/changeset.task.js +1 -1
  3. package/dist/clean_fs.js +2 -1
  4. package/dist/cli.js +1 -1
  5. package/dist/config.js +3 -2
  6. package/dist/deploy.task.js +5 -4
  7. package/dist/docs/gen.md +16 -0
  8. package/dist/docs/tasks.gen.md.js +2 -3
  9. package/dist/esbuild_plugin_external_worker.js +1 -2
  10. package/dist/esbuild_plugin_svelte.js +1 -2
  11. package/dist/esbuild_plugin_sveltekit_shim_alias.js +1 -2
  12. package/dist/format_directory.js +3 -2
  13. package/dist/gen.d.ts +5 -0
  14. package/dist/gen.task.js +2 -2
  15. package/dist/gro.config.default.js +3 -2
  16. package/dist/gro_helpers.js +18 -17
  17. package/dist/gro_plugin_server.js +9 -5
  18. package/dist/gro_plugin_sveltekit_app.d.ts +0 -1
  19. package/dist/gro_plugin_sveltekit_app.js +2 -4
  20. package/dist/gro_plugin_sveltekit_library.d.ts +0 -2
  21. package/dist/gro_plugin_sveltekit_library.js +1 -7
  22. package/dist/input_path.d.ts +1 -1
  23. package/dist/input_path.js +1 -1
  24. package/dist/input_path.test.js +3 -3
  25. package/dist/invoke_task.js +9 -10
  26. package/dist/lint.task.js +1 -1
  27. package/dist/loader.js +11 -4
  28. package/dist/module.d.ts +1 -1
  29. package/dist/module.js +2 -2
  30. package/dist/modules.test.js +2 -2
  31. package/dist/package.d.ts +41 -0
  32. package/dist/package.js +57 -31
  33. package/dist/package_json.d.ts +5 -0
  34. package/dist/package_json.js +7 -2
  35. package/dist/package_meta.d.ts +1 -2
  36. package/dist/path_constants.d.ts +20 -0
  37. package/dist/path_constants.js +27 -0
  38. package/dist/paths.d.ts +2 -26
  39. package/dist/paths.js +10 -33
  40. package/dist/publish.task.js +1 -1
  41. package/dist/register.d.ts +1 -0
  42. package/dist/register.js +2 -0
  43. package/dist/release.task.js +1 -2
  44. package/dist/resolve_node_specifier.js +2 -1
  45. package/dist/run_gen.d.ts +2 -1
  46. package/dist/run_gen.js +2 -2
  47. package/dist/run_gen.test.js +3 -2
  48. package/dist/sveltekit_config.d.ts +1 -1
  49. package/dist/sveltekit_config.js +9 -5
  50. package/dist/sveltekit_config_global.d.ts +4 -0
  51. package/dist/sveltekit_config_global.js +5 -0
  52. package/dist/sveltekit_helpers.d.ts +4 -0
  53. package/dist/sveltekit_helpers.js +12 -0
  54. package/dist/sync.task.js +4 -1
  55. package/dist/task.d.ts +1 -1
  56. package/dist/task.js +11 -7
  57. package/dist/task.test.js +9 -13
  58. package/dist/task_logging.d.ts +2 -2
  59. package/dist/task_logging.js +4 -4
  60. package/dist/task_module.d.ts +3 -3
  61. package/dist/task_module.js +6 -6
  62. package/dist/task_module.test.js +4 -7
  63. package/package.json +18 -2
package/README.md CHANGED
@@ -35,8 +35,7 @@ It includes:
35
35
  [`@sveltejs/package`](https://kit.svelte.dev/docs/packaging) for the library
36
36
  - exposes all of its internals in `$lib`
37
37
  - uses [Changesets](https://github.com/changesets/changesets) for versioning and changelogs
38
- - provides a [Node loader](/src/lib/loader.ts) and
39
- [esbuild plugins for the server](/src/lib/gro_plugin_server.ts)
38
+ - provides a [Node loader](/src/lib/loader.ts) with a [register hook](/src/lib/register.ts)
40
39
  - supports importing TypeScript, JSON, and SSR'd Svelte files in tests and tasks
41
40
  - supports [SvelteKit module imports](https://kit.svelte.dev/docs/modules) for
42
41
  `$lib`, `$env`, and `$app` in tasks, tests, Node servers,
@@ -44,8 +43,10 @@ It includes:
44
43
  so you can use SvelteKit patterns everywhere
45
44
  (these are best-effort shims, not perfect)
46
45
  - supports running TypeScript files directly without a task via `gro run a.ts`
47
- - [configurable plugins](/src/lib/docs/plugin.md)
48
- to support SvelteKit, auto-restarting Node servers, and other external build processes
46
+ or `node --import @ryanatkn/gro/register.js a.ts`
47
+ - [configurable plugins](/src/lib/docs/plugin.md) to support SvelteKit,
48
+ [auto-restarting Node servers](/src/lib/gro_plugin_server.ts),
49
+ and other external build processes
49
50
  - see the [Gro config docs](/src/lib/docs/config.md) and
50
51
  [the default config](https://github.com/ryanatkn/gro/blob/main/src/lib/gro.config.default.ts)
51
52
  - see [`fuz_template`](https://github.com/fuz-dev/fuz_template)
@@ -126,17 +127,34 @@ typecheck run tsc on the project without emitting any files
126
127
  upgrade upgrade deps
127
128
  ```
128
129
 
129
- Gro matches your CLI input against its filesystem conventions.
130
+ To run tasks, Gro matches your CLI input against its filesystem conventions.
130
131
  It tries to do the right thing, where right is helpful but not surprising,
131
132
  with some magic but not too much:
132
133
 
133
134
  ```bash
134
- gro # print all available tasks, those matching `src/lib/**/*.task.ts` and Gro's builtins
135
- gro some/dir # list all tasks inside `src/lib/some/dir`
136
- gro some/file # run `src/lib/some/file.task.ts`
135
+ gro # displays all available tasks matching `src/lib/**/*.task.ts` and Gro's builtins
136
+ gro a # tries to run `src/lib/a.task.ts`, then `./a.task.ts`, then Gro's builtin if one exists
137
+ gro a --help # displays docs for the "a" task and its args, works for every task
138
+ gro some/dir # lists all tasks inside `src/lib/some/dir`
139
+ gro some/file # runs `src/lib/some/file.task.ts`
137
140
  gro some/file.task.ts # same as above
138
- gro a # run `src/lib/a.task.ts` if it exists, falling back to Gro's builtin
139
- gro a --help # print info about the "a" task; works for every task
141
+ ```
142
+
143
+ Gro can also run non-task TypeScript files directly
144
+ with [the `gro run` task](/src/lib/run.task.ts) or [register hook](/src/lib/register.ts):
145
+
146
+ ```bash
147
+ gro run foo.ts
148
+ node --import @ryanatkn/gro/register.js foo.ts
149
+ ```
150
+
151
+ Or programmatically:
152
+
153
+ ```js
154
+ // myfile.js
155
+ import {register} from 'node:module';
156
+ register('@ryanatkn/gro/loader.js', import.meta.url);
157
+ await import('./foo.ts');
140
158
  ```
141
159
 
142
160
  Gro has a number of builtin tasks that you can run with the CLI.
@@ -200,19 +218,17 @@ To publish: (also see [`src/lib/docs/publish.md`](/src/lib/docs/publish.md))
200
218
  gro publish # flush changeset to changelog, bump version, publish to npm, and git push
201
219
  ```
202
220
 
203
- Etc:
221
+ More:
204
222
 
205
223
  ```bash
206
224
  gro clean # delete all build artifacts from the filesystem
207
225
  gro clean --sveltekit --nodemodules --git # also deletes dirs and prunes git branches
208
226
  gro upgrade excluded-dep-1 excluded-dep-2 # npm updates to the latest everything
209
- ```
210
-
211
- ```bash
212
227
  gro --version # print the Gro version
213
228
  ```
214
229
 
215
- For more see [`src/lib/docs/task.md`](/src/lib/docs/task.md) and [`src/lib/docs`](/src/lib/docs).
230
+ For more see [the tasks index](/src/lib/docs/tasks.md),
231
+ [the task feature docs](/src/lib/docs/task.md), and [the docs index](/src/lib/docs/README.md).
216
232
 
217
233
  ## develop
218
234
 
@@ -9,7 +9,7 @@ import { exists } from './fs.js';
9
9
  import { load_package_json } from './package_json.js';
10
10
  import { find_cli, spawn_cli } from './cli.js';
11
11
  import { Git_Origin, git_push_to_create } from './git.js';
12
- import { has_sveltekit_library } from './gro_plugin_sveltekit_library.js';
12
+ import { has_sveltekit_library } from './sveltekit_helpers.js';
13
13
  const RESTRICTED_ACCESS = 'restricted';
14
14
  const PUBLIC_ACCESS = 'public';
15
15
  const CHANGESET_DIR = '.changeset';
package/dist/clean_fs.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { rm, readdir } from 'node:fs/promises';
2
- import { NODE_MODULES_DIRNAME, paths, SVELTEKIT_DEV_DIRNAME, SVELTEKIT_BUILD_DIRNAME, SVELTEKIT_VITE_CACHE_PATH, GRO_DIST_PREFIX, SVELTEKIT_DIST_DIRNAME, } from './paths.js';
2
+ import { paths } from './paths.js';
3
+ import { NODE_MODULES_DIRNAME, GRO_DIST_PREFIX, SVELTEKIT_DEV_DIRNAME, SVELTEKIT_BUILD_DIRNAME, SVELTEKIT_VITE_CACHE_PATH, SVELTEKIT_DIST_DIRNAME, } from './path_constants.js';
3
4
  export const clean_fs = async ({ build = false, build_dev = false, build_dist = false, sveltekit = false, nodemodules = false, }, rm_options = { force: true, recursive: true }) => {
4
5
  const promises = [];
5
6
  if (build) {
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { spawn, spawn_out } from '@ryanatkn/belt/process.js';
2
2
  import { join } from 'node:path';
3
3
  import { exists } from './fs.js';
4
- import { NODE_MODULES_DIRNAME } from './paths.js';
4
+ import { NODE_MODULES_DIRNAME } from './path_constants.js';
5
5
  /**
6
6
  * Looks for the CLI `name`, first local to the cwd and then globally.
7
7
  */
package/dist/config.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { join, resolve } from 'node:path';
2
- import { CONFIG_PATH, GRO_DIST_DIR, IS_THIS_GRO, paths } from './paths.js';
2
+ import { GRO_DIST_DIR, IS_THIS_GRO, paths } from './paths.js';
3
+ import { GRO_CONFIG_PATH } from './path_constants.js';
3
4
  import create_default_config from './gro.config.default.js';
4
5
  import { exists } from './fs.js';
5
6
  export const create_empty_config = () => ({
@@ -17,7 +18,7 @@ const default_map_package_json = async (package_json) => {
17
18
  export const DEFAULT_EXPORTS_EXCLUDER = /(\.md|\.(test|ignore)\.|\/(test|fixtures|ignore)\/)/u;
18
19
  export const load_config = async (dir = paths.root) => {
19
20
  const default_config = await create_default_config(create_empty_config());
20
- const config_path = join(dir, CONFIG_PATH);
21
+ const config_path = join(dir, GRO_CONFIG_PATH);
21
22
  let config;
22
23
  if (await exists(config_path)) {
23
24
  const config_module = await import(config_path);
@@ -5,7 +5,8 @@ import { z } from 'zod';
5
5
  import { cp, mkdir, readdir, rm } from 'node:fs/promises';
6
6
  import { join, resolve } from 'node:path';
7
7
  import { Task_Error } from './task.js';
8
- import { GIT_DIRNAME, GRO_DIRNAME, print_path, SVELTEKIT_BUILD_DIRNAME } from './paths.js';
8
+ import { print_path } from './paths.js';
9
+ import { GRO_DIRNAME, GIT_DIRNAME, SVELTEKIT_BUILD_DIRNAME } from './path_constants.js';
9
10
  import { empty_dir, exists } from './fs.js';
10
11
  import { git_check_clean_workspace, git_checkout, git_local_branch_exists, git_remote_branch_exists, Git_Origin, Git_Branch, git_delete_local_branch, git_push_to_create, git_reset_branch_to_first_commit, git_pull, git_fetch, git_check_setting_pull_rebase, git_clone_locally, git_current_branch_name, } from './git.js';
11
12
  // docs at ./docs/deploy.md
@@ -13,7 +14,7 @@ import { git_check_clean_workspace, git_checkout, git_local_branch_exists, git_r
13
14
  // terminal command for testing:
14
15
  // npm run build && rm -rf .gro && clear && gro deploy --source no-git-workspace --no-build --dry
15
16
  // TODO customize
16
- const cwd = process.cwd();
17
+ const dir = process.cwd();
17
18
  const INITIAL_FILE_PATH = '.gitkeep';
18
19
  const INITIAL_FILE_CONTENTS = '';
19
20
  const DEPLOY_DIR = GRO_DIRNAME + '/deploy';
@@ -121,7 +122,7 @@ export const task = {
121
122
  if (!(await exists(resolved_deploy_dir))) {
122
123
  const local_deploy_branch_exists = await git_local_branch_exists(target);
123
124
  await git_fetch(origin, ('+' + target + ':' + target)); // fetch+merge and allow non-fastforward updates with the +
124
- await git_clone_locally(origin, target, cwd, resolved_deploy_dir);
125
+ await git_clone_locally(origin, target, dir, resolved_deploy_dir);
125
126
  // Clean up if we created the target branch in the cwd
126
127
  if (!local_deploy_branch_exists) {
127
128
  await git_delete_local_branch(target);
@@ -145,7 +146,7 @@ export const task = {
145
146
  }
146
147
  // Create the target branch locally and remotely.
147
148
  // This is more complex to avoid churning the cwd.
148
- await git_clone_locally(origin, source, cwd, resolved_deploy_dir);
149
+ await git_clone_locally(origin, source, dir, resolved_deploy_dir);
149
150
  await spawn(`git checkout --orphan ${target} && ` +
150
151
  // TODO there's definitely a better way to do this
151
152
  `git rm -rf . && ` +
package/dist/docs/gen.md CHANGED
@@ -91,6 +91,22 @@ Outputs `src/script.ts`:
91
91
  console.log('generated a string');
92
92
  ```
93
93
 
94
+ ### gen context
95
+
96
+ The `Gen` function receives one argument, the `Gen_Context` object:
97
+
98
+ ```ts
99
+ export interface Gen_Context {
100
+ config: Gro_Config;
101
+ /**
102
+ * Same as `import.meta.url` but in path form.
103
+ */
104
+ origin_id: string;
105
+ log: Logger;
106
+ }
107
+ // export const gen: Gen = ({config, origin_id, log}) => {
108
+ ```
109
+
94
110
  ### generate other filetypes
95
111
 
96
112
  Files with any extension can be generated without configuration.
@@ -14,14 +14,13 @@ import { log_error_reasons } from '../task_logging.js';
14
14
  // TODO display more info about each task, including a summary and params
15
15
  // TODO needs some cleanup and better APIs - paths are confusing and verbose!
16
16
  // TODO add backlinks to every document that links to this one
17
- export const gen = async ({ origin_id, log }) => {
18
- const result = await load_task_modules([paths.lib]);
17
+ export const gen = async ({ config, origin_id, log }) => {
18
+ const result = await load_task_modules([paths.lib], config.task_root_paths);
19
19
  if (!result.ok) {
20
20
  log_error_reasons(log, result.reasons);
21
21
  throw new Error(result.type);
22
22
  }
23
23
  const tasks = result.modules;
24
- // TODO need to get this from project config or something
25
24
  const root_path = parse_path_segments(paths.root).at(-1);
26
25
  const origin_dir = dirname(origin_id);
27
26
  const origin_base = basename(origin_id);
@@ -1,6 +1,5 @@
1
1
  import * as esbuild from 'esbuild';
2
2
  import { basename } from 'node:path';
3
- import { cwd } from 'node:process';
4
3
  import { print_build_result, to_define_import_meta_env } from './esbuild_helpers.js';
5
4
  import { resolve_specifier } from './resolve_specifier.js';
6
5
  import { esbuild_plugin_sveltekit_shim_alias } from './esbuild_plugin_sveltekit_shim_alias.js';
@@ -8,7 +7,7 @@ import { esbuild_plugin_sveltekit_shim_env } from './esbuild_plugin_sveltekit_sh
8
7
  import { esbuild_plugin_sveltekit_shim_app } from './esbuild_plugin_sveltekit_shim_app.js';
9
8
  import { esbuild_plugin_sveltekit_local_imports } from './esbuild_plugin_sveltekit_local_imports.js';
10
9
  import { esbuild_plugin_svelte } from './esbuild_plugin_svelte.js';
11
- export const esbuild_plugin_external_worker = ({ dev, build_options, dir = cwd(), svelte_compile_options, svelte_preprocessors, svelte_compile_module_options, alias, base_url, assets_url, public_prefix, private_prefix, env_dir, env_files, ambient_env, log, }) => ({
10
+ export const esbuild_plugin_external_worker = ({ dev, build_options, dir = process.cwd(), svelte_compile_options, svelte_preprocessors, svelte_compile_module_options, alias, base_url, assets_url, public_prefix, private_prefix, env_dir, env_files, ambient_env, log, }) => ({
12
11
  name: 'external_worker',
13
12
  setup: (build) => {
14
13
  const builds = new Map();
@@ -1,10 +1,9 @@
1
1
  import { compile, compileModule, preprocess, } from 'svelte/compiler';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { relative } from 'node:path';
4
- import { cwd } from 'node:process';
5
4
  import { SVELTE_MATCHER, SVELTE_RUNES_MATCHER } from './svelte_helpers.js';
6
5
  export const esbuild_plugin_svelte = (options = {}) => {
7
- const { dir = cwd(), svelte_compile_options = {}, svelte_compile_module_options = {}, svelte_preprocessors, } = options;
6
+ const { dir = process.cwd(), svelte_compile_options = {}, svelte_compile_module_options = {}, svelte_preprocessors, } = options;
8
7
  return {
9
8
  name: 'svelte',
10
9
  setup: (build) => {
@@ -1,7 +1,6 @@
1
1
  import { escape_regexp } from '@ryanatkn/belt/regexp.js';
2
- import { cwd } from 'node:process';
3
2
  import { join } from 'node:path';
4
- export const esbuild_plugin_sveltekit_shim_alias = ({ dir = cwd(), alias, }) => ({
3
+ export const esbuild_plugin_sveltekit_shim_alias = ({ dir = process.cwd(), alias, }) => ({
5
4
  name: 'sveltekit_shim_alias',
6
5
  setup: (build) => {
7
6
  const aliases = { $lib: 'src/lib', ...alias };
@@ -1,10 +1,11 @@
1
1
  import { spawn } from '@ryanatkn/belt/process.js';
2
- import { GITHUB_DIRNAME, paths, README_FILENAME, SVELTEKIT_CONFIG_FILENAME, VITE_CONFIG_FILENAME, TSCONFIG_FILENAME, CONFIG_PATH, } from './paths.js';
2
+ import { paths } from './paths.js';
3
+ import { GITHUB_DIRNAME, README_FILENAME, SVELTEKIT_CONFIG_FILENAME, VITE_CONFIG_FILENAME, TSCONFIG_FILENAME, GRO_CONFIG_PATH, } from './path_constants.js';
3
4
  import { print_command_args, serialize_args, to_forwarded_args } from './args.js';
4
5
  const DEFAULT_EXTENSIONS = 'ts,js,json,svelte,html,css,md,yml';
5
6
  const DEFAULT_ROOT_PATHS = `${[
6
7
  README_FILENAME,
7
- CONFIG_PATH,
8
+ GRO_CONFIG_PATH,
8
9
  SVELTEKIT_CONFIG_FILENAME,
9
10
  VITE_CONFIG_FILENAME,
10
11
  TSCONFIG_FILENAME,
package/dist/gen.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Logger } from '@ryanatkn/belt/log.js';
2
2
  import { z } from 'zod';
3
+ import type { Gro_Config } from './config.js';
3
4
  export type Gen_Result = {
4
5
  origin_id: string;
5
6
  files: Gen_File[];
@@ -14,6 +15,10 @@ export interface Gen {
14
15
  (ctx: Gen_Context): Raw_Gen_Result | Promise<Raw_Gen_Result>;
15
16
  }
16
17
  export interface Gen_Context {
18
+ config: Gro_Config;
19
+ /**
20
+ * Same as `import.meta.url` but in path form.
21
+ */
17
22
  origin_id: string;
18
23
  log: Logger;
19
24
  }
package/dist/gen.task.js CHANGED
@@ -25,7 +25,7 @@ export const Args = z
25
25
  export const task = {
26
26
  summary: 'run code generation scripts',
27
27
  Args,
28
- run: async ({ args, log, timings }) => {
28
+ run: async ({ args, log, timings, config }) => {
29
29
  const { _: raw_input_paths, check } = args;
30
30
  const input_paths = raw_input_paths.length ? to_input_paths(raw_input_paths) : [paths.source];
31
31
  // load all of the gen modules
@@ -48,7 +48,7 @@ export const task = {
48
48
  }
49
49
  // run `gen` on each of the modules
50
50
  const timing_to_generate_code = timings.start('generate code'); // TODO this ignores `gen_results.elapsed` - should it return `Timings` instead?
51
- const gen_results = await run_gen(load_modules_result.modules, log, timings, format_file);
51
+ const gen_results = await run_gen(load_modules_result.modules, config, log, timings, format_file);
52
52
  timing_to_generate_code();
53
53
  const fail_count = gen_results.failures.length;
54
54
  if (check) {
@@ -1,6 +1,7 @@
1
- import { has_sveltekit_library, gro_plugin_sveltekit_library, } from './gro_plugin_sveltekit_library.js';
1
+ import { gro_plugin_sveltekit_library } from './gro_plugin_sveltekit_library.js';
2
2
  import { has_server, gro_plugin_server } from './gro_plugin_server.js';
3
- import { has_sveltekit_app, gro_plugin_sveltekit_app } from './gro_plugin_sveltekit_app.js';
3
+ import { gro_plugin_sveltekit_app } from './gro_plugin_sveltekit_app.js';
4
+ import { has_sveltekit_app, has_sveltekit_library } from './sveltekit_helpers.js';
4
5
  /**
5
6
  * This is the default config that's passed to `gro.config.ts`
6
7
  * if it exists in the current project, and if not, this is the final config.
@@ -3,7 +3,12 @@ import { join, resolve } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { spawn } from '@ryanatkn/belt/process.js';
5
5
  import { exists } from './fs.js';
6
- import { NODE_MODULES_DIRNAME } from './paths.js';
6
+ import { NODE_MODULES_DIRNAME, SVELTEKIT_DIST_DIRNAME } from './path_constants.js';
7
+ /*
8
+
9
+ This module is intended to have minimal dependencies to avoid over-imports in the CLI.
10
+
11
+ */
7
12
  /**
8
13
  * Resolves a path to an internal Gro file.
9
14
  * Prefers any local installation of Gro and falls back to the current CLI context.
@@ -40,26 +45,22 @@ import { NODE_MODULES_DIRNAME } from './paths.js';
40
45
  */
41
46
  export const resolve_gro_module_path = async (path = '') => {
42
47
  const gro_bin_path = resolve(NODE_MODULES_DIRNAME, '.bin/gro');
48
+ // case 1
49
+ // Prefer any locally installed version of Gro.
43
50
  if (await exists(gro_bin_path)) {
44
- // case 1
45
- // Prefer any locally installed version of Gro.
46
51
  return join(await realpath(gro_bin_path), '..', path);
47
52
  }
48
- else {
49
- // case 2
50
- // If running Gro inside its own repo, require the local dist.
51
- // If the local dist is not yet built it will fall back to the global.
52
- const file_path = fileURLToPath(import.meta.url);
53
- const base_path = 'dist';
54
- if ((await exists(join(base_path, 'gro.js'))) && (await exists(join(base_path, path)))) {
55
- return join(file_path, '../..', base_path, path);
56
- }
57
- else {
58
- // case 3
59
- // Fall back to the version associated with the running CLI.
60
- return join(file_path, '..', path);
61
- }
53
+ // case 2
54
+ // If running Gro inside its own repo, require the local dist.
55
+ // If the local dist is not yet built it will fall back to the global.
56
+ if ((await exists(join(SVELTEKIT_DIST_DIRNAME, 'gro.js'))) &&
57
+ (await exists(join(SVELTEKIT_DIST_DIRNAME, path)))) {
58
+ return resolve(SVELTEKIT_DIST_DIRNAME, path);
62
59
  }
60
+ // case 3
61
+ // Fall back to the version associated with the running CLI.
62
+ const file_path = fileURLToPath(import.meta.url);
63
+ return join(file_path, '..', path);
63
64
  };
64
65
  /**
65
66
  * Runs a file using the Gro loader.
@@ -1,10 +1,10 @@
1
1
  import { spawn_restartable_process } from '@ryanatkn/belt/process.js';
2
2
  import * as esbuild from 'esbuild';
3
- import { cwd } from 'node:process';
4
3
  import { join, resolve } from 'node:path';
5
4
  import { identity } from '@ryanatkn/belt/function.js';
6
- import { strip_before } from '@ryanatkn/belt/string.js';
7
- import { base_path_to_source_id, GRO_DEV_DIRNAME, SERVER_DIST_PATH, LIB_DIRNAME, paths, } from './paths.js';
5
+ import { strip_before, strip_end } from '@ryanatkn/belt/string.js';
6
+ import { base_path_to_source_id, LIB_DIRNAME, paths } from './paths.js';
7
+ import { GRO_DEV_DIRNAME, SERVER_DIST_PATH } from './path_constants.js';
8
8
  import { watch_dir } from './watch_dir.js';
9
9
  import { init_sveltekit_config } from './sveltekit_config.js';
10
10
  import { esbuild_plugin_sveltekit_shim_app } from './esbuild_plugin_sveltekit_shim_app.js';
@@ -16,10 +16,11 @@ import { esbuild_plugin_sveltekit_local_imports } from './esbuild_plugin_sveltek
16
16
  import { exists } from './fs.js';
17
17
  import { esbuild_plugin_svelte } from './esbuild_plugin_svelte.js';
18
18
  import { throttle } from './throttle.js';
19
+ import { sveltekit_config_global } from './sveltekit_config_global.js';
19
20
  // TODO sourcemap as a hoisted option? disable for production by default - or like `outpaths`, passed a `dev` param
20
21
  export const SERVER_SOURCE_ID = base_path_to_source_id(LIB_DIRNAME + '/server/server.ts');
21
22
  export const has_server = (path = SERVER_SOURCE_ID) => exists(path);
22
- export const gro_plugin_server = ({ entry_points = [SERVER_SOURCE_ID], dir = cwd(), outpaths = (dev) => ({
23
+ export const gro_plugin_server = ({ entry_points = [SERVER_SOURCE_ID], dir = process.cwd(), outpaths = (dev) => ({
23
24
  outdir: join(dir, dev ? GRO_DEV_DIRNAME : SERVER_DIST_PATH),
24
25
  outbase: paths.lib,
25
26
  outname: 'server/server.js',
@@ -32,7 +33,10 @@ export const gro_plugin_server = ({ entry_points = [SERVER_SOURCE_ID], dir = cwd
32
33
  return {
33
34
  name: 'gro_plugin_server',
34
35
  setup: async ({ dev, watch, timings, log }) => {
35
- const { alias, base_url, assets_url, env_dir, private_prefix, public_prefix, svelte_compile_options, svelte_compile_module_options, svelte_preprocessors, } = await init_sveltekit_config(sveltekit_config ?? dir);
36
+ const parsed_sveltekit_config = !sveltekit_config && strip_end(dir, '/') === process.cwd()
37
+ ? sveltekit_config_global
38
+ : await init_sveltekit_config(sveltekit_config ?? dir);
39
+ const { alias, base_url, assets_url, env_dir, private_prefix, public_prefix, svelte_compile_options, svelte_compile_module_options, svelte_preprocessors, } = parsed_sveltekit_config;
36
40
  // TODO hacky
37
41
  if (svelte_compile_options.generate === undefined) {
38
42
  svelte_compile_options.generate = 'server';
@@ -1,7 +1,6 @@
1
1
  import type { Plugin, Plugin_Context } from './plugin.js';
2
2
  import { type Map_Package_Json } from './package_json.js';
3
3
  import { type Map_Src_Json } from './src_json.js';
4
- export declare const has_sveltekit_app: () => Promise<boolean>;
5
4
  export interface Options {
6
5
  /**
7
6
  * Used for finalizing a SvelteKit build like adding a `.nojekyll` file for GitHub Pages.
@@ -4,13 +4,11 @@ import { dirname, join } from 'node:path';
4
4
  import { print_command_args, serialize_args, to_forwarded_args } from './args.js';
5
5
  import { exists } from './fs.js';
6
6
  import { serialize_package_json, load_package_json } from './package_json.js';
7
- import { init_sveltekit_config } from './sveltekit_config.js';
8
7
  import { Task_Error } from './task.js';
9
8
  import { spawn_cli } from './cli.js';
10
9
  import { serialize_src_json, create_src_json } from './src_json.js';
11
10
  import { DEFAULT_EXPORTS_EXCLUDER } from './config.js';
12
- import { SVELTEKIT_CONFIG_FILENAME } from './paths.js';
13
- export const has_sveltekit_app = () => exists(SVELTEKIT_CONFIG_FILENAME);
11
+ import { sveltekit_config_global } from './sveltekit_config_global.js';
14
12
  export const gro_plugin_sveltekit_app = ({ host_target = 'github_pages', well_known_package_json, well_known_src_json, well_known_src_files, } = {}) => {
15
13
  let sveltekit_process = null;
16
14
  return {
@@ -57,7 +55,7 @@ export const gro_plugin_sveltekit_app = ({ host_target = 'github_pages', well_kn
57
55
  // maybe a Vite middleware is best? what if this plugin added its plugin to your `vite.config.ts`?
58
56
  // copy files to `static` before building, in such a way
59
57
  // that's non-destructive to existing files and dirs and easy to clean up
60
- const { assets_path } = await init_sveltekit_config(); // TODO probably put in plugin context
58
+ const { assets_path } = sveltekit_config_global;
61
59
  const cleanups = [
62
60
  serialized_package_json
63
61
  ? await create_temporarily(join(assets_path, '.well-known/package.json'), serialized_package_json)
@@ -1,4 +1,2 @@
1
1
  import type { Plugin, Plugin_Context } from './plugin.js';
2
- import { Package_Json } from './package_json.js';
3
- export declare const has_sveltekit_library: (package_json?: Package_Json) => Promise<boolean>;
4
2
  export declare const gro_plugin_sveltekit_library: () => Plugin<Plugin_Context>;
@@ -1,14 +1,8 @@
1
1
  import { print_spawn_result, spawn } from '@ryanatkn/belt/process.js';
2
2
  import { Task_Error } from './task.js';
3
- import { Package_Json, load_package_json } from './package_json.js';
3
+ import { load_package_json } from './package_json.js';
4
4
  import { print_command_args, serialize_args, to_forwarded_args } from './args.js';
5
5
  import { find_cli, spawn_cli } from './cli.js';
6
- export const has_sveltekit_library = async (package_json) => {
7
- const p = package_json ?? (await load_package_json()); // TODO from param, on config?
8
- return !!p.devDependencies?.['@sveltejs/package'] || !!p.dependencies?.['@sveltejs/package'];
9
- // TODO @multiple get from the sveltekit config
10
- // && exists(sveltekit_config.lib_path);
11
- };
12
6
  export const gro_plugin_sveltekit_library = () => {
13
7
  return {
14
8
  name: 'gro_plugin_sveltekit_library',
@@ -26,7 +26,7 @@ export declare const to_input_paths: (raw_input_paths: Raw_Input_Path[], root_pa
26
26
  * This is first used to fall back to the Gro dir to search for tasks.
27
27
  * It's the helper used in implementations of `get_possible_source_ids_for_input_path` below.
28
28
  */
29
- export declare const get_possible_source_ids: (input_path: Flavored<string, "Input_Path">, extensions: string[], root_dirs?: string[]) => Source_Id[];
29
+ export declare const get_possible_source_ids: (input_path: Flavored<string, "Input_Path">, extensions: string[], root_dirs: string[]) => Source_Id[];
30
30
  /**
31
31
  * Gets the path data for each input path, checking the filesystem for the possibilities
32
32
  * and stopping at the first existing file or falling back to the first existing directory.
@@ -59,7 +59,7 @@ export const get_possible_source_ids = (input_path, extensions, root_dirs) => {
59
59
  if (isAbsolute(input_path)) {
60
60
  add_possible_source_ids(input_path);
61
61
  }
62
- else if (root_dirs?.length) {
62
+ else {
63
63
  for (const root_dir of root_dirs) {
64
64
  add_possible_source_ids(join(root_dir, input_path));
65
65
  }
@@ -22,14 +22,14 @@ test('to_input_paths', () => {
22
22
  });
23
23
  test('get_possible_source_ids in the gro directory', () => {
24
24
  const input_path = resolve('src/foo/bar');
25
- assert.equal(get_possible_source_ids(input_path, ['.baz.ts']), [
25
+ assert.equal(get_possible_source_ids(input_path, ['.baz.ts'], []), [
26
26
  input_path,
27
27
  input_path + '.baz.ts',
28
28
  ]);
29
29
  });
30
30
  test('get_possible_source_ids does not repeat the extension', () => {
31
31
  const input_path = resolve('src/foo/bar.baz.ts');
32
- assert.equal(get_possible_source_ids(input_path, ['.baz.ts']), [input_path]);
32
+ assert.equal(get_possible_source_ids(input_path, ['.baz.ts'], []), [input_path]);
33
33
  });
34
34
  test('get_possible_source_ids does not repeat with the same root directory', () => {
35
35
  const input_path = resolve('src/foo/bar.baz.ts');
@@ -39,7 +39,7 @@ test('get_possible_source_ids does not repeat with the same root directory', ()
39
39
  });
40
40
  test('get_possible_source_ids implied to be a directory by trailing slash', () => {
41
41
  const input_path = resolve('src/foo/bar') + '/';
42
- assert.equal(get_possible_source_ids(input_path, ['.baz.ts']), [input_path]);
42
+ assert.equal(get_possible_source_ids(input_path, ['.baz.ts'], []), [input_path]);
43
43
  });
44
44
  test('load_source_ids_by_input_path', async () => {
45
45
  const test_files = {
@@ -39,14 +39,15 @@ export const invoke_task = async (task_name, args, config, timings = new Timings
39
39
  if (!task_name && (args.version || args.v)) {
40
40
  const gro_package_json = await load_gro_package_json();
41
41
  log.info(`${gray('v')}${cyan(gro_package_json.version)}`);
42
- log.info(`🕒 ${print_ms(total_timing())}`);
42
+ finish();
43
43
  return;
44
44
  }
45
45
  // Resolve the input path for the provided task name.
46
46
  const input_path = to_input_path(task_name);
47
+ const { task_root_paths } = config;
47
48
  // Find the task or directory specified by the `input_path`.
48
49
  // Fall back to searching the Gro directory as well.
49
- const find_modules_result = await find_task_modules([input_path], config.task_root_paths);
50
+ const find_modules_result = await find_task_modules([input_path], task_root_paths);
50
51
  if (!find_modules_result.ok) {
51
52
  if (find_modules_result.type === 'input_directories_with_no_files') {
52
53
  // The input path matched a directory, but it contains no matching files.
@@ -60,8 +61,7 @@ export const invoke_task = async (task_name, args, config, timings = new Timings
60
61
  else {
61
62
  // If there's a matching directory in the current working directory,
62
63
  // but it has no matching files, we still want to search Gro's directory.
63
- const gro_dir_find_modules_result = await log_gro_package_tasks(input_path, log);
64
- // TODO this doesn't seem to be working as commented, test this condition in another repo (maybe like "gro sync" when there's a "src/lib/sync" folder)
64
+ const gro_dir_find_modules_result = await log_gro_package_tasks(input_path, task_root_paths, log);
65
65
  if (!gro_dir_find_modules_result.ok) {
66
66
  // Log the original errors, not the Gro-specific ones.
67
67
  log_error_reasons(log, find_modules_result.reasons);
@@ -83,7 +83,7 @@ export const invoke_task = async (task_name, args, config, timings = new Timings
83
83
  if (!path_data.isDirectory) {
84
84
  // The input path matches a file, so load and run it.
85
85
  // Try to load the task module.
86
- const load_modules_result = await load_modules(find_modules_result.source_ids_by_input_path, load_task_module);
86
+ const load_modules_result = await load_modules(find_modules_result.source_ids_by_input_path, (id) => load_task_module(id, task_root_paths));
87
87
  if (load_modules_result.ok) {
88
88
  // We found a task module. Run it!
89
89
  // `path_data` is not a directory, so there's a single task module here.
@@ -110,21 +110,20 @@ export const invoke_task = async (task_name, args, config, timings = new Timings
110
110
  // The input path matches a directory. Log the tasks but don't run them.
111
111
  if (IS_THIS_GRO) {
112
112
  // Is the Gro directory the same as the cwd? Log the matching files.
113
- await log_tasks(log, print_path(path_data.id), find_modules_result.source_ids_by_input_path);
113
+ await log_tasks(log, print_path(path_data.id), find_modules_result.source_ids_by_input_path, task_root_paths);
114
114
  }
115
115
  else if (is_gro_id(path_data.id)) {
116
- // TODO delete this? merge behavior with the block above/below?
117
116
  // Does the Gro directory contain the matching files? Log them.
118
- await log_tasks(log, print_path_or_gro_path(path_data.id), find_modules_result.source_ids_by_input_path);
117
+ await log_tasks(log, print_path_or_gro_path(path_data.id), find_modules_result.source_ids_by_input_path, task_root_paths);
119
118
  }
120
119
  else {
121
120
  // The Gro directory is not the same as the cwd and it doesn't contain the matching files.
122
121
  // Find all of the possible matches in both the current project and the Gro directory,
123
122
  // and log everything out.
124
123
  // Ignore any errors - the directory may not exist or have any files!
125
- const gro_dir_find_modules_result = await log_gro_package_tasks(input_path, log);
124
+ const gro_dir_find_modules_result = await log_gro_package_tasks(input_path, task_root_paths, log);
126
125
  // Then log the current working directory matches.
127
- await log_tasks(log, print_path(path_data.id), find_modules_result.source_ids_by_input_path, !gro_dir_find_modules_result.ok);
126
+ await log_tasks(log, print_path(path_data.id), find_modules_result.source_ids_by_input_path, task_root_paths, !gro_dir_find_modules_result.ok);
128
127
  }
129
128
  }
130
129
  finish();
package/dist/lint.task.js CHANGED
@@ -2,7 +2,7 @@ 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 { print_command_args, serialize_args, to_forwarded_args } from './args.js';
5
- import { SOURCE_DIRNAME } from './paths.js';
5
+ import { SOURCE_DIRNAME } from './path_constants.js';
6
6
  import { find_cli, spawn_cli } from './cli.js';
7
7
  export const Args = z
8
8
  .object({
package/dist/loader.js CHANGED
@@ -5,21 +5,28 @@ import { dirname, join } from 'node:path';
5
5
  import { escape_regexp } from '@ryanatkn/belt/regexp.js';
6
6
  import { render_env_shim_module } from './sveltekit_shim_env.js';
7
7
  import { render_sveltekit_shim_app_environment, render_sveltekit_shim_app_paths, sveltekit_shim_app_environment_matcher, sveltekit_shim_app_paths_matcher, sveltekit_shim_app_specifiers, } from './sveltekit_shim_app.js';
8
- import { init_sveltekit_config } from './sveltekit_config.js';
8
+ import { sveltekit_config_global } from './sveltekit_config_global.js';
9
9
  import { SVELTE_MATCHER, SVELTE_RUNES_MATCHER } from './svelte_helpers.js';
10
- import { paths, NODE_MODULES_DIRNAME } from './paths.js';
10
+ import { paths } from './paths.js';
11
+ import { NODE_MODULES_DIRNAME } from './path_constants.js';
11
12
  import { to_define_import_meta_env, ts_transform_options } from './esbuild_helpers.js';
12
13
  import { resolve_specifier } from './resolve_specifier.js';
13
14
  import { resolve_node_specifier } from './resolve_node_specifier.js';
14
15
  /*
15
16
 
17
+ Usage via `$lib/register.ts`:
18
+
19
+ ```bash
20
+ node --import @ryanatkn/gro/register.js foo.ts
21
+ ```
22
+
16
23
  Usage via `$lib/run.task.ts`:
17
24
 
18
25
  ```bash
19
26
  gro run foo.ts
20
27
  ```
21
28
 
22
- Direct usage (see also `$lib/gro.ts`):
29
+ Direct usage without register (see also `$lib/gro.ts`):
23
30
 
24
31
  ```bash
25
32
  node --import 'data:text/javascript,import {register} from "node:module"; import {pathToFileURL} from "node:url"; register("@ryanatkn/gro/loader.js", pathToFileURL("./"));' --enable-source-maps' foo.ts
@@ -34,7 +41,7 @@ TODO how to improve that gnarly import line? was originally designed for the now
34
41
  // dev is always true in the loader
35
42
  const dev = true;
36
43
  const dir = paths.root;
37
- const { alias, base_url, assets_url, env_dir, private_prefix, public_prefix, svelte_compile_options, svelte_compile_module_options, svelte_preprocessors, } = await init_sveltekit_config(dir); // always load it to keep things simple ahead
44
+ const { alias, base_url, assets_url, env_dir, private_prefix, public_prefix, svelte_compile_options, svelte_compile_module_options, svelte_preprocessors, } = sveltekit_config_global;
38
45
  const final_ts_transform_options = {
39
46
  ...ts_transform_options,
40
47
  define: to_define_import_meta_env(dev, base_url),