@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.
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/args.d.ts +37 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +102 -0
- package/dist/build.task.d.ts +20 -0
- package/dist/build.task.d.ts.map +1 -0
- package/dist/build.task.js +119 -0
- package/dist/build_cache.d.ts +100 -0
- package/dist/build_cache.d.ts.map +1 -0
- package/dist/build_cache.js +299 -0
- package/dist/changelog.d.ts +11 -0
- package/dist/changelog.d.ts.map +1 -0
- package/dist/changelog.js +47 -0
- package/dist/changeset.task.d.ts +35 -0
- package/dist/changeset.task.d.ts.map +1 -0
- package/dist/changeset.task.js +151 -0
- package/dist/changeset_helpers.d.ts +17 -0
- package/dist/changeset_helpers.d.ts.map +1 -0
- package/dist/changeset_helpers.js +7 -0
- package/dist/check.task.d.ts +28 -0
- package/dist/check.task.d.ts.map +1 -0
- package/dist/check.task.js +104 -0
- package/dist/child_process_logging.d.ts +10 -0
- package/dist/child_process_logging.d.ts.map +1 -0
- package/dist/child_process_logging.js +26 -0
- package/dist/clean.task.d.ts +15 -0
- package/dist/clean.task.d.ts.map +1 -0
- package/dist/clean.task.js +40 -0
- package/dist/clean_fs.d.ts +9 -0
- package/dist/clean_fs.d.ts.map +1 -0
- package/dist/clean_fs.js +28 -0
- package/dist/cli.d.ts +34 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +61 -0
- package/dist/commit.task.d.ts +11 -0
- package/dist/commit.task.d.ts.map +1 -0
- package/dist/commit.task.js +24 -0
- package/dist/constants.d.ts +46 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +52 -0
- package/dist/deploy.task.d.ts +29 -0
- package/dist/deploy.task.d.ts.map +1 -0
- package/dist/deploy.task.js +217 -0
- package/dist/dev.task.d.ts +16 -0
- package/dist/dev.task.d.ts.map +1 -0
- package/dist/dev.task.js +44 -0
- package/dist/disknode.d.ts +23 -0
- package/dist/disknode.d.ts.map +1 -0
- package/dist/disknode.js +1 -0
- package/dist/env.d.ts +11 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +49 -0
- package/dist/esbuild_helpers.d.ts +16 -0
- package/dist/esbuild_helpers.d.ts.map +1 -0
- package/dist/esbuild_helpers.js +36 -0
- package/dist/esbuild_plugin_external_worker.d.ts +23 -0
- package/dist/esbuild_plugin_external_worker.d.ts.map +1 -0
- package/dist/esbuild_plugin_external_worker.js +55 -0
- package/dist/esbuild_plugin_svelte.d.ts +15 -0
- package/dist/esbuild_plugin_svelte.d.ts.map +1 -0
- package/dist/esbuild_plugin_svelte.js +83 -0
- package/dist/esbuild_plugin_sveltekit_local_imports.d.ts +8 -0
- package/dist/esbuild_plugin_sveltekit_local_imports.d.ts.map +1 -0
- package/dist/esbuild_plugin_sveltekit_local_imports.js +30 -0
- package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts +7 -0
- package/dist/esbuild_plugin_sveltekit_shim_alias.d.ts.map +1 -0
- package/dist/esbuild_plugin_sveltekit_shim_alias.js +18 -0
- package/dist/esbuild_plugin_sveltekit_shim_app.d.ts +9 -0
- package/dist/esbuild_plugin_sveltekit_shim_app.d.ts.map +1 -0
- package/dist/esbuild_plugin_sveltekit_shim_app.js +22 -0
- package/dist/esbuild_plugin_sveltekit_shim_env.d.ts +11 -0
- package/dist/esbuild_plugin_sveltekit_shim_env.d.ts.map +1 -0
- package/dist/esbuild_plugin_sveltekit_shim_env.js +18 -0
- package/dist/filer.d.ts +33 -0
- package/dist/filer.d.ts.map +1 -0
- package/dist/filer.js +385 -0
- package/dist/format.task.d.ts +11 -0
- package/dist/format.task.d.ts.map +1 -0
- package/dist/format.task.js +27 -0
- package/dist/format_directory.d.ts +13 -0
- package/dist/format_directory.d.ts.map +1 -0
- package/dist/format_directory.js +40 -0
- package/dist/format_file.d.ts +9 -0
- package/dist/format_file.d.ts.map +1 -0
- package/dist/format_file.js +42 -0
- package/dist/gen.d.ts +142 -0
- package/dist/gen.d.ts.map +1 -0
- package/dist/gen.js +199 -0
- package/dist/gen.task.d.ts +12 -0
- package/dist/gen.task.d.ts.map +1 -0
- package/dist/gen.task.js +149 -0
- package/dist/gen_helpers.d.ts +11 -0
- package/dist/gen_helpers.d.ts.map +1 -0
- package/dist/gen_helpers.js +76 -0
- package/dist/github.d.ts +19 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +33 -0
- package/dist/gro.config.default.d.ts +13 -0
- package/dist/gro.config.default.d.ts.map +1 -0
- package/dist/gro.config.default.js +33 -0
- package/dist/gro.d.ts +3 -0
- package/dist/gro.d.ts.map +1 -0
- package/dist/gro.js +21 -0
- package/dist/gro_config.d.ts +115 -0
- package/dist/gro_config.d.ts.map +1 -0
- package/dist/gro_config.js +114 -0
- package/dist/gro_helpers.d.ts +49 -0
- package/dist/gro_helpers.d.ts.map +1 -0
- package/dist/gro_helpers.js +97 -0
- package/dist/gro_plugin_gen.d.ts +12 -0
- package/dist/gro_plugin_gen.d.ts.map +1 -0
- package/dist/gro_plugin_gen.js +101 -0
- package/dist/gro_plugin_server.d.ts +80 -0
- package/dist/gro_plugin_server.d.ts.map +1 -0
- package/dist/gro_plugin_server.js +167 -0
- package/dist/gro_plugin_sveltekit_app.d.ts +9 -0
- package/dist/gro_plugin_sveltekit_app.d.ts.map +1 -0
- package/dist/gro_plugin_sveltekit_app.js +42 -0
- package/dist/gro_plugin_sveltekit_library.d.ts +16 -0
- package/dist/gro_plugin_sveltekit_library.d.ts.map +1 -0
- package/dist/gro_plugin_sveltekit_library.js +34 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/input_path.d.ts +64 -0
- package/dist/input_path.d.ts.map +1 -0
- package/dist/input_path.js +199 -0
- package/dist/invoke.d.ts +2 -0
- package/dist/invoke.d.ts.map +1 -0
- package/dist/invoke.js +28 -0
- package/dist/invoke_task.d.ts +30 -0
- package/dist/invoke_task.d.ts.map +1 -0
- package/dist/invoke_task.js +104 -0
- package/dist/lint.task.d.ts +11 -0
- package/dist/lint.task.d.ts.map +1 -0
- package/dist/lint.task.js +32 -0
- package/dist/loader.d.ts +6 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +192 -0
- package/dist/module.d.ts +4 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +6 -0
- package/dist/modules.d.ts +36 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +71 -0
- package/dist/package_json.d.ts +32 -0
- package/dist/package_json.d.ts.map +1 -0
- package/dist/package_json.js +178 -0
- package/dist/parse_exports.d.ts +20 -0
- package/dist/parse_exports.d.ts.map +1 -0
- package/dist/parse_exports.js +65 -0
- package/dist/parse_exports_context.d.ts +21 -0
- package/dist/parse_exports_context.d.ts.map +1 -0
- package/dist/parse_exports_context.js +332 -0
- package/dist/parse_imports.d.ts +5 -0
- package/dist/parse_imports.d.ts.map +1 -0
- package/dist/parse_imports.js +140 -0
- package/dist/paths.d.ts +41 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +69 -0
- package/dist/plugin.d.ts +36 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +78 -0
- package/dist/publish.task.d.ts +26 -0
- package/dist/publish.task.d.ts.map +1 -0
- package/dist/publish.task.js +176 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +2 -0
- package/dist/reinstall.task.d.ts +8 -0
- package/dist/reinstall.task.d.ts.map +1 -0
- package/dist/reinstall.task.js +35 -0
- package/dist/release.task.d.ts +8 -0
- package/dist/release.task.d.ts.map +1 -0
- package/dist/release.task.js +20 -0
- package/dist/resolve.task.d.ts +11 -0
- package/dist/resolve.task.d.ts.map +1 -0
- package/dist/resolve.task.js +38 -0
- package/dist/resolve_specifier.d.ts +22 -0
- package/dist/resolve_specifier.d.ts.map +1 -0
- package/dist/resolve_specifier.js +57 -0
- package/dist/run.task.d.ts +16 -0
- package/dist/run.task.d.ts.map +1 -0
- package/dist/run.task.js +52 -0
- package/dist/run_gen.d.ts +10 -0
- package/dist/run_gen.d.ts.map +1 -0
- package/dist/run_gen.js +73 -0
- package/dist/run_task.d.ts +17 -0
- package/dist/run_task.d.ts.map +1 -0
- package/dist/run_task.js +45 -0
- package/dist/source_json.d.ts +7 -0
- package/dist/source_json.d.ts.map +1 -0
- package/dist/source_json.js +145 -0
- package/dist/svelte_config.d.ts +57 -0
- package/dist/svelte_config.d.ts.map +1 -0
- package/dist/svelte_config.js +81 -0
- package/dist/sveltekit_helpers.d.ts +75 -0
- package/dist/sveltekit_helpers.d.ts.map +1 -0
- package/dist/sveltekit_helpers.js +94 -0
- package/dist/sveltekit_shim_app.d.ts +11 -0
- package/dist/sveltekit_shim_app.d.ts.map +1 -0
- package/dist/sveltekit_shim_app.js +31 -0
- package/dist/sveltekit_shim_app_environment.d.ts +13 -0
- package/dist/sveltekit_shim_app_environment.d.ts.map +1 -0
- package/dist/sveltekit_shim_app_environment.js +14 -0
- package/dist/sveltekit_shim_app_forms.d.ts +5 -0
- package/dist/sveltekit_shim_app_forms.d.ts.map +1 -0
- package/dist/sveltekit_shim_app_forms.js +6 -0
- package/dist/sveltekit_shim_app_navigation.d.ts +10 -0
- package/dist/sveltekit_shim_app_navigation.d.ts.map +1 -0
- package/dist/sveltekit_shim_app_navigation.js +11 -0
- package/dist/sveltekit_shim_app_paths.d.ts +17 -0
- package/dist/sveltekit_shim_app_paths.d.ts.map +1 -0
- package/dist/sveltekit_shim_app_paths.js +10 -0
- package/dist/sveltekit_shim_app_state.d.ts +5 -0
- package/dist/sveltekit_shim_app_state.d.ts.map +1 -0
- package/dist/sveltekit_shim_app_state.js +26 -0
- package/dist/sveltekit_shim_env.d.ts +5 -0
- package/dist/sveltekit_shim_env.d.ts.map +1 -0
- package/dist/sveltekit_shim_env.js +23 -0
- package/dist/sync.task.d.ts +16 -0
- package/dist/sync.task.d.ts.map +1 -0
- package/dist/sync.task.js +39 -0
- package/dist/task.d.ts +98 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +109 -0
- package/dist/task_logging.d.ts +6 -0
- package/dist/task_logging.d.ts.map +1 -0
- package/dist/task_logging.js +201 -0
- package/dist/test.task.d.ts +13 -0
- package/dist/test.task.d.ts.map +1 -0
- package/dist/test.task.js +53 -0
- package/dist/typecheck.task.d.ts +13 -0
- package/dist/typecheck.task.d.ts.map +1 -0
- package/dist/typecheck.task.js +68 -0
- package/dist/upgrade.task.d.ts +20 -0
- package/dist/upgrade.task.d.ts.map +1 -0
- package/dist/upgrade.task.js +111 -0
- package/dist/watch_dir.d.ts +36 -0
- package/dist/watch_dir.d.ts.map +1 -0
- package/dist/watch_dir.js +69 -0
- package/package.json +149 -0
- package/src/lib/args.ts +115 -0
- package/src/lib/build.task.ts +151 -0
- package/src/lib/build_cache.ts +378 -0
- package/src/lib/changelog.ts +69 -0
- package/src/lib/changeset.task.ts +228 -0
- package/src/lib/changeset_helpers.ts +14 -0
- package/src/lib/check.task.ts +132 -0
- package/src/lib/child_process_logging.ts +38 -0
- package/src/lib/clean.task.ts +48 -0
- package/src/lib/clean_fs.ts +54 -0
- package/src/lib/cli.ts +98 -0
- package/src/lib/commit.task.ts +34 -0
- package/src/lib/constants.ts +56 -0
- package/src/lib/deploy.task.ts +287 -0
- package/src/lib/dev.task.ts +52 -0
- package/src/lib/disknode.ts +26 -0
- package/src/lib/env.ts +78 -0
- package/src/lib/esbuild_helpers.ts +49 -0
- package/src/lib/esbuild_plugin_external_worker.ts +94 -0
- package/src/lib/esbuild_plugin_svelte.ts +134 -0
- package/src/lib/esbuild_plugin_sveltekit_local_imports.ts +38 -0
- package/src/lib/esbuild_plugin_sveltekit_shim_alias.ts +27 -0
- package/src/lib/esbuild_plugin_sveltekit_shim_app.ts +42 -0
- package/src/lib/esbuild_plugin_sveltekit_shim_env.ts +47 -0
- package/src/lib/filer.ts +458 -0
- package/src/lib/format.task.ts +44 -0
- package/src/lib/format_directory.ts +65 -0
- package/src/lib/format_file.ts +49 -0
- package/src/lib/gen.task.ts +206 -0
- package/src/lib/gen.ts +406 -0
- package/src/lib/gen_helpers.ts +131 -0
- package/src/lib/github.ts +46 -0
- package/src/lib/gro.config.default.ts +42 -0
- package/src/lib/gro.ts +29 -0
- package/src/lib/gro_config.ts +254 -0
- package/src/lib/gro_helpers.ts +108 -0
- package/src/lib/gro_plugin_gen.ts +149 -0
- package/src/lib/gro_plugin_server.ts +288 -0
- package/src/lib/gro_plugin_sveltekit_app.ts +58 -0
- package/src/lib/gro_plugin_sveltekit_library.ts +63 -0
- package/src/lib/index.ts +8 -0
- package/src/lib/input_path.ts +254 -0
- package/src/lib/invoke.ts +34 -0
- package/src/lib/invoke_task.ts +139 -0
- package/src/lib/lint.task.ts +39 -0
- package/src/lib/loader.ts +229 -0
- package/src/lib/module.ts +13 -0
- package/src/lib/modules.ts +117 -0
- package/src/lib/package_json.ts +255 -0
- package/src/lib/parse_exports.ts +100 -0
- package/src/lib/parse_exports_context.ts +395 -0
- package/src/lib/parse_imports.ts +180 -0
- package/src/lib/paths.ts +111 -0
- package/src/lib/plugin.ts +106 -0
- package/src/lib/publish.task.ts +228 -0
- package/src/lib/register.ts +3 -0
- package/src/lib/reinstall.task.ts +45 -0
- package/src/lib/release.task.ts +26 -0
- package/src/lib/resolve.task.ts +43 -0
- package/src/lib/resolve_specifier.ts +81 -0
- package/src/lib/run.task.ts +65 -0
- package/src/lib/run_gen.ts +110 -0
- package/src/lib/run_task.ts +82 -0
- package/src/lib/source_json.ts +183 -0
- package/src/lib/svelte_config.ts +140 -0
- package/src/lib/sveltekit_helpers.ts +193 -0
- package/src/lib/sveltekit_shim_app.ts +41 -0
- package/src/lib/sveltekit_shim_app_environment.ts +16 -0
- package/src/lib/sveltekit_shim_app_forms.ts +13 -0
- package/src/lib/sveltekit_shim_app_navigation.ts +23 -0
- package/src/lib/sveltekit_shim_app_paths.ts +26 -0
- package/src/lib/sveltekit_shim_app_state.ts +35 -0
- package/src/lib/sveltekit_shim_env.ts +45 -0
- package/src/lib/sync.task.ts +47 -0
- package/src/lib/task.ts +245 -0
- package/src/lib/task_logging.ts +255 -0
- package/src/lib/test.task.ts +63 -0
- package/src/lib/typecheck.task.ts +81 -0
- package/src/lib/upgrade.task.ts +148 -0
- package/src/lib/watch_dir.ts +115 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { resolve_specifier } from "./resolve_specifier.js";
|
|
4
|
+
import { EVERYTHING_MATCHER } from "./constants.js";
|
|
5
|
+
/**
|
|
6
|
+
* Adds support for imports to both `.ts` and `.js`,
|
|
7
|
+
* as well as imports without extensions that resolve to `.js` or `.ts`.
|
|
8
|
+
* Prefers `.ts` over any `.js`, and falls back to `.ts` if no file is found.
|
|
9
|
+
*/
|
|
10
|
+
export const esbuild_plugin_sveltekit_local_imports = () => ({
|
|
11
|
+
name: 'sveltekit_local_imports',
|
|
12
|
+
setup: (build) => {
|
|
13
|
+
build.onResolve({ filter: /^(\/|\.)/ }, async (args) => {
|
|
14
|
+
const { path, importer } = args;
|
|
15
|
+
if (!importer)
|
|
16
|
+
return { path };
|
|
17
|
+
const { path_id, namespace } = await resolve_specifier(path, dirname(importer));
|
|
18
|
+
return { path: path_id, namespace }; // `namespace` may be `undefined`, but esbuild needs the absolute path for json etc
|
|
19
|
+
});
|
|
20
|
+
build.onLoad({ filter: EVERYTHING_MATCHER, namespace: 'sveltekit_local_imports_ts' }, async ({ path }) => ({
|
|
21
|
+
contents: await readFile(path),
|
|
22
|
+
loader: 'ts',
|
|
23
|
+
resolveDir: dirname(path),
|
|
24
|
+
}));
|
|
25
|
+
build.onLoad({ filter: EVERYTHING_MATCHER, namespace: 'sveltekit_local_imports_js' }, async ({ path }) => ({
|
|
26
|
+
contents: await readFile(path),
|
|
27
|
+
resolveDir: dirname(path),
|
|
28
|
+
}));
|
|
29
|
+
},
|
|
30
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type * as esbuild from 'esbuild';
|
|
2
|
+
export interface EsbuildPluginSveltekitShimAliasOptions {
|
|
3
|
+
dir?: string;
|
|
4
|
+
alias?: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
export declare const esbuild_plugin_sveltekit_shim_alias: ({ dir, alias, }: EsbuildPluginSveltekitShimAliasOptions) => esbuild.Plugin;
|
|
7
|
+
//# sourceMappingURL=esbuild_plugin_sveltekit_shim_alias.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esbuild_plugin_sveltekit_shim_alias.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/esbuild_plugin_sveltekit_shim_alias.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,CAAC;AAIxC,MAAM,WAAW,sCAAsC;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,eAAO,MAAM,mCAAmC,GAAI,iBAGjD,sCAAsC,KAAG,OAAO,CAAC,MAclD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { escape_regexp } from '@fuzdev/fuz_util/regexp.js';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const esbuild_plugin_sveltekit_shim_alias = ({ dir = process.cwd(), alias, }) => ({
|
|
4
|
+
name: 'sveltekit_shim_alias',
|
|
5
|
+
setup: (build) => {
|
|
6
|
+
const aliases = { $lib: 'src/lib', ...alias };
|
|
7
|
+
// Create a Go-compatible regexp
|
|
8
|
+
const filter = new RegExp(`^(?:${Object.keys(aliases).map(escape_regexp).join('|')})`);
|
|
9
|
+
build.onResolve({ filter }, async (args) => {
|
|
10
|
+
const { path, ...rest } = args;
|
|
11
|
+
// Find which alias prefix matches
|
|
12
|
+
const prefix = Object.keys(aliases).find((key) => path.startsWith(key));
|
|
13
|
+
if (!prefix)
|
|
14
|
+
return null;
|
|
15
|
+
return build.resolve(join(dir, aliases[prefix] + path.substring(prefix.length)), rest);
|
|
16
|
+
});
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type * as esbuild from 'esbuild';
|
|
2
|
+
import type { ParsedSvelteConfig } from './svelte_config.ts';
|
|
3
|
+
export interface EsbuildPluginSveltekitShimAppOptions {
|
|
4
|
+
dev: boolean;
|
|
5
|
+
base_url: ParsedSvelteConfig['base_url'];
|
|
6
|
+
assets_url: ParsedSvelteConfig['assets_url'];
|
|
7
|
+
}
|
|
8
|
+
export declare const esbuild_plugin_sveltekit_shim_app: ({ dev, base_url, assets_url, }: EsbuildPluginSveltekitShimAppOptions) => esbuild.Plugin;
|
|
9
|
+
//# sourceMappingURL=esbuild_plugin_sveltekit_shim_app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esbuild_plugin_sveltekit_shim_app.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/esbuild_plugin_sveltekit_shim_app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,CAAC;AAOxC,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AAG3D,MAAM,WAAW,oCAAoC;IACpD,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACzC,UAAU,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;CAC7C;AAED,eAAO,MAAM,iCAAiC,GAAI,gCAI/C,oCAAoC,KAAG,OAAO,CAAC,MAqBhD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { render_sveltekit_shim_app_environment, render_sveltekit_shim_app_paths, sveltekit_shim_app_specifiers, } from "./sveltekit_shim_app.js";
|
|
2
|
+
import { EVERYTHING_MATCHER } from "./constants.js";
|
|
3
|
+
export const esbuild_plugin_sveltekit_shim_app = ({ dev, base_url, assets_url, }) => ({
|
|
4
|
+
name: 'sveltekit_shim_app',
|
|
5
|
+
setup: (build) => {
|
|
6
|
+
build.onResolve({ filter: /^\$app\/(forms|navigation|stores)$/ }, ({ path, ...rest }) => build.resolve(sveltekit_shim_app_specifiers.get(path), rest));
|
|
7
|
+
build.onResolve({ filter: /^\$app\/paths$/ }, ({ path }) => ({
|
|
8
|
+
path: sveltekit_shim_app_specifiers.get(path),
|
|
9
|
+
namespace: 'sveltekit_shim_app_paths',
|
|
10
|
+
}));
|
|
11
|
+
build.onLoad({ filter: EVERYTHING_MATCHER, namespace: 'sveltekit_shim_app_paths' }, () => ({
|
|
12
|
+
contents: render_sveltekit_shim_app_paths(base_url, assets_url),
|
|
13
|
+
}));
|
|
14
|
+
build.onResolve({ filter: /^\$app\/environment$/ }, ({ path }) => ({
|
|
15
|
+
path: sveltekit_shim_app_specifiers.get(path),
|
|
16
|
+
namespace: 'sveltekit_shim_app_environment',
|
|
17
|
+
}));
|
|
18
|
+
build.onLoad({ filter: EVERYTHING_MATCHER, namespace: 'sveltekit_shim_app_environment' }, () => ({
|
|
19
|
+
contents: render_sveltekit_shim_app_environment(dev),
|
|
20
|
+
}));
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as esbuild from 'esbuild';
|
|
2
|
+
export interface EsbuildPluginSveltekitShimEnvOptions {
|
|
3
|
+
dev: boolean;
|
|
4
|
+
public_prefix?: string;
|
|
5
|
+
private_prefix?: string;
|
|
6
|
+
env_dir?: string;
|
|
7
|
+
env_files?: Array<string>;
|
|
8
|
+
ambient_env?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export declare const esbuild_plugin_sveltekit_shim_env: ({ dev, public_prefix, private_prefix, env_dir, env_files, ambient_env, }: EsbuildPluginSveltekitShimEnvOptions) => esbuild.Plugin;
|
|
11
|
+
//# sourceMappingURL=esbuild_plugin_sveltekit_shim_env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esbuild_plugin_sveltekit_shim_env.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/esbuild_plugin_sveltekit_shim_env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,CAAC;AAKxC,MAAM,WAAW,oCAAoC;IACpD,GAAG,EAAE,OAAO,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAID,eAAO,MAAM,iCAAiC,GAAI,0EAO/C,oCAAoC,KAAG,OAAO,CAAC,MAuBhD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { render_env_shim_module } from "./sveltekit_shim_env.js";
|
|
2
|
+
import { SVELTEKIT_ENV_MATCHER, EVERYTHING_MATCHER } from "./constants.js";
|
|
3
|
+
const namespace = 'sveltekit_shim_env';
|
|
4
|
+
export const esbuild_plugin_sveltekit_shim_env = ({ dev, public_prefix, private_prefix, env_dir, env_files, ambient_env, }) => ({
|
|
5
|
+
name: 'sveltekit_shim_env',
|
|
6
|
+
setup: (build) => {
|
|
7
|
+
build.onResolve({ filter: SVELTEKIT_ENV_MATCHER }, ({ path }) => ({ path, namespace }));
|
|
8
|
+
build.onLoad({ filter: EVERYTHING_MATCHER, namespace }, ({ path }) => {
|
|
9
|
+
const matches = SVELTEKIT_ENV_MATCHER.exec(path);
|
|
10
|
+
const mode = matches[1];
|
|
11
|
+
const visibility = matches[2];
|
|
12
|
+
return {
|
|
13
|
+
loader: 'ts',
|
|
14
|
+
contents: render_env_shim_module(dev, mode, visibility, public_prefix, private_prefix, env_dir, env_files, ambient_env),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
},
|
|
18
|
+
});
|
package/dist/filer.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { OmitStrict } from '@fuzdev/fuz_util/types.js';
|
|
2
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
3
|
+
import type { PackageJson } from '@fuzdev/fuz_util/package_json.js';
|
|
4
|
+
import type { FileFilter, PathId } from '@fuzdev/fuz_util/path.js';
|
|
5
|
+
import { watch_dir, type WatcherChange, type WatchDirOptions } from './watch_dir.ts';
|
|
6
|
+
import type { Disknode } from './disknode.ts';
|
|
7
|
+
export type OnFilerChange = (change: WatcherChange, disknode: Disknode) => void;
|
|
8
|
+
export interface FilerOptions {
|
|
9
|
+
watch_dir?: typeof watch_dir;
|
|
10
|
+
watch_dir_options?: Partial<OmitStrict<WatchDirOptions, 'on_change'>>;
|
|
11
|
+
package_json_cache?: Record<string, PackageJson>;
|
|
12
|
+
log?: Logger;
|
|
13
|
+
}
|
|
14
|
+
export declare class Filer {
|
|
15
|
+
#private;
|
|
16
|
+
readonly root_dir: PathId;
|
|
17
|
+
readonly files: Map<PathId, Disknode>;
|
|
18
|
+
constructor(options?: FilerOptions);
|
|
19
|
+
get inited(): boolean;
|
|
20
|
+
get_by_id: (id: PathId) => Disknode | undefined;
|
|
21
|
+
get_or_create: (id: PathId) => Disknode;
|
|
22
|
+
filter(predicate: (disknode: Disknode) => boolean): Array<Disknode> | null;
|
|
23
|
+
/**
|
|
24
|
+
* Initialize the filer to populate files without watching.
|
|
25
|
+
* Safe to call multiple times - subsequent calls are no-ops.
|
|
26
|
+
* Used by gen files to access the file graph.
|
|
27
|
+
*/
|
|
28
|
+
init(): Promise<void>;
|
|
29
|
+
watch(listener: OnFilerChange): Promise<() => void>;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export declare const filter_dependents: (disknode: Disknode, get_by_id: (id: PathId) => Disknode | undefined, filter?: FileFilter, results?: Set<PathId>, searched?: Set<PathId>, log?: Logger) => Set<PathId>;
|
|
33
|
+
//# sourceMappingURL=filer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filer.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/filer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2BAA2B,CAAC;AAI1D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAC,UAAU,EAAE,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAGjE,OAAO,EACN,SAAS,EAET,KAAK,aAAa,EAClB,KAAK,eAAe,EAEpB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAI5C,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,KAAK;;IACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAG1B,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;gBAetC,OAAO,GAAE,YAA2B;IAUhD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,SAAS,GAAI,IAAI,MAAM,KAAG,QAAQ,GAAG,SAAS,CAE5C;IAEF,aAAa,GAAI,IAAI,MAAM,KAAG,QAAQ,CAqBpC;IAEF,MAAM,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI;IAU1E;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsDrB,KAAK,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAmBzD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA8OtB;AAGD,eAAO,MAAM,iBAAiB,GAC7B,UAAU,QAAQ,EAClB,WAAW,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,EAC/C,SAAS,UAAU,EACnB,UAAS,GAAG,CAAC,MAAM,CAAa,EAChC,WAAU,GAAG,CAAC,MAAM,CAAa,EACjC,MAAM,MAAM,KACV,GAAG,CAAC,MAAM,CAuBZ,CAAC"}
|
package/dist/filer.js
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { EMPTY_OBJECT } from '@fuzdev/fuz_util/object.js';
|
|
2
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { isBuiltin } from 'node:module';
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
|
+
import { UnreachableError } from '@fuzdev/fuz_util/error.js';
|
|
7
|
+
import { hash_secure } from '@fuzdev/fuz_util/hash.js';
|
|
8
|
+
import { watch_dir, } from "./watch_dir.js";
|
|
9
|
+
import { paths } from "./paths.js";
|
|
10
|
+
import { parse_imports } from "./parse_imports.js";
|
|
11
|
+
import { resolve_specifier } from "./resolve_specifier.js";
|
|
12
|
+
import { default_svelte_config } from "./svelte_config.js";
|
|
13
|
+
import { map_sveltekit_aliases } from "./sveltekit_helpers.js";
|
|
14
|
+
import { SVELTEKIT_GLOBAL_SPECIFIER } from "./constants.js";
|
|
15
|
+
const aliases = Object.entries(default_svelte_config.alias);
|
|
16
|
+
export class Filer {
|
|
17
|
+
root_dir;
|
|
18
|
+
// TODO rename everything to `disknode`
|
|
19
|
+
files = new Map();
|
|
20
|
+
#watch_dir;
|
|
21
|
+
#watch_dir_options;
|
|
22
|
+
#log;
|
|
23
|
+
#listeners = new Set();
|
|
24
|
+
#watching;
|
|
25
|
+
#initing;
|
|
26
|
+
#closing;
|
|
27
|
+
#change_queue = [];
|
|
28
|
+
#processing_promise = null;
|
|
29
|
+
constructor(options = EMPTY_OBJECT) {
|
|
30
|
+
this.#watch_dir = options.watch_dir ?? watch_dir;
|
|
31
|
+
this.#watch_dir_options = options.watch_dir_options ?? EMPTY_OBJECT;
|
|
32
|
+
this.root_dir = resolve(options.watch_dir_options?.dir ?? paths.source);
|
|
33
|
+
// TODO for package.json maybe another array of files/dirs to watch to invalidate everything?
|
|
34
|
+
// or instead of that, think of taking an array of config objects that can specify invalidation rules,
|
|
35
|
+
// so package.json would be configured differently than ./src, and we could add a default with
|
|
36
|
+
// package.json/gro.config.ts/tsconfig.json/svelte.config.js/vite.config.ts to invalidate everything
|
|
37
|
+
this.#log = options.log;
|
|
38
|
+
}
|
|
39
|
+
get inited() {
|
|
40
|
+
return this.#watching !== undefined;
|
|
41
|
+
}
|
|
42
|
+
get_by_id = (id) => {
|
|
43
|
+
return this.files.get(id);
|
|
44
|
+
};
|
|
45
|
+
get_or_create = (id) => {
|
|
46
|
+
const existing = this.get_by_id(id);
|
|
47
|
+
if (existing)
|
|
48
|
+
return existing;
|
|
49
|
+
const file = {
|
|
50
|
+
id,
|
|
51
|
+
contents: null,
|
|
52
|
+
external: this.#is_external(id), // TODO maybe filter externals by default? the user needs to configure the filer then
|
|
53
|
+
ctime: null,
|
|
54
|
+
mtime: null,
|
|
55
|
+
content_hash: null,
|
|
56
|
+
dependents: new Map(),
|
|
57
|
+
dependencies: new Map(),
|
|
58
|
+
};
|
|
59
|
+
this.files.set(id, file);
|
|
60
|
+
// Defer external file change notification to avoid reentrancy during queue processing
|
|
61
|
+
if (file.external) {
|
|
62
|
+
queueMicrotask(() => {
|
|
63
|
+
this.#on_change({ type: 'add', path: file.id, is_directory: false });
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return file;
|
|
67
|
+
};
|
|
68
|
+
filter(predicate) {
|
|
69
|
+
let found = null;
|
|
70
|
+
for (const disknode of this.files.values()) {
|
|
71
|
+
if (predicate(disknode)) {
|
|
72
|
+
(found ??= []).push(disknode);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return found;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Initialize the filer to populate files without watching.
|
|
79
|
+
* Safe to call multiple times - subsequent calls are no-ops.
|
|
80
|
+
* Used by gen files to access the file graph.
|
|
81
|
+
*/
|
|
82
|
+
async init() {
|
|
83
|
+
// if already initing, return the existing promise
|
|
84
|
+
if (this.#initing)
|
|
85
|
+
return this.#initing;
|
|
86
|
+
// if already initialized, just ensure ready
|
|
87
|
+
if (this.#watching) {
|
|
88
|
+
return this.#watching.init();
|
|
89
|
+
}
|
|
90
|
+
// start new initialization
|
|
91
|
+
this.#initing = this.#init();
|
|
92
|
+
try {
|
|
93
|
+
await this.#initing;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
// use shared cleanup logic
|
|
97
|
+
this.#cleanup();
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
this.#initing = undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async #init() {
|
|
105
|
+
const watcher = this.#watch_dir({
|
|
106
|
+
...this.#watch_dir_options,
|
|
107
|
+
dir: this.root_dir,
|
|
108
|
+
on_change: this.#on_change,
|
|
109
|
+
});
|
|
110
|
+
try {
|
|
111
|
+
await watcher.init();
|
|
112
|
+
// Wait for any queued changes from init to be processed
|
|
113
|
+
await this.#drain_queue();
|
|
114
|
+
// check if close() was called during init
|
|
115
|
+
if (this.#closing) {
|
|
116
|
+
await watcher.close();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// only set after successful init and not closing
|
|
120
|
+
this.#watching = watcher;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
// clean up watcher on error, but don't let close error mask init error
|
|
124
|
+
try {
|
|
125
|
+
await watcher.close();
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// ignore close errors - init error is more important
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async watch(listener) {
|
|
134
|
+
await this.#add_listener(listener);
|
|
135
|
+
return () => {
|
|
136
|
+
this.#remove_listener(listener);
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Internal cleanup of all state - can be called safely from anywhere
|
|
141
|
+
*/
|
|
142
|
+
#cleanup() {
|
|
143
|
+
this.#listeners.clear();
|
|
144
|
+
this.files.clear();
|
|
145
|
+
this.#watching = undefined;
|
|
146
|
+
this.#change_queue = [];
|
|
147
|
+
this.#processing_promise = null;
|
|
148
|
+
// #initing is handled in finally block of init()
|
|
149
|
+
}
|
|
150
|
+
close() {
|
|
151
|
+
// if already closing, return existing promise
|
|
152
|
+
if (this.#closing)
|
|
153
|
+
return this.#closing;
|
|
154
|
+
// if already closed and not initing, nothing to do
|
|
155
|
+
if (!this.#watching && !this.#initing)
|
|
156
|
+
return Promise.resolve();
|
|
157
|
+
// start new close operation
|
|
158
|
+
const closing = this.#close();
|
|
159
|
+
this.#closing = closing;
|
|
160
|
+
// Clean up after completion, but don't change the returned promise
|
|
161
|
+
// Use void to ensure we don't accidentally return the .then() promise
|
|
162
|
+
void closing.then(() => {
|
|
163
|
+
this.#closing = undefined;
|
|
164
|
+
}, () => {
|
|
165
|
+
this.#closing = undefined;
|
|
166
|
+
});
|
|
167
|
+
return this.#closing;
|
|
168
|
+
}
|
|
169
|
+
async #close() {
|
|
170
|
+
// wait for any pending initialization to complete
|
|
171
|
+
if (this.#initing) {
|
|
172
|
+
try {
|
|
173
|
+
await this.#initing;
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// ignore errors during close
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// close watcher if it exists
|
|
180
|
+
if (this.#watching) {
|
|
181
|
+
await this.#watching.close();
|
|
182
|
+
}
|
|
183
|
+
// clean up all state
|
|
184
|
+
this.#cleanup();
|
|
185
|
+
}
|
|
186
|
+
async #update(id) {
|
|
187
|
+
const file = this.get_or_create(id);
|
|
188
|
+
let stats = null;
|
|
189
|
+
let new_contents = null; // TODO need to lazily load contents, probably turn `Disknode` into a class
|
|
190
|
+
try {
|
|
191
|
+
[stats, new_contents] = await Promise.all([stat(id), readFile(id, 'utf8')]);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
const code = error.code;
|
|
195
|
+
// Treat file as deleted/inaccessible for common error codes
|
|
196
|
+
if (code === 'ENOENT' || code === 'EACCES' || code === 'EPERM') {
|
|
197
|
+
// File doesn't exist or is inaccessible, treat as deleted
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Compute hash for new contents
|
|
204
|
+
const new_hash = new_contents !== null ? await hash_secure(new_contents) : null;
|
|
205
|
+
file.ctime = stats?.ctimeMs ?? null;
|
|
206
|
+
file.mtime = stats?.mtimeMs ?? null;
|
|
207
|
+
// Use hash comparison for change detection (content-based, not mtime-based)
|
|
208
|
+
if (file.content_hash === new_hash) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
file.contents = new_contents;
|
|
212
|
+
file.content_hash = new_hash;
|
|
213
|
+
const dir = dirname(file.id);
|
|
214
|
+
const dependencies_before = new Set(file.dependencies.keys());
|
|
215
|
+
const dependencies_removed = new Set(dependencies_before);
|
|
216
|
+
let imported = [];
|
|
217
|
+
if (file.contents) {
|
|
218
|
+
try {
|
|
219
|
+
imported = parse_imports(file.id, file.contents);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
this.#log?.error('[filer] Failed to parse imports', file.id, error);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
for (const specifier of imported) {
|
|
226
|
+
if (SVELTEKIT_GLOBAL_SPECIFIER.test(specifier))
|
|
227
|
+
continue;
|
|
228
|
+
const path = map_sveltekit_aliases(specifier, aliases);
|
|
229
|
+
let path_id;
|
|
230
|
+
// TODO can we replace `resolve_specifier` with `import.meta.resolve` completely now outside of esbuild plugins?
|
|
231
|
+
if (path[0] === '.' || path[0] === '/') {
|
|
232
|
+
const resolved = await resolve_specifier(path, dir); // eslint-disable-line no-await-in-loop
|
|
233
|
+
path_id = resolved.path_id;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
if (isBuiltin(path))
|
|
237
|
+
continue;
|
|
238
|
+
const file_url = pathToFileURL(file.id);
|
|
239
|
+
try {
|
|
240
|
+
path_id = fileURLToPath(import.meta.resolve(path, file_url.href));
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
// if resolving fails for any reason, just log and ignore it
|
|
244
|
+
this.#log?.error('[filer] failed to resolve path', path, file_url.href, error);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
dependencies_removed.delete(path_id);
|
|
249
|
+
if (!dependencies_before.has(path_id)) {
|
|
250
|
+
const d = this.get_or_create(path_id);
|
|
251
|
+
file.dependencies.set(d.id, d);
|
|
252
|
+
d.dependents.set(file.id, file);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// update any removed dependencies
|
|
256
|
+
for (const dependency_removed of dependencies_removed) {
|
|
257
|
+
file.dependencies.delete(dependency_removed);
|
|
258
|
+
const dependency_removed_file = this.get_or_create(dependency_removed);
|
|
259
|
+
dependency_removed_file.dependents.delete(file.id);
|
|
260
|
+
}
|
|
261
|
+
return file;
|
|
262
|
+
}
|
|
263
|
+
#remove(id) {
|
|
264
|
+
const file = this.get_by_id(id);
|
|
265
|
+
if (!file)
|
|
266
|
+
return null; // this is safe because the object would exist if any other file referenced it as a dependency or dependent
|
|
267
|
+
file.contents = null; // clear contents in case it gets re-added later, we want the change to be detected
|
|
268
|
+
file.content_hash = null; // clear hash so re-add detects the change
|
|
269
|
+
file.dependencies.clear();
|
|
270
|
+
// keep the file in memory if other files still depend on it
|
|
271
|
+
if (file.dependents.size === 0) {
|
|
272
|
+
this.files.delete(id);
|
|
273
|
+
}
|
|
274
|
+
return file;
|
|
275
|
+
}
|
|
276
|
+
#sync_listener_with_files(listener) {
|
|
277
|
+
for (const disknode of this.files.values()) {
|
|
278
|
+
try {
|
|
279
|
+
listener({ type: 'add', path: disknode.id, is_directory: false }, disknode);
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
this.#log?.error('[filer] Listener error during sync:', error);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
#notify_change(change, disknode) {
|
|
287
|
+
for (const listener of this.#listeners) {
|
|
288
|
+
try {
|
|
289
|
+
listener(change, disknode);
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
this.#log?.error('[filer] Listener error during change notification:', error);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async #add_listener(listener) {
|
|
297
|
+
this.#listeners.add(listener);
|
|
298
|
+
// ensure initialized
|
|
299
|
+
await this.init();
|
|
300
|
+
// notify of existing files
|
|
301
|
+
this.#sync_listener_with_files(listener);
|
|
302
|
+
}
|
|
303
|
+
#remove_listener(listener) {
|
|
304
|
+
this.#listeners.delete(listener);
|
|
305
|
+
// keep watching active even with no listeners, only close() tears down
|
|
306
|
+
}
|
|
307
|
+
async #drain_queue() {
|
|
308
|
+
// Wait for queue to be empty and no active processing
|
|
309
|
+
while (this.#change_queue.length > 0 || this.#processing_promise) {
|
|
310
|
+
await this.#process_queue(); // eslint-disable-line no-await-in-loop
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async #process_queue() {
|
|
314
|
+
// If already processing, return the existing promise
|
|
315
|
+
if (this.#processing_promise)
|
|
316
|
+
return this.#processing_promise;
|
|
317
|
+
// Create and track the processing promise
|
|
318
|
+
this.#processing_promise = this.#do_process_queue();
|
|
319
|
+
try {
|
|
320
|
+
await this.#processing_promise;
|
|
321
|
+
}
|
|
322
|
+
finally {
|
|
323
|
+
this.#processing_promise = null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async #do_process_queue() {
|
|
327
|
+
while (this.#change_queue.length > 0) {
|
|
328
|
+
const change = this.#change_queue.shift();
|
|
329
|
+
if (this.#closing)
|
|
330
|
+
continue; // ignore changes during close
|
|
331
|
+
if (change.is_directory)
|
|
332
|
+
continue; // TODO manage directories?
|
|
333
|
+
let disknode;
|
|
334
|
+
switch (change.type) {
|
|
335
|
+
case 'add':
|
|
336
|
+
case 'update': {
|
|
337
|
+
disknode = await this.#update(change.path); // eslint-disable-line no-await-in-loop
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case 'delete': {
|
|
341
|
+
disknode = this.#remove(change.path);
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
default:
|
|
345
|
+
throw new UnreachableError(change.type);
|
|
346
|
+
}
|
|
347
|
+
if (disknode && this.#listeners.size > 0) {
|
|
348
|
+
this.#notify_change(change, disknode);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
#on_change = (change) => {
|
|
353
|
+
// Enqueue the change (sync callback from chokidar)
|
|
354
|
+
this.#change_queue.push(change);
|
|
355
|
+
// Start processing if not already running
|
|
356
|
+
void this.#process_queue();
|
|
357
|
+
};
|
|
358
|
+
#is_external(id) {
|
|
359
|
+
const { filter } = this.#watch_dir_options;
|
|
360
|
+
return !id.startsWith(this.root_dir + '/') || (!!filter && !filter(id, false));
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// TODO maybe `Disknode` class?
|
|
364
|
+
export const filter_dependents = (disknode, get_by_id, filter, results = new Set(), searched = new Set(), log) => {
|
|
365
|
+
// Use iterative approach to avoid stack overflow on deep dependency trees
|
|
366
|
+
const stack = [disknode];
|
|
367
|
+
while (stack.length > 0) {
|
|
368
|
+
const current = stack.pop();
|
|
369
|
+
for (const dependent_id of current.dependents.keys()) {
|
|
370
|
+
if (searched.has(dependent_id))
|
|
371
|
+
continue;
|
|
372
|
+
searched.add(dependent_id);
|
|
373
|
+
if (!filter || filter(dependent_id)) {
|
|
374
|
+
results.add(dependent_id);
|
|
375
|
+
}
|
|
376
|
+
const dependent_disknode = get_by_id(dependent_id);
|
|
377
|
+
if (!dependent_disknode) {
|
|
378
|
+
log?.warn(`[filer.filter_dependents] dependent source file ${dependent_id} not found for ${current.id}`);
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
stack.push(dependent_disknode);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return results;
|
|
385
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type Task } from './task.ts';
|
|
3
|
+
/** @nodocs */
|
|
4
|
+
export declare const Args: z.ZodObject<{
|
|
5
|
+
_: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
6
|
+
check: z.ZodDefault<z.ZodBoolean>;
|
|
7
|
+
}, z.core.$strict>;
|
|
8
|
+
export type Args = z.infer<typeof Args>;
|
|
9
|
+
/** @nodocs */
|
|
10
|
+
export declare const task: Task<Args>;
|
|
11
|
+
//# sourceMappingURL=format.task.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/format.task.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAMtB,OAAO,EAAY,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAE/C,cAAc;AACd,eAAO,MAAM,IAAI;;;kBAMf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,cAAc;AACd,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CAuB3B,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { print_spawn_result } from '@fuzdev/fuz_util/process.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { to_implicit_forwarded_args } from "./args.js";
|
|
4
|
+
import { PRETTIER_CLI_DEFAULT } from "./constants.js";
|
|
5
|
+
import { format_directory } from "./format_directory.js";
|
|
6
|
+
import { paths } from "./paths.js";
|
|
7
|
+
import { TaskError } from "./task.js";
|
|
8
|
+
/** @nodocs */
|
|
9
|
+
export const Args = z.strictObject({
|
|
10
|
+
_: z.array(z.string()).meta({ description: 'files or directories to format' }).optional(),
|
|
11
|
+
check: z
|
|
12
|
+
.boolean()
|
|
13
|
+
.meta({ description: 'exit with a nonzero code if any files are unformatted' })
|
|
14
|
+
.default(false),
|
|
15
|
+
});
|
|
16
|
+
/** @nodocs */
|
|
17
|
+
export const task = {
|
|
18
|
+
summary: 'format source files',
|
|
19
|
+
Args,
|
|
20
|
+
run: async ({ args, log, config }) => {
|
|
21
|
+
const { _: patterns, check } = args;
|
|
22
|
+
const format_result = await format_directory(log, paths.source, check, undefined, undefined, undefined, config.pm_cli, to_implicit_forwarded_args(PRETTIER_CLI_DEFAULT), patterns);
|
|
23
|
+
if (!format_result.ok) {
|
|
24
|
+
throw new TaskError(`Failed ${check ? 'formatting check' : 'to format'}. ${print_spawn_result(format_result)}`);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Args } from '@fuzdev/fuz_util/args.js';
|
|
2
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
3
|
+
import type { SpawnResult } from '@fuzdev/fuz_util/process.js';
|
|
4
|
+
import { type Cli } from './cli.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Formats files on the filesystem.
|
|
7
|
+
* When `patterns` is provided, formats those specific files/patterns.
|
|
8
|
+
* Otherwise formats `dir` with default extensions, plus root files if `dir` is `paths.source`.
|
|
9
|
+
* This is separated from `./format_file` to avoid importing all of the `prettier` code
|
|
10
|
+
* inside modules that import this one. (which has a nontrivial cost)
|
|
11
|
+
*/
|
|
12
|
+
export declare const format_directory: (log: Logger, dir: string, check?: boolean, extensions?: string, root_paths?: string, prettier_cli?: string | Cli, pm_cli?: string, additional_args?: Args, patterns?: Array<string>) => Promise<SpawnResult>;
|
|
13
|
+
//# sourceMappingURL=format_directory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format_directory.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/format_directory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,IAAI,EAAC,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAyB,KAAK,GAAG,EAAC,MAAM,UAAU,CAAC;AAuB1D;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC5B,KAAK,MAAM,EACX,KAAK,MAAM,EACX,eAAa,EACb,mBAA+B,EAC/B,mBAA+B,EAC/B,eAAc,MAAM,GAAG,GAA0B,EACjD,SAAQ,MAAuB,EAC/B,kBAAkB,IAAI,EACtB,WAAW,KAAK,CAAC,MAAM,CAAC,KACtB,OAAO,CAAC,WAAW,CAoBrB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { args_serialize } from '@fuzdev/fuz_util/args.js';
|
|
2
|
+
import { spawn_cli, to_cli_name } from "./cli.js";
|
|
3
|
+
import { GITHUB_DIRNAME, README_FILENAME, SVELTE_CONFIG_FILENAME, VITE_CONFIG_FILENAME, TSCONFIG_FILENAME, GRO_CONFIG_FILENAME, PM_CLI_DEFAULT, PRETTIER_CLI_DEFAULT, } from "./constants.js";
|
|
4
|
+
import { paths } from "./paths.js";
|
|
5
|
+
const EXTENSIONS_DEFAULT = 'ts,js,json,svelte,html,css,md,yml';
|
|
6
|
+
const ROOT_PATHS_DEFAULT = `${[
|
|
7
|
+
README_FILENAME,
|
|
8
|
+
GRO_CONFIG_FILENAME,
|
|
9
|
+
SVELTE_CONFIG_FILENAME,
|
|
10
|
+
VITE_CONFIG_FILENAME,
|
|
11
|
+
TSCONFIG_FILENAME,
|
|
12
|
+
GITHUB_DIRNAME,
|
|
13
|
+
].join(',')}/**/*`;
|
|
14
|
+
/**
|
|
15
|
+
* Formats files on the filesystem.
|
|
16
|
+
* When `patterns` is provided, formats those specific files/patterns.
|
|
17
|
+
* Otherwise formats `dir` with default extensions, plus root files if `dir` is `paths.source`.
|
|
18
|
+
* This is separated from `./format_file` to avoid importing all of the `prettier` code
|
|
19
|
+
* inside modules that import this one. (which has a nontrivial cost)
|
|
20
|
+
*/
|
|
21
|
+
export const format_directory = async (log, dir, check = false, extensions = EXTENSIONS_DEFAULT, root_paths = ROOT_PATHS_DEFAULT, prettier_cli = PRETTIER_CLI_DEFAULT, pm_cli = PM_CLI_DEFAULT, additional_args, patterns) => {
|
|
22
|
+
const forwarded_args = { ...additional_args };
|
|
23
|
+
if (forwarded_args.check === undefined && forwarded_args.write === undefined) {
|
|
24
|
+
forwarded_args[check ? 'check' : 'write'] = true;
|
|
25
|
+
}
|
|
26
|
+
const serialized_args = args_serialize(forwarded_args);
|
|
27
|
+
if (patterns?.length) {
|
|
28
|
+
serialized_args.push(...patterns);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
serialized_args.push(`${dir}**/*.{${extensions}}`);
|
|
32
|
+
if (dir === paths.source) {
|
|
33
|
+
serialized_args.push(`${paths.root}{${root_paths}}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const spawned = await spawn_cli(prettier_cli, serialized_args, log);
|
|
37
|
+
if (!spawned)
|
|
38
|
+
throw Error(`failed to find \`${to_cli_name(prettier_cli)}\` CLI locally or globally, do you need to run \`${pm_cli} install\`?`);
|
|
39
|
+
return spawned;
|
|
40
|
+
};
|