@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,9 @@
|
|
|
1
|
+
import prettier from 'prettier';
|
|
2
|
+
/**
|
|
3
|
+
* Formats a file with Prettier.
|
|
4
|
+
* @param content
|
|
5
|
+
* @param options
|
|
6
|
+
* @param base_options - defaults to the the cwd's package.json `prettier` value
|
|
7
|
+
*/
|
|
8
|
+
export declare const format_file: (content: string, options: prettier.Options, base_options?: prettier.Options | null | undefined) => Promise<string>;
|
|
9
|
+
//# sourceMappingURL=format_file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format_file.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/format_file.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAOhC;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACvB,SAAS,MAAM,EACf,SAAS,QAAQ,CAAC,OAAO,EACzB,eAAc,QAAQ,CAAC,OAAO,GAAG,IAAI,GAAG,SAA+B,KACrE,OAAO,CAAC,MAAM,CAgBhB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import prettier from 'prettier';
|
|
2
|
+
import { extname } from 'node:path';
|
|
3
|
+
import { package_json_load } from "./package_json.js";
|
|
4
|
+
let cached_base_options;
|
|
5
|
+
/**
|
|
6
|
+
* Formats a file with Prettier.
|
|
7
|
+
* @param content
|
|
8
|
+
* @param options
|
|
9
|
+
* @param base_options - defaults to the the cwd's package.json `prettier` value
|
|
10
|
+
*/
|
|
11
|
+
export const format_file = async (content, options, base_options = cached_base_options) => {
|
|
12
|
+
const final_base_options = base_options !== undefined
|
|
13
|
+
? base_options
|
|
14
|
+
: (cached_base_options = (await package_json_load()).prettier);
|
|
15
|
+
let final_options = options;
|
|
16
|
+
if (options.filepath && !options.parser) {
|
|
17
|
+
const { filepath, ...rest } = options;
|
|
18
|
+
const parser = infer_parser(filepath);
|
|
19
|
+
if (parser)
|
|
20
|
+
final_options = { ...rest, parser };
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
return await prettier.format(content, { ...final_base_options, ...final_options });
|
|
24
|
+
}
|
|
25
|
+
catch (_err) {
|
|
26
|
+
return content;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
// This is just a simple convenience for callers so they can pass a file path.
|
|
30
|
+
// They can provide the Prettier `options.parser` for custom extensions.
|
|
31
|
+
const infer_parser = (path) => {
|
|
32
|
+
const extension = extname(path).substring(1);
|
|
33
|
+
switch (extension) {
|
|
34
|
+
case 'svelte':
|
|
35
|
+
case 'xml': {
|
|
36
|
+
return extension;
|
|
37
|
+
}
|
|
38
|
+
default: {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
package/dist/gen.d.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
2
|
+
import type { Result } from '@fuzdev/fuz_util/result.js';
|
|
3
|
+
import type { Timings } from '@fuzdev/fuz_util/timings.js';
|
|
4
|
+
import type { PathId } from '@fuzdev/fuz_util/path.js';
|
|
5
|
+
import type { GroConfig } from './gro_config.ts';
|
|
6
|
+
import type { ParsedSvelteConfig } from './svelte_config.ts';
|
|
7
|
+
import { type LoadModulesFailure, type ModuleMeta } from './modules.ts';
|
|
8
|
+
import { InputPath, type ResolvedInputFile, type ResolvedInputPath } from './input_path.ts';
|
|
9
|
+
import type { Filer } from './filer.ts';
|
|
10
|
+
import type { InvokeTask } from './task.ts';
|
|
11
|
+
export declare const GEN_FILE_PATTERN_TEXT = "gen";
|
|
12
|
+
export declare const GEN_FILE_PATTERN: string;
|
|
13
|
+
export declare const is_gen_path: (path: string) => boolean;
|
|
14
|
+
export interface GenResult {
|
|
15
|
+
origin_id: PathId;
|
|
16
|
+
files: Array<GenFile>;
|
|
17
|
+
}
|
|
18
|
+
export interface GenFile {
|
|
19
|
+
id: PathId;
|
|
20
|
+
content: string;
|
|
21
|
+
origin_id: PathId;
|
|
22
|
+
format: boolean;
|
|
23
|
+
}
|
|
24
|
+
export type GenDependencies = 'all' | GenDependenciesConfig | GenDependenciesResolver;
|
|
25
|
+
export interface GenDependenciesConfig {
|
|
26
|
+
patterns?: Array<RegExp>;
|
|
27
|
+
files?: Array<PathId>;
|
|
28
|
+
}
|
|
29
|
+
export type GenDependenciesResolver = (ctx: GenContext) => GenDependenciesConfig | 'all' | null | Promise<GenDependenciesConfig | 'all' | null>;
|
|
30
|
+
export type Gen = GenFunction | GenConfig;
|
|
31
|
+
export type GenFunction = (ctx: GenContext) => RawGenResult | Promise<RawGenResult>;
|
|
32
|
+
export interface GenConfig {
|
|
33
|
+
generate: GenFunction;
|
|
34
|
+
dependencies?: GenDependencies;
|
|
35
|
+
}
|
|
36
|
+
export interface GenContext {
|
|
37
|
+
config: GroConfig;
|
|
38
|
+
svelte_config: ParsedSvelteConfig;
|
|
39
|
+
filer: Filer;
|
|
40
|
+
log: Logger;
|
|
41
|
+
timings: Timings;
|
|
42
|
+
invoke_task: InvokeTask;
|
|
43
|
+
/**
|
|
44
|
+
* Same as `import.meta.url` but in path form.
|
|
45
|
+
*/
|
|
46
|
+
origin_id: PathId;
|
|
47
|
+
/**
|
|
48
|
+
* The `origin_id` relative to the root dir.
|
|
49
|
+
*/
|
|
50
|
+
origin_path: string;
|
|
51
|
+
/**
|
|
52
|
+
* The file that triggered dependency checking.
|
|
53
|
+
* Only available when resolving dependencies dynamically.
|
|
54
|
+
* `undefined` during actual generation.
|
|
55
|
+
*/
|
|
56
|
+
changed_file_id: PathId | undefined;
|
|
57
|
+
}
|
|
58
|
+
export type RawGenResult = string | RawGenFile | null | Array<RawGenResult>;
|
|
59
|
+
export interface RawGenFile {
|
|
60
|
+
content: string;
|
|
61
|
+
filename?: string;
|
|
62
|
+
format?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export interface GenResults {
|
|
65
|
+
results: Array<GenfileModuleResult>;
|
|
66
|
+
successes: Array<GenfileModuleResultSuccess>;
|
|
67
|
+
failures: Array<GenfileModuleResultFailure>;
|
|
68
|
+
input_count: number;
|
|
69
|
+
output_count: number;
|
|
70
|
+
elapsed: number;
|
|
71
|
+
}
|
|
72
|
+
export type GenfileModuleResult = GenfileModuleResultSuccess | GenfileModuleResultFailure;
|
|
73
|
+
export interface GenfileModuleResultSuccess {
|
|
74
|
+
ok: true;
|
|
75
|
+
id: PathId;
|
|
76
|
+
files: Array<GenFile>;
|
|
77
|
+
elapsed: number;
|
|
78
|
+
}
|
|
79
|
+
export interface GenfileModuleResultFailure {
|
|
80
|
+
ok: false;
|
|
81
|
+
id: PathId;
|
|
82
|
+
reason: string;
|
|
83
|
+
error: Error;
|
|
84
|
+
elapsed: number;
|
|
85
|
+
}
|
|
86
|
+
export declare const to_gen_result: (origin_id: PathId, raw_result: RawGenResult) => GenResult;
|
|
87
|
+
export declare const to_output_file_name: (filename: string) => string;
|
|
88
|
+
export type AnalyzedGenResult = {
|
|
89
|
+
file: GenFile;
|
|
90
|
+
existing_content: string;
|
|
91
|
+
is_new: false;
|
|
92
|
+
has_changed: boolean;
|
|
93
|
+
} | {
|
|
94
|
+
file: GenFile;
|
|
95
|
+
existing_content: null;
|
|
96
|
+
is_new: true;
|
|
97
|
+
has_changed: true;
|
|
98
|
+
};
|
|
99
|
+
export declare const analyze_gen_results: (gen_results: GenResults) => Promise<Array<AnalyzedGenResult>>;
|
|
100
|
+
export declare const analyze_gen_result: (file: GenFile) => Promise<AnalyzedGenResult>;
|
|
101
|
+
export declare const write_gen_results: (gen_results: GenResults, analyzed_gen_results: Array<AnalyzedGenResult>, log: Logger) => Promise<void>;
|
|
102
|
+
export interface FoundGenfiles {
|
|
103
|
+
resolved_input_files: Array<ResolvedInputFile>;
|
|
104
|
+
resolved_input_files_by_root_dir: Map<PathId, Array<ResolvedInputFile>>;
|
|
105
|
+
resolved_input_paths: Array<ResolvedInputPath>;
|
|
106
|
+
}
|
|
107
|
+
export type FindGenfilesResult = Result<{
|
|
108
|
+
value: FoundGenfiles;
|
|
109
|
+
}, FindGenfilesFailure>;
|
|
110
|
+
export type FindGenfilesFailure = {
|
|
111
|
+
type: 'unmapped_input_paths';
|
|
112
|
+
unmapped_input_paths: Array<InputPath>;
|
|
113
|
+
resolved_input_paths: Array<ResolvedInputPath>;
|
|
114
|
+
reasons: Array<string>;
|
|
115
|
+
} | {
|
|
116
|
+
type: 'input_directories_with_no_files';
|
|
117
|
+
input_directories_with_no_files: Array<InputPath>;
|
|
118
|
+
resolved_input_files: Array<ResolvedInputFile>;
|
|
119
|
+
resolved_input_files_by_root_dir: Map<PathId, Array<ResolvedInputFile>>;
|
|
120
|
+
resolved_input_paths: Array<ResolvedInputPath>;
|
|
121
|
+
reasons: Array<string>;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Finds modules from input paths. (see `src/lib/input_path.ts` for more)
|
|
125
|
+
*/
|
|
126
|
+
export declare const find_genfiles: (input_paths: Array<InputPath>, root_dirs: Array<PathId>, config: GroConfig, timings?: Timings) => Promise<FindGenfilesResult>;
|
|
127
|
+
export interface GenfileModule {
|
|
128
|
+
gen: Gen;
|
|
129
|
+
}
|
|
130
|
+
export type GenfileModuleMeta = ModuleMeta<GenfileModule>;
|
|
131
|
+
export interface LoadedGenfiles {
|
|
132
|
+
modules: Array<GenfileModuleMeta>;
|
|
133
|
+
found_genfiles: FoundGenfiles;
|
|
134
|
+
}
|
|
135
|
+
export type LoadGenfilesResult = Result<{
|
|
136
|
+
value: LoadedGenfiles;
|
|
137
|
+
}, LoadGenfilesFailure>;
|
|
138
|
+
export type LoadGenfilesFailure = LoadModulesFailure<GenfileModuleMeta>;
|
|
139
|
+
export declare const load_genfiles: (found_genfiles: FoundGenfiles, timings?: Timings) => Promise<LoadGenfilesResult>;
|
|
140
|
+
export declare const validate_gen_module: (mod: Record<string, any>) => mod is GenfileModule;
|
|
141
|
+
export declare const normalize_gen_config: (gen: Gen) => GenConfig;
|
|
142
|
+
//# sourceMappingURL=gen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen.ts"],"names":[],"mappings":"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"}
|
package/dist/gen.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { join, basename, dirname, isAbsolute } from 'node:path';
|
|
2
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { styleText as st } from 'node:util';
|
|
4
|
+
import { each_concurrent, map_concurrent } from '@fuzdev/fuz_util/async.js';
|
|
5
|
+
import { fs_search } from '@fuzdev/fuz_util/fs.js';
|
|
6
|
+
import { print_path } from "./paths.js";
|
|
7
|
+
import { load_modules } from "./modules.js";
|
|
8
|
+
import { InputPath, resolve_input_files, resolve_input_paths, } from "./input_path.js";
|
|
9
|
+
export const GEN_FILE_PATTERN_TEXT = 'gen';
|
|
10
|
+
export const GEN_FILE_PATTERN = '.' + GEN_FILE_PATTERN_TEXT + '.';
|
|
11
|
+
export const is_gen_path = (path) => path.includes(GEN_FILE_PATTERN);
|
|
12
|
+
export const to_gen_result = (origin_id, raw_result) => {
|
|
13
|
+
return {
|
|
14
|
+
origin_id,
|
|
15
|
+
files: to_gen_files(origin_id, raw_result),
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
const to_gen_files = (origin_id, raw_result) => {
|
|
19
|
+
if (raw_result === null) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
else if (typeof raw_result === 'string') {
|
|
23
|
+
return [to_gen_file(origin_id, { content: raw_result })];
|
|
24
|
+
}
|
|
25
|
+
else if (Array.isArray(raw_result)) {
|
|
26
|
+
const files = raw_result.flatMap((f) => to_gen_files(origin_id, f));
|
|
27
|
+
validate_gen_files(files);
|
|
28
|
+
return files;
|
|
29
|
+
}
|
|
30
|
+
return [to_gen_file(origin_id, raw_result)];
|
|
31
|
+
};
|
|
32
|
+
const to_gen_file = (origin_id, raw_gen_file) => {
|
|
33
|
+
const { content, filename, format = true } = raw_gen_file;
|
|
34
|
+
const id = to_output_file_id(origin_id, filename);
|
|
35
|
+
return { id, content, origin_id, format };
|
|
36
|
+
};
|
|
37
|
+
const to_output_file_id = (origin_id, raw_file_name) => {
|
|
38
|
+
if (raw_file_name === '') {
|
|
39
|
+
throw Error(`Output file name cannot be an empty string`);
|
|
40
|
+
}
|
|
41
|
+
const filename = raw_file_name ?? to_output_file_name(basename(origin_id));
|
|
42
|
+
if (isAbsolute(filename))
|
|
43
|
+
return filename;
|
|
44
|
+
const dir = dirname(origin_id);
|
|
45
|
+
const output_file_id = join(dir, filename);
|
|
46
|
+
if (output_file_id === origin_id) {
|
|
47
|
+
throw Error('Gen origin and output file ids cannot be the same');
|
|
48
|
+
}
|
|
49
|
+
return output_file_id;
|
|
50
|
+
};
|
|
51
|
+
export const to_output_file_name = (filename) => {
|
|
52
|
+
const parts = filename.split('.');
|
|
53
|
+
const gen_pattern_index = parts.indexOf(GEN_FILE_PATTERN_TEXT);
|
|
54
|
+
if (gen_pattern_index === -1) {
|
|
55
|
+
throw Error(`Invalid gen file name - '${GEN_FILE_PATTERN_TEXT}' not found in '${filename}'`);
|
|
56
|
+
}
|
|
57
|
+
if (gen_pattern_index !== parts.lastIndexOf(GEN_FILE_PATTERN_TEXT)) {
|
|
58
|
+
throw Error(`Invalid gen file name - multiple instances of '${GEN_FILE_PATTERN_TEXT}' found in '${filename}'`);
|
|
59
|
+
}
|
|
60
|
+
if (gen_pattern_index < parts.length - 3) {
|
|
61
|
+
// This check is technically unneccessary,
|
|
62
|
+
// but ensures a consistent file naming convention.
|
|
63
|
+
throw Error(`Invalid gen file name - only one additional extension is allowed to follow '${GEN_FILE_PATTERN}' in '${filename}'`);
|
|
64
|
+
}
|
|
65
|
+
const final_parts = [];
|
|
66
|
+
const has_different_ext = gen_pattern_index === parts.length - 3;
|
|
67
|
+
const length = has_different_ext ? parts.length - 1 : parts.length;
|
|
68
|
+
for (let i = 0; i < length; i++) {
|
|
69
|
+
if (i === gen_pattern_index)
|
|
70
|
+
continue; // skip the `.gen.` pattern
|
|
71
|
+
if (i === length - 1 && parts[i] === '')
|
|
72
|
+
continue; // allow empty extension
|
|
73
|
+
final_parts.push(parts[i]);
|
|
74
|
+
}
|
|
75
|
+
return final_parts.join('.');
|
|
76
|
+
};
|
|
77
|
+
const validate_gen_files = (files) => {
|
|
78
|
+
const ids = new Set();
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
if (ids.has(file.id)) {
|
|
81
|
+
throw Error(`Duplicate gen file id: ${file.id}`);
|
|
82
|
+
}
|
|
83
|
+
ids.add(file.id);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
export const analyze_gen_results = async (gen_results) => {
|
|
87
|
+
const files = gen_results.successes.flatMap((result) => result.files);
|
|
88
|
+
return map_concurrent(files, (file) => analyze_gen_result(file), 10);
|
|
89
|
+
};
|
|
90
|
+
export const analyze_gen_result = async (file) => {
|
|
91
|
+
let existing_content;
|
|
92
|
+
try {
|
|
93
|
+
existing_content = await readFile(file.id, 'utf8');
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error.code === 'ENOENT') {
|
|
97
|
+
return {
|
|
98
|
+
file,
|
|
99
|
+
existing_content: null,
|
|
100
|
+
is_new: true,
|
|
101
|
+
has_changed: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
file,
|
|
108
|
+
existing_content,
|
|
109
|
+
is_new: false,
|
|
110
|
+
has_changed: file.content !== existing_content,
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
export const write_gen_results = async (gen_results, analyzed_gen_results, log) => {
|
|
114
|
+
const files = gen_results.successes.flatMap((result) => result.files);
|
|
115
|
+
await each_concurrent(files, async (file) => {
|
|
116
|
+
const analyzed = analyzed_gen_results.find((r) => r.file.id === file.id);
|
|
117
|
+
if (!analyzed)
|
|
118
|
+
throw Error('Expected to find analyzed result: ' + file.id);
|
|
119
|
+
const log_args = [print_path(file.id), 'generated from', print_path(file.origin_id)];
|
|
120
|
+
if (analyzed.is_new) {
|
|
121
|
+
log.info('writing new', ...log_args);
|
|
122
|
+
await mkdir(dirname(file.id), { recursive: true });
|
|
123
|
+
await writeFile(file.id, file.content);
|
|
124
|
+
}
|
|
125
|
+
else if (analyzed.has_changed) {
|
|
126
|
+
log.info('writing changed', ...log_args);
|
|
127
|
+
await writeFile(file.id, file.content);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
log.info('skipping unchanged', ...log_args);
|
|
131
|
+
}
|
|
132
|
+
}, 10);
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Finds modules from input paths. (see `src/lib/input_path.ts` for more)
|
|
136
|
+
*/
|
|
137
|
+
export const find_genfiles = async (input_paths, root_dirs, config, timings) => {
|
|
138
|
+
const extensions = [GEN_FILE_PATTERN];
|
|
139
|
+
// Check which extension variation works - if it's a directory, prefer others first!
|
|
140
|
+
const timing_to_resolve_input_paths = timings?.start('resolve input paths');
|
|
141
|
+
const { resolved_input_paths, unmapped_input_paths } = await resolve_input_paths(input_paths, root_dirs, extensions);
|
|
142
|
+
timing_to_resolve_input_paths?.();
|
|
143
|
+
// Error if any input path could not be mapped.
|
|
144
|
+
if (unmapped_input_paths.length) {
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
type: 'unmapped_input_paths',
|
|
148
|
+
unmapped_input_paths,
|
|
149
|
+
resolved_input_paths,
|
|
150
|
+
reasons: unmapped_input_paths.map((input_path) => st('red', `Input path ${print_path(input_path)} cannot be mapped to a file or directory.`)),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// Find all of the files for any directories.
|
|
154
|
+
const timing_to_fs_search = timings?.start('find files');
|
|
155
|
+
const { resolved_input_files, resolved_input_files_by_root_dir, input_directories_with_no_files } = await resolve_input_files(resolved_input_paths, async (id) => await fs_search(id, {
|
|
156
|
+
filter: config.search_filters,
|
|
157
|
+
file_filter: (p) => extensions.some((e) => p.includes(e)),
|
|
158
|
+
}));
|
|
159
|
+
timing_to_fs_search?.();
|
|
160
|
+
// Error if any input path has no files. (means we have an empty directory)
|
|
161
|
+
if (input_directories_with_no_files.length) {
|
|
162
|
+
return {
|
|
163
|
+
ok: false,
|
|
164
|
+
type: 'input_directories_with_no_files',
|
|
165
|
+
input_directories_with_no_files,
|
|
166
|
+
resolved_input_files,
|
|
167
|
+
resolved_input_files_by_root_dir,
|
|
168
|
+
resolved_input_paths,
|
|
169
|
+
reasons: input_directories_with_no_files.map((input_path) => st('red', `Input directory contains no matching files: ${print_path(input_path)}`)),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
value: {
|
|
175
|
+
resolved_input_files,
|
|
176
|
+
resolved_input_files_by_root_dir,
|
|
177
|
+
resolved_input_paths,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
export const load_genfiles = async (found_genfiles, timings) => {
|
|
182
|
+
const loaded_modules = await load_modules(found_genfiles.resolved_input_files, validate_gen_module, (resolved_input_file, mod) => ({ id: resolved_input_file.id, mod }), timings);
|
|
183
|
+
if (!loaded_modules.ok) {
|
|
184
|
+
return loaded_modules;
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
ok: true,
|
|
188
|
+
value: { modules: loaded_modules.modules, found_genfiles },
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
export const validate_gen_module = (mod) => {
|
|
192
|
+
if (typeof mod.gen === 'function')
|
|
193
|
+
return true;
|
|
194
|
+
if (typeof mod.gen === 'object' && mod.gen !== null && typeof mod.gen.generate === 'function') {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
return false;
|
|
198
|
+
};
|
|
199
|
+
export const normalize_gen_config = (gen) => typeof gen === 'function' ? { generate: gen } : gen;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type Task } from './task.ts';
|
|
3
|
+
/** @nodocs */
|
|
4
|
+
export declare const Args: z.ZodObject<{
|
|
5
|
+
_: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
6
|
+
root_dirs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
7
|
+
check: z.ZodDefault<z.ZodBoolean>;
|
|
8
|
+
}, z.core.$strict>;
|
|
9
|
+
export type Args = z.infer<typeof Args>;
|
|
10
|
+
/** @nodocs */
|
|
11
|
+
export declare const task: Task<Args>;
|
|
12
|
+
//# sourceMappingURL=gen.task.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen.task.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAAY,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AAgB/C,cAAc;AACd,eAAO,MAAM,IAAI;;;;kBAUf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,cAAc;AACd,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CAqG3B,CAAC"}
|
package/dist/gen.task.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { styleText as st } from 'node:util';
|
|
2
|
+
import { print_ms, print_error } from '@fuzdev/fuz_util/print.js';
|
|
3
|
+
import { plural } from '@fuzdev/fuz_util/string.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { TaskError } from "./task.js";
|
|
6
|
+
import { run_gen } from "./run_gen.js";
|
|
7
|
+
import { RawInputPath, to_input_paths } from "./input_path.js";
|
|
8
|
+
import { format_file } from "./format_file.js";
|
|
9
|
+
import { print_path } from "./paths.js";
|
|
10
|
+
import { log_error_reasons } from "./task_logging.js";
|
|
11
|
+
import { write_gen_results, analyze_gen_results, find_genfiles, load_genfiles, } from "./gen.js";
|
|
12
|
+
import { SOURCE_DIRNAME } from "./constants.js";
|
|
13
|
+
/** @nodocs */
|
|
14
|
+
export const Args = z.strictObject({
|
|
15
|
+
_: z.array(RawInputPath).meta({ description: 'input paths to generate' }).default([SOURCE_DIRNAME]),
|
|
16
|
+
root_dirs: z
|
|
17
|
+
.array(z.string())
|
|
18
|
+
.meta({ description: 'root directories to resolve input paths against' }) // TODO `PathId` schema
|
|
19
|
+
.default([process.cwd()]),
|
|
20
|
+
check: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.meta({ description: 'exit with a nonzero code if any files need to be generated' })
|
|
23
|
+
.default(false),
|
|
24
|
+
});
|
|
25
|
+
/** @nodocs */
|
|
26
|
+
export const task = {
|
|
27
|
+
summary: 'run code generation scripts',
|
|
28
|
+
Args,
|
|
29
|
+
run: async ({ args, filer, log, timings, config, invoke_task }) => {
|
|
30
|
+
const { _: raw_input_paths, root_dirs, check } = args;
|
|
31
|
+
const input_paths = to_input_paths(raw_input_paths);
|
|
32
|
+
// load all of the gen modules
|
|
33
|
+
const found = await find_genfiles(input_paths, root_dirs, config, timings);
|
|
34
|
+
if (!found.ok) {
|
|
35
|
+
if (found.type === 'input_directories_with_no_files') {
|
|
36
|
+
// TODO maybe let this error like the normal case, but only call `gro gen` if we find gen files? problem is the args would need to be hoisted to callers like `gro sync`
|
|
37
|
+
log.info('no gen modules found in ' + input_paths.join(', '));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
log_error_reasons(log, found.reasons);
|
|
42
|
+
throw new TaskError('Failed to find gen modules.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const found_genfiles = found.value;
|
|
46
|
+
log.info('gen files', found_genfiles.resolved_input_files.map((f) => f.id));
|
|
47
|
+
const loaded = await load_genfiles(found_genfiles, timings);
|
|
48
|
+
if (!loaded.ok) {
|
|
49
|
+
log_error_reasons(log, loaded.reasons);
|
|
50
|
+
throw new TaskError('Failed to load gen modules.');
|
|
51
|
+
}
|
|
52
|
+
const loaded_genfiles = loaded.value;
|
|
53
|
+
// run `gen` on each of the modules
|
|
54
|
+
const timing_to_generate_code = timings.start('generate code'); // TODO this ignores `gen_results.elapsed` - should it return `Timings` instead?
|
|
55
|
+
const gen_results = await run_gen(loaded_genfiles.modules, config, filer, log, timings, invoke_task, format_file);
|
|
56
|
+
timing_to_generate_code();
|
|
57
|
+
const fail_count = gen_results.failures.length;
|
|
58
|
+
const analyzed_gen_results = await analyze_gen_results(gen_results);
|
|
59
|
+
if (check) {
|
|
60
|
+
// check if any files changed, and if so, throw errors,
|
|
61
|
+
// but if there are gen failures, skip the check and defer to their errors
|
|
62
|
+
if (!fail_count) {
|
|
63
|
+
log.info('checking generated files for changes');
|
|
64
|
+
const timing_to_check_results = timings.start('check results for changes');
|
|
65
|
+
timing_to_check_results();
|
|
66
|
+
let has_unexpected_changes = false;
|
|
67
|
+
for (const analyzed of analyzed_gen_results) {
|
|
68
|
+
if (!analyzed.has_changed)
|
|
69
|
+
continue;
|
|
70
|
+
has_unexpected_changes = true;
|
|
71
|
+
log.error(st('red', `Generated file ${print_path(analyzed.file.id)} via ${print_path(analyzed.file.origin_id)} ${analyzed.is_new ? 'is new' : 'has changed'}.`));
|
|
72
|
+
}
|
|
73
|
+
if (has_unexpected_changes) {
|
|
74
|
+
throw new TaskError('Failed gen check. Some generated files have unexpectedly changed.' +
|
|
75
|
+
' Run `gro gen` and try again.');
|
|
76
|
+
}
|
|
77
|
+
log.info('check passed, no files have changed');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const timing_to_output_results = timings.start('output results');
|
|
82
|
+
await write_gen_results(gen_results, analyzed_gen_results, log);
|
|
83
|
+
timing_to_output_results();
|
|
84
|
+
}
|
|
85
|
+
// collect and format output with summary
|
|
86
|
+
const output_lines = collect_output_lines(gen_results, analyzed_gen_results);
|
|
87
|
+
const new_count = analyzed_gen_results.filter((r) => r.is_new).length;
|
|
88
|
+
const changed_count = analyzed_gen_results.filter((r) => r.has_changed && !r.is_new).length;
|
|
89
|
+
const unchanged_count = analyzed_gen_results.filter((r) => !r.is_new && !r.has_changed).length;
|
|
90
|
+
const error_count = gen_results.failures.length;
|
|
91
|
+
log.info(format_gen_output(output_lines) +
|
|
92
|
+
`\n\n\t${new_count} ${st(new_count > 0 ? 'green' : 'gray', 'new')}, ${changed_count} ${st(changed_count > 0 ? 'cyan' : 'gray', 'changed')}, ${unchanged_count} ${st('gray', 'unchanged')}${error_count ? `, ${error_count} ${st('red', 'error' + plural(error_count))}` : ''} from ${gen_results.input_count} input file${plural(gen_results.input_count)}`);
|
|
93
|
+
if (fail_count) {
|
|
94
|
+
for (const result of gen_results.failures) {
|
|
95
|
+
log.error(result.reason, '\n', print_error(result.error));
|
|
96
|
+
}
|
|
97
|
+
throw new TaskError(`Failed to generate ${fail_count} file${plural(fail_count)}.`);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
const format_gen_status = (analyzed) => {
|
|
102
|
+
if (!analyzed)
|
|
103
|
+
return { symbol: '?', color: 'gray', text: 'unknown' };
|
|
104
|
+
if (analyzed.is_new)
|
|
105
|
+
return { symbol: '●', color: 'green', text: 'new' };
|
|
106
|
+
if (analyzed.has_changed)
|
|
107
|
+
return { symbol: '◐', color: 'cyan', text: 'changed' };
|
|
108
|
+
return { symbol: '○', color: 'gray', text: 'unchanged' };
|
|
109
|
+
};
|
|
110
|
+
const collect_output_lines = (gen_results, analyzed_gen_results) => {
|
|
111
|
+
const output_lines = [];
|
|
112
|
+
for (const result of gen_results.results) {
|
|
113
|
+
if (result.ok) {
|
|
114
|
+
for (const file of result.files) {
|
|
115
|
+
const analyzed = analyzed_gen_results.find((a) => a.file.id === file.id);
|
|
116
|
+
output_lines.push({
|
|
117
|
+
status: format_gen_status(analyzed),
|
|
118
|
+
elapsed: print_ms(result.elapsed),
|
|
119
|
+
source: print_path(result.id),
|
|
120
|
+
target: print_path(file.id),
|
|
121
|
+
is_error: false,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
output_lines.push({
|
|
127
|
+
status: { symbol: '🞩', color: 'red', text: 'error' },
|
|
128
|
+
elapsed: print_ms(result.elapsed),
|
|
129
|
+
source: print_path(result.id),
|
|
130
|
+
target: st('red', result.error.stack || result.error.message || 'error'),
|
|
131
|
+
is_error: true,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return output_lines;
|
|
136
|
+
};
|
|
137
|
+
const format_gen_output = (output_lines) => {
|
|
138
|
+
// calculate column widths for alignment
|
|
139
|
+
const max_elapsed_length = Math.max(...output_lines.map((l) => l.elapsed.length));
|
|
140
|
+
const max_source_length = Math.max(...output_lines.map((l) => l.source.length));
|
|
141
|
+
// format the output lines
|
|
142
|
+
let log_result = 'gen results:';
|
|
143
|
+
for (const line of output_lines) {
|
|
144
|
+
const elapsed_text = line.elapsed.padStart(max_elapsed_length);
|
|
145
|
+
const source_text = line.source.padEnd(max_source_length);
|
|
146
|
+
log_result += `\n\t${st(line.status.color, line.status.symbol)} ${elapsed_text} ${source_text} → ${line.target}`;
|
|
147
|
+
}
|
|
148
|
+
return log_result;
|
|
149
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
2
|
+
import type { Timings } from '@fuzdev/fuz_util/timings.js';
|
|
3
|
+
import type { PathId } from '@fuzdev/fuz_util/path.js';
|
|
4
|
+
import type { GroConfig } from './gro_config.ts';
|
|
5
|
+
import { type Filer } from './filer.ts';
|
|
6
|
+
import type { InvokeTask } from './task.ts';
|
|
7
|
+
/**
|
|
8
|
+
* Check if a file change should trigger a gen file.
|
|
9
|
+
*/
|
|
10
|
+
export declare const should_trigger_gen: (gen_file_id: PathId, changed_file_id: PathId, config: GroConfig, filer: Filer, log: Logger, timings: Timings, invoke_task: InvokeTask) => Promise<boolean>;
|
|
11
|
+
//# sourceMappingURL=gen_helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gen_helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,6BAA6B,CAAC;AACzD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAErD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAoB,KAAK,KAAK,EAAC,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAY1C;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC9B,aAAa,MAAM,EACnB,iBAAiB,MAAM,EACvB,QAAQ,SAAS,EACjB,OAAO,KAAK,EACZ,KAAK,MAAM,EACX,SAAS,OAAO,EAChB,aAAa,UAAU,KACrB,OAAO,CAAC,OAAO,CAqCjB,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { filter_dependents } from "./filer.js";
|
|
3
|
+
import { normalize_gen_config, validate_gen_module, } from "./gen.js";
|
|
4
|
+
import { default_svelte_config } from "./svelte_config.js";
|
|
5
|
+
import { to_root_path } from "./paths.js";
|
|
6
|
+
import { load_module } from "./modules.js";
|
|
7
|
+
/**
|
|
8
|
+
* Check if a file change should trigger a gen file.
|
|
9
|
+
*/
|
|
10
|
+
export const should_trigger_gen = async (gen_file_id, changed_file_id, config, filer, log, timings, invoke_task) => {
|
|
11
|
+
// Always trigger if the gen file itself changed
|
|
12
|
+
const is_self_change = gen_file_id === changed_file_id;
|
|
13
|
+
if (is_self_change)
|
|
14
|
+
return true;
|
|
15
|
+
// Check if gen file depends on the changed file (directly or transitively)
|
|
16
|
+
const changed_disknode = filer.get_by_id(changed_file_id);
|
|
17
|
+
let should_bust_cache = false;
|
|
18
|
+
if (changed_disknode) {
|
|
19
|
+
const dependents = filter_dependents(changed_disknode, filer.get_by_id, (id) => id === gen_file_id);
|
|
20
|
+
should_bust_cache = dependents.has(gen_file_id);
|
|
21
|
+
}
|
|
22
|
+
// Resolve dependencies (with cache busting if the changed file is a dependency of the gen file)
|
|
23
|
+
const dependencies = await resolve_gen_dependencies(gen_file_id, changed_file_id, should_bust_cache, config, filer, log, timings, invoke_task);
|
|
24
|
+
if (!dependencies)
|
|
25
|
+
return false;
|
|
26
|
+
return (dependencies === 'all' ||
|
|
27
|
+
dependencies.patterns?.some((p) => p.test(changed_file_id)) ||
|
|
28
|
+
dependencies.files?.includes(changed_file_id) ||
|
|
29
|
+
false);
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Resolve dependencies for a gen file.
|
|
33
|
+
* Uses cache-busting only when the gen file itself changes,
|
|
34
|
+
* otherwise relies on Node's module caching.
|
|
35
|
+
*/
|
|
36
|
+
const resolve_gen_dependencies = async (gen_file_id, changed_file_id, bust_cache, config, filer, log, timings, invoke_task) => {
|
|
37
|
+
const result = await load_module(gen_file_id, validate_gen_module, bust_cache);
|
|
38
|
+
if (!result.ok) {
|
|
39
|
+
if (result.type === 'failed_import') {
|
|
40
|
+
log.error(`Failed to import ${gen_file_id}:`, result.error);
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const gen_config = normalize_gen_config(result.mod.gen);
|
|
45
|
+
if (!gen_config.dependencies) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
let dependencies = gen_config.dependencies;
|
|
49
|
+
if (typeof dependencies === 'function') {
|
|
50
|
+
const gen_ctx = {
|
|
51
|
+
config,
|
|
52
|
+
svelte_config: default_svelte_config,
|
|
53
|
+
filer,
|
|
54
|
+
log,
|
|
55
|
+
timings,
|
|
56
|
+
invoke_task,
|
|
57
|
+
origin_id: gen_file_id,
|
|
58
|
+
origin_path: to_root_path(gen_file_id),
|
|
59
|
+
changed_file_id,
|
|
60
|
+
};
|
|
61
|
+
dependencies = await dependencies(gen_ctx);
|
|
62
|
+
}
|
|
63
|
+
if (dependencies === null || dependencies === 'all') {
|
|
64
|
+
return dependencies;
|
|
65
|
+
}
|
|
66
|
+
// At this point, dependencies is either 'all' or GenDependenciesConfig
|
|
67
|
+
// For static dependencies, also normalize empty objects
|
|
68
|
+
if (!dependencies.patterns?.length && !dependencies.files?.length) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
// Normalize file paths to absolute paths
|
|
72
|
+
if (dependencies.files) {
|
|
73
|
+
dependencies.files = dependencies.files.map((f) => resolve(f));
|
|
74
|
+
}
|
|
75
|
+
return dependencies;
|
|
76
|
+
};
|