@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,178 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { plural, strip_end } from '@fuzdev/fuz_util/string.js';
|
|
5
|
+
import { styleText as st } from 'node:util';
|
|
6
|
+
import { PackageJson, PackageJsonExports } from '@fuzdev/fuz_util/package_json.js';
|
|
7
|
+
import { fs_search } from '@fuzdev/fuz_util/fs.js';
|
|
8
|
+
import { paths, gro_paths, IS_THIS_GRO } from "./paths.js";
|
|
9
|
+
import { PACKAGE_JSON_FILENAME, SVELTEKIT_DIST_DIRNAME, TS_MATCHER, JS_MATCHER, SVELTE_MATCHER, JSON_MATCHER, CSS_MATCHER, } from "./constants.js";
|
|
10
|
+
import { has_sveltekit_library } from "./sveltekit_helpers.js";
|
|
11
|
+
import { GITHUB_REPO_MATCHER } from "./github.js";
|
|
12
|
+
export const PACKAGE_JSON_EMPTY = { name: '', version: '' };
|
|
13
|
+
export const package_json_load = async (dir = IS_THIS_GRO ? gro_paths.root : paths.root, cache, parse = true, // TODO pass `false` here in more places, especially anything perf-sensitive like work on startup
|
|
14
|
+
log) => {
|
|
15
|
+
let package_json;
|
|
16
|
+
if (cache && dir in cache) {
|
|
17
|
+
return cache[dir];
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
package_json = JSON.parse(await package_json_load_contents(dir));
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
log?.error(st('yellow', `Failed to load package.json in ${dir}`), error);
|
|
24
|
+
return PACKAGE_JSON_EMPTY;
|
|
25
|
+
}
|
|
26
|
+
if (parse) {
|
|
27
|
+
package_json = parse_package_json(PackageJson, package_json);
|
|
28
|
+
}
|
|
29
|
+
if (cache) {
|
|
30
|
+
cache[dir] = package_json;
|
|
31
|
+
}
|
|
32
|
+
return package_json;
|
|
33
|
+
};
|
|
34
|
+
export const package_json_sync = async (map_package_json, log, write = true, dir = paths.root, exports_dir = paths.lib) => {
|
|
35
|
+
const exported_files = await fs_search(exports_dir);
|
|
36
|
+
const exported_paths = exported_files.map((f) => f.path);
|
|
37
|
+
const updated = await package_json_update(async (package_json) => {
|
|
38
|
+
if ((await has_sveltekit_library(package_json)).ok) {
|
|
39
|
+
package_json.exports = package_json_to_exports(exported_paths);
|
|
40
|
+
}
|
|
41
|
+
const mapped = await map_package_json(package_json);
|
|
42
|
+
return mapped ? parse_package_json(PackageJson, mapped) : mapped;
|
|
43
|
+
}, dir, write);
|
|
44
|
+
const exports_count = updated.changed && updated.package_json?.exports
|
|
45
|
+
? Object.keys(updated.package_json.exports).length
|
|
46
|
+
: 0;
|
|
47
|
+
log.info(updated.changed
|
|
48
|
+
? `updated package.json exports with ${exports_count} total export${plural(exports_count)}`
|
|
49
|
+
: 'no changes to exports in package.json');
|
|
50
|
+
return updated;
|
|
51
|
+
};
|
|
52
|
+
export const package_json_load_for_gro = () => package_json_load(gro_paths.root);
|
|
53
|
+
// TODO probably make this nullable and make callers handle failures
|
|
54
|
+
const package_json_load_contents = (dir) => readFile(join(dir, PACKAGE_JSON_FILENAME), 'utf8');
|
|
55
|
+
export const package_json_write = (serialized_package_json) => writeFile(join(paths.root, PACKAGE_JSON_FILENAME), serialized_package_json);
|
|
56
|
+
export const package_json_serialize = (package_json) => JSON.stringify(parse_package_json(PackageJson, package_json), null, 2) + '\n';
|
|
57
|
+
/**
|
|
58
|
+
* Updates package.json. Writes to the filesystem only when contents change.
|
|
59
|
+
*/
|
|
60
|
+
export const package_json_update = async (update, dir = paths.root, write = true) => {
|
|
61
|
+
const original_contents = await package_json_load_contents(dir);
|
|
62
|
+
const original = JSON.parse(original_contents);
|
|
63
|
+
const updated = await update(original);
|
|
64
|
+
if (updated === null) {
|
|
65
|
+
return { package_json: original, changed: false };
|
|
66
|
+
}
|
|
67
|
+
const updated_contents = package_json_serialize(updated);
|
|
68
|
+
if (updated_contents === original_contents) {
|
|
69
|
+
return { package_json: original, changed: false };
|
|
70
|
+
}
|
|
71
|
+
if (write)
|
|
72
|
+
await package_json_write(updated_contents);
|
|
73
|
+
return { package_json: updated, changed: true };
|
|
74
|
+
};
|
|
75
|
+
const is_index = (path) => path === 'index.ts' || path === 'index.js';
|
|
76
|
+
export const package_json_to_exports = (paths) => {
|
|
77
|
+
const has_index = paths.some(is_index);
|
|
78
|
+
const has_js = paths.some((p) => TS_MATCHER.test(p) || JS_MATCHER.test(p));
|
|
79
|
+
const has_svelte = paths.some((p) => SVELTE_MATCHER.test(p));
|
|
80
|
+
const has_json = paths.some((p) => JSON_MATCHER.test(p));
|
|
81
|
+
const has_css = paths.some((p) => CSS_MATCHER.test(p));
|
|
82
|
+
const exports = {
|
|
83
|
+
'./package.json': './package.json',
|
|
84
|
+
};
|
|
85
|
+
if (has_index) {
|
|
86
|
+
exports['.'] = {
|
|
87
|
+
types: IMPORT_PREFIX + 'index.d.ts',
|
|
88
|
+
default: IMPORT_PREFIX + 'index.js',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (has_js) {
|
|
92
|
+
exports['./*.js'] = {
|
|
93
|
+
types: IMPORT_PREFIX + '*.d.ts',
|
|
94
|
+
default: IMPORT_PREFIX + '*.js',
|
|
95
|
+
};
|
|
96
|
+
exports['./*.ts'] = {
|
|
97
|
+
types: IMPORT_PREFIX + '*.d.ts',
|
|
98
|
+
default: IMPORT_PREFIX + '*.js',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (has_svelte) {
|
|
102
|
+
exports['./*.svelte'] = {
|
|
103
|
+
types: IMPORT_PREFIX + '*.svelte.d.ts',
|
|
104
|
+
svelte: IMPORT_PREFIX + '*.svelte',
|
|
105
|
+
default: IMPORT_PREFIX + '*.svelte',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (has_json) {
|
|
109
|
+
exports['./*.json'] = {
|
|
110
|
+
types: IMPORT_PREFIX + '*.json.d.ts',
|
|
111
|
+
default: IMPORT_PREFIX + '*.json',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
if (has_css) {
|
|
115
|
+
exports['./*.css'] = {
|
|
116
|
+
default: IMPORT_PREFIX + '*.css',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return parse_or_throw_formatted_error('package.json#exports', PackageJsonExports, exports);
|
|
120
|
+
};
|
|
121
|
+
const IMPORT_PREFIX = './' + SVELTEKIT_DIST_DIRNAME + '/';
|
|
122
|
+
export const package_json_parse_repo_url = (package_json) => {
|
|
123
|
+
const { repository } = package_json;
|
|
124
|
+
const repo_url = repository
|
|
125
|
+
? typeof repository === 'string'
|
|
126
|
+
? repository
|
|
127
|
+
: repository.url
|
|
128
|
+
: undefined;
|
|
129
|
+
if (!repo_url) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const parsed_repo_url = GITHUB_REPO_MATCHER.exec(strip_end(strip_end(repo_url, '/'), '.git'));
|
|
133
|
+
if (!parsed_repo_url) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const [, owner, repo] = parsed_repo_url;
|
|
137
|
+
return { owner: owner, repo: repo };
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Parses a `PackageJson` object but preserves the order of the original keys.
|
|
141
|
+
*/
|
|
142
|
+
const parse_package_json = (schema, value) => {
|
|
143
|
+
const parsed = parse_or_throw_formatted_error(PACKAGE_JSON_FILENAME, schema, value);
|
|
144
|
+
const keys = Object.keys(value);
|
|
145
|
+
return Object.fromEntries(Object.entries(parsed).sort(([a], [b]) => keys.indexOf(a) - keys.indexOf(b)));
|
|
146
|
+
};
|
|
147
|
+
// TODO maybe extract to zod helpers? see also everything in `task_logging.ts`
|
|
148
|
+
const parse_or_throw_formatted_error = (name, schema, value) => {
|
|
149
|
+
const parsed = schema.safeParse(value);
|
|
150
|
+
if (!parsed.success) {
|
|
151
|
+
let msg = st('red', `Failed to parse ${name}:\n`);
|
|
152
|
+
for (const issue of parsed.error.issues) {
|
|
153
|
+
msg += st('red', `\n\t"${issue.path}" ${issue.message}\n`);
|
|
154
|
+
}
|
|
155
|
+
throw Error(msg);
|
|
156
|
+
}
|
|
157
|
+
return parsed.data;
|
|
158
|
+
};
|
|
159
|
+
export const package_json_has_dependency = (dep_name, package_json) => !!package_json.devDependencies?.[dep_name] ||
|
|
160
|
+
!!package_json.dependencies?.[dep_name] ||
|
|
161
|
+
!!package_json.peerDependencies?.[dep_name];
|
|
162
|
+
export const package_json_extract_dependencies = (package_json) => {
|
|
163
|
+
const deps_by_name = new Map();
|
|
164
|
+
// Earlier versions override later ones, so peer deps goes last.
|
|
165
|
+
const add_deps = (deps) => {
|
|
166
|
+
if (!deps)
|
|
167
|
+
return;
|
|
168
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
169
|
+
if (!deps_by_name.has(name)) {
|
|
170
|
+
deps_by_name.set(name, { name, version });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
add_deps(package_json.dependencies);
|
|
175
|
+
add_deps(package_json.devDependencies);
|
|
176
|
+
add_deps(package_json.peerDependencies);
|
|
177
|
+
return Array.from(deps_by_name.values());
|
|
178
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { Flavored } from '@fuzdev/fuz_util/types.js';
|
|
3
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
4
|
+
import type { DeclarationKind } from '@fuzdev/fuz_util/source_json.js';
|
|
5
|
+
import type { PathId } from '@fuzdev/fuz_util/path.js';
|
|
6
|
+
export interface Declaration {
|
|
7
|
+
name: string;
|
|
8
|
+
kind: DeclarationKind | null;
|
|
9
|
+
}
|
|
10
|
+
export type ExportDeclaration = Flavored<Declaration, 'ExportDeclaration'>;
|
|
11
|
+
/**
|
|
12
|
+
* Parse exports from a file based on its file type and content.
|
|
13
|
+
*/
|
|
14
|
+
export declare const parse_exports: (id: PathId, program?: ts.Program, declarations?: Array<ExportDeclaration>, log?: Logger) => Array<ExportDeclaration>;
|
|
15
|
+
export declare const infer_declarations_from_file_type: (file_path: PathId, declarations?: Array<ExportDeclaration>) => Array<ExportDeclaration>;
|
|
16
|
+
/**
|
|
17
|
+
* Process TypeScript exports, identifying their kinds.
|
|
18
|
+
*/
|
|
19
|
+
export declare const process_ts_exports: (source_file: ts.SourceFile, program: ts.Program, exports: Array<ts.Symbol>, declarations?: Array<ExportDeclaration>, log?: Logger) => Array<ExportDeclaration>;
|
|
20
|
+
//# sourceMappingURL=parse_exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse_exports.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/parse_exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAKrD,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,aAAa,GACzB,IAAI,MAAM,EACV,UAAU,EAAE,CAAC,OAAO,EACpB,eAAc,KAAK,CAAC,iBAAiB,CAAM,EAC3C,MAAM,MAAM,KACV,KAAK,CAAC,iBAAiB,CAyBzB,CAAC;AAGF,eAAO,MAAM,iCAAiC,GAC7C,WAAW,MAAM,EACjB,eAAc,KAAK,CAAC,iBAAiB,CAAM,KACzC,KAAK,CAAC,iBAAiB,CA4BzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC9B,aAAa,EAAE,CAAC,UAAU,EAC1B,SAAS,EAAE,CAAC,OAAO,EACnB,SAAS,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EACzB,eAAc,KAAK,CAAC,iBAAiB,CAAM,EAC3C,MAAM,MAAM,KACV,KAAK,CAAC,iBAAiB,CAIzB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { extname } from 'node:path';
|
|
3
|
+
import { TS_MATCHER } from "./constants.js";
|
|
4
|
+
import { ParseExportsContext } from "./parse_exports_context.js";
|
|
5
|
+
/**
|
|
6
|
+
* Parse exports from a file based on its file type and content.
|
|
7
|
+
*/
|
|
8
|
+
export const parse_exports = (id, program, declarations = [], log) => {
|
|
9
|
+
// First, infer declarations based on file extension
|
|
10
|
+
infer_declarations_from_file_type(id, declarations);
|
|
11
|
+
// For TypeScript files with program, perform detailed export analysis
|
|
12
|
+
if (TS_MATCHER.test(id) && program) {
|
|
13
|
+
const source_file = program.getSourceFile(id);
|
|
14
|
+
if (!source_file)
|
|
15
|
+
return declarations;
|
|
16
|
+
const checker = program.getTypeChecker();
|
|
17
|
+
// Get the exports of the source file (module)
|
|
18
|
+
const symbol = checker.getSymbolAtLocation(source_file);
|
|
19
|
+
if (!symbol)
|
|
20
|
+
return declarations;
|
|
21
|
+
// Get the module exports
|
|
22
|
+
const exports = checker.getExportsOfModule(symbol);
|
|
23
|
+
// Process TypeScript declarations
|
|
24
|
+
const export_context = new ParseExportsContext(program, log);
|
|
25
|
+
export_context.analyze_source_file(source_file);
|
|
26
|
+
export_context.process_exports(source_file, exports, declarations);
|
|
27
|
+
}
|
|
28
|
+
return declarations;
|
|
29
|
+
};
|
|
30
|
+
// TODO temporary until proper type inference
|
|
31
|
+
export const infer_declarations_from_file_type = (file_path, declarations = []) => {
|
|
32
|
+
const extension = extname(file_path).toLowerCase();
|
|
33
|
+
switch (extension) {
|
|
34
|
+
case '.svelte': {
|
|
35
|
+
declarations.push({
|
|
36
|
+
name: 'default',
|
|
37
|
+
kind: 'component',
|
|
38
|
+
});
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case '.css': {
|
|
42
|
+
declarations.push({
|
|
43
|
+
name: 'default',
|
|
44
|
+
kind: 'css',
|
|
45
|
+
});
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case '.json': {
|
|
49
|
+
declarations.push({
|
|
50
|
+
name: 'default',
|
|
51
|
+
kind: 'json',
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return declarations;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Process TypeScript exports, identifying their kinds.
|
|
60
|
+
*/
|
|
61
|
+
export const process_ts_exports = (source_file, program, exports, declarations = [], log) => {
|
|
62
|
+
const export_context = new ParseExportsContext(program, log);
|
|
63
|
+
export_context.analyze_source_file(source_file);
|
|
64
|
+
return export_context.process_exports(source_file, exports, declarations);
|
|
65
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { Logger } from '@fuzdev/fuz_util/log.js';
|
|
3
|
+
import type { ExportDeclaration } from './parse_exports.ts';
|
|
4
|
+
/**
|
|
5
|
+
* A class to track export context and determine export kinds.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ParseExportsContext {
|
|
8
|
+
#private;
|
|
9
|
+
readonly log: Logger | undefined;
|
|
10
|
+
debug: boolean;
|
|
11
|
+
constructor(program: ts.Program, log?: Logger);
|
|
12
|
+
/**
|
|
13
|
+
* Analyze a source file to prepare for export processing.
|
|
14
|
+
*/
|
|
15
|
+
analyze_source_file(source_file: ts.SourceFile): void;
|
|
16
|
+
/**
|
|
17
|
+
* Process a list of exported symbols and identify their kinds.
|
|
18
|
+
*/
|
|
19
|
+
process_exports(source_file: ts.SourceFile, exports: Array<ts.Symbol>, declarations?: Array<ExportDeclaration>): Array<ExportDeclaration>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=parse_exports_context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse_exports_context.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/parse_exports_context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAE1D;;GAEG;AACH,qBAAa,mBAAmB;;IAQ/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,KAAK,UAAwC;gBAEjC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM;IAc7C;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,GAAG,IAAI;IAerD;;OAEG;IACH,eAAe,CACd,WAAW,EAAE,EAAE,CAAC,UAAU,EAC1B,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EACzB,YAAY,GAAE,KAAK,CAAC,iBAAiB,CAAM,GACzC,KAAK,CAAC,iBAAiB,CAAC;CA+U3B"}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* A class to track export context and determine export kinds.
|
|
4
|
+
*/
|
|
5
|
+
export class ParseExportsContext {
|
|
6
|
+
#checker;
|
|
7
|
+
// Map of source file paths to their symbols
|
|
8
|
+
#file_symbols = new Map();
|
|
9
|
+
// Cache for resolved symbols to avoid repeated resolution
|
|
10
|
+
#symbol_kind_cache = new Map();
|
|
11
|
+
log;
|
|
12
|
+
debug = process.env.DEBUG_EXPORTS === 'true';
|
|
13
|
+
constructor(program, log) {
|
|
14
|
+
this.log = log;
|
|
15
|
+
this.#checker = program.getTypeChecker();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Log a debug message if debug mode is enabled.
|
|
19
|
+
*/
|
|
20
|
+
#log(...args) {
|
|
21
|
+
if (this.debug && this.log) {
|
|
22
|
+
this.log.info(...args);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Analyze a source file to prepare for export processing.
|
|
27
|
+
*/
|
|
28
|
+
analyze_source_file(source_file) {
|
|
29
|
+
const file_path = source_file.fileName;
|
|
30
|
+
// Skip if we've already analyzed this file
|
|
31
|
+
if (this.#file_symbols.has(file_path)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// Get the source file symbol and cache it
|
|
35
|
+
const symbol = this.#checker.getSymbolAtLocation(source_file);
|
|
36
|
+
if (symbol) {
|
|
37
|
+
this.#file_symbols.set(file_path, symbol);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Process a list of exported symbols and identify their kinds.
|
|
42
|
+
*/
|
|
43
|
+
process_exports(source_file, exports, declarations = []) {
|
|
44
|
+
for (const export_symbol of exports) {
|
|
45
|
+
const name = export_symbol.name;
|
|
46
|
+
this.#log(`Determining kind for export: ${name}`);
|
|
47
|
+
const kind = this.#determine_export_kind(source_file, export_symbol);
|
|
48
|
+
declarations.push({
|
|
49
|
+
name,
|
|
50
|
+
kind,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return declarations;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Determine the kind of an export based on its symbol.
|
|
57
|
+
*/
|
|
58
|
+
#determine_export_kind(source_file, symbol) {
|
|
59
|
+
// Check if this is a type-only export (no value export)
|
|
60
|
+
if (this.#is_type_only_export(source_file, symbol)) {
|
|
61
|
+
return 'type';
|
|
62
|
+
}
|
|
63
|
+
// Get the true symbol by resolving aliases
|
|
64
|
+
const resolved_symbol = this.#resolve_symbol(symbol);
|
|
65
|
+
// Check if we've already determined this symbol's kind
|
|
66
|
+
if (this.#symbol_kind_cache.has(resolved_symbol)) {
|
|
67
|
+
return this.#symbol_kind_cache.get(resolved_symbol);
|
|
68
|
+
}
|
|
69
|
+
// Determine the kind based on declaration and type information
|
|
70
|
+
const kind = this.#infer_declaration_kind(resolved_symbol);
|
|
71
|
+
// Cache the result for future lookups
|
|
72
|
+
this.#symbol_kind_cache.set(resolved_symbol, kind);
|
|
73
|
+
return kind;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve a symbol through aliases to its original declaration.
|
|
77
|
+
*/
|
|
78
|
+
#resolve_symbol(symbol) {
|
|
79
|
+
try {
|
|
80
|
+
if (symbol.flags & ts.SymbolFlags.Alias) {
|
|
81
|
+
return this.#checker.getAliasedSymbol(symbol);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// If resolution fails, return the original symbol
|
|
86
|
+
}
|
|
87
|
+
return symbol;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Infer the declaration kind from a symbol's declaration and type information.
|
|
91
|
+
*/
|
|
92
|
+
#infer_declaration_kind(symbol) {
|
|
93
|
+
// Check symbol flags first for direct type matching
|
|
94
|
+
if (this.#is_class_symbol(symbol)) {
|
|
95
|
+
return 'class';
|
|
96
|
+
}
|
|
97
|
+
if (this.#is_function_symbol(symbol)) {
|
|
98
|
+
return 'function';
|
|
99
|
+
}
|
|
100
|
+
// If no direct match from flags, look at declarations
|
|
101
|
+
if (symbol.declarations && symbol.declarations.length > 0) {
|
|
102
|
+
const decl = symbol.declarations[0];
|
|
103
|
+
const kind_from_decl = this.#infer_kind_from_declaration(decl);
|
|
104
|
+
if (kind_from_decl) {
|
|
105
|
+
return kind_from_decl;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Check for callable type as a fallback for functions
|
|
109
|
+
if (this.#is_callable(symbol)) {
|
|
110
|
+
return 'function';
|
|
111
|
+
}
|
|
112
|
+
// Default to variable if no other type can be determined
|
|
113
|
+
return 'variable';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Check if a symbol represents a callable type (function-like).
|
|
117
|
+
*/
|
|
118
|
+
#is_callable(symbol) {
|
|
119
|
+
try {
|
|
120
|
+
// Try to get valid declaration node
|
|
121
|
+
const declaration = this.#get_valid_declaration(symbol);
|
|
122
|
+
if (!declaration) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
// Get the type at the declaration location
|
|
126
|
+
const type = this.#checker.getTypeOfSymbolAtLocation(symbol, declaration);
|
|
127
|
+
// Check if the type has call signatures (making it function-like)
|
|
128
|
+
return type.getCallSignatures().length > 0;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get a valid declaration for a symbol, preferring valueDeclaration.
|
|
136
|
+
*/
|
|
137
|
+
#get_valid_declaration(symbol) {
|
|
138
|
+
if (symbol.valueDeclaration) {
|
|
139
|
+
return symbol.valueDeclaration;
|
|
140
|
+
}
|
|
141
|
+
if (symbol.declarations && symbol.declarations.length > 0) {
|
|
142
|
+
return symbol.declarations[0];
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Infer the declaration kind from a specific declaration node.
|
|
148
|
+
*/
|
|
149
|
+
#infer_kind_from_declaration(decl) {
|
|
150
|
+
if (ts.isFunctionDeclaration(decl)) {
|
|
151
|
+
return 'function';
|
|
152
|
+
}
|
|
153
|
+
if (ts.isClassDeclaration(decl)) {
|
|
154
|
+
return 'class';
|
|
155
|
+
}
|
|
156
|
+
if (ts.isInterfaceDeclaration(decl) || ts.isTypeAliasDeclaration(decl)) {
|
|
157
|
+
return 'type';
|
|
158
|
+
}
|
|
159
|
+
if (ts.isVariableDeclaration(decl)) {
|
|
160
|
+
// Handle initializers for variable declarations
|
|
161
|
+
if (decl.initializer) {
|
|
162
|
+
if (ts.isFunctionExpression(decl.initializer) || ts.isArrowFunction(decl.initializer)) {
|
|
163
|
+
return 'function';
|
|
164
|
+
}
|
|
165
|
+
if (ts.isClassExpression(decl.initializer)) {
|
|
166
|
+
return 'class';
|
|
167
|
+
}
|
|
168
|
+
// Handle identifiers pointing to other declarations
|
|
169
|
+
if (ts.isIdentifier(decl.initializer)) {
|
|
170
|
+
try {
|
|
171
|
+
const referred_symbol = this.#checker.getSymbolAtLocation(decl.initializer);
|
|
172
|
+
if (referred_symbol) {
|
|
173
|
+
// Avoid infinite recursion by not resolving symbols here
|
|
174
|
+
if (this.#is_function_symbol(referred_symbol)) {
|
|
175
|
+
return 'function';
|
|
176
|
+
}
|
|
177
|
+
if (this.#is_class_symbol(referred_symbol)) {
|
|
178
|
+
return 'class';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Ignore failures to resolve identifiers
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// As a fallback, check if the variable's type is callable
|
|
188
|
+
try {
|
|
189
|
+
const symbol = this.#checker.getSymbolAtLocation(decl.name);
|
|
190
|
+
if (symbol && this.#is_callable(symbol)) {
|
|
191
|
+
return 'function';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Ignore errors in type checking
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if a symbol is exported as a type-only export.
|
|
202
|
+
* A type-only export means it's ONLY exported as a type with no value export.
|
|
203
|
+
*/
|
|
204
|
+
#is_type_only_export(source_file, symbol) {
|
|
205
|
+
// First, check if the symbol has an explicit type-only export
|
|
206
|
+
let has_type_only_export = false;
|
|
207
|
+
// Check if it has a corresponding value export
|
|
208
|
+
const has_value_export = this.#has_value_export(source_file, symbol);
|
|
209
|
+
// If it has both type and value exports (dual purpose), it's not type-only
|
|
210
|
+
if (has_value_export) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
// Check export declarations for explicit type-only exports
|
|
214
|
+
ts.forEachChild(source_file, (node) => {
|
|
215
|
+
if (ts.isExportDeclaration(node) &&
|
|
216
|
+
node.exportClause &&
|
|
217
|
+
ts.isNamedExports(node.exportClause)) {
|
|
218
|
+
// Check if it's a type-only export declaration (export type {...})
|
|
219
|
+
if (node.isTypeOnly) {
|
|
220
|
+
for (const specifier of node.exportClause.elements) {
|
|
221
|
+
if (specifier.name.text === symbol.name) {
|
|
222
|
+
has_type_only_export = true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
// Check if it's a specific type export (export {type X})
|
|
228
|
+
for (const specifier of node.exportClause.elements) {
|
|
229
|
+
if (specifier.name.text === symbol.name && specifier.isTypeOnly) {
|
|
230
|
+
has_type_only_export = true;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
// If explicitly marked as a type-only export, use that
|
|
237
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
238
|
+
if (has_type_only_export) {
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
// If not explicitly marked as type-only, check if the symbol itself is a type
|
|
242
|
+
// AND there's no value export for it
|
|
243
|
+
const resolved_symbol = this.#resolve_symbol(symbol);
|
|
244
|
+
return this.#is_type_symbol(resolved_symbol) && !has_value_export;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Check if a symbol has a value export in the source file.
|
|
248
|
+
*/
|
|
249
|
+
#has_value_export(source_file, symbol) {
|
|
250
|
+
let has_value_export = false;
|
|
251
|
+
// Check export declarations
|
|
252
|
+
ts.forEachChild(source_file, (node) => {
|
|
253
|
+
if (ts.isExportDeclaration(node) &&
|
|
254
|
+
node.exportClause &&
|
|
255
|
+
ts.isNamedExports(node.exportClause)) {
|
|
256
|
+
// Skip type-only exports
|
|
257
|
+
if (node.isTypeOnly)
|
|
258
|
+
return;
|
|
259
|
+
// Check if it's a regular export (not type-only)
|
|
260
|
+
for (const specifier of node.exportClause.elements) {
|
|
261
|
+
if (specifier.name.text === symbol.name && !specifier.isTypeOnly) {
|
|
262
|
+
has_value_export = true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Check for default export
|
|
267
|
+
else if (ts.isExportAssignment(node) && symbol.name === 'default') {
|
|
268
|
+
has_value_export = true;
|
|
269
|
+
}
|
|
270
|
+
// Check for direct exports (export const x = ...)
|
|
271
|
+
else if (this.#is_direct_export(node) && this.#get_export_name(node) === symbol.name) {
|
|
272
|
+
has_value_export = true;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
return has_value_export;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Check if a node is a direct export (export const/function/class).
|
|
279
|
+
*/
|
|
280
|
+
#is_direct_export(node) {
|
|
281
|
+
return ((ts.isVariableStatement(node) ||
|
|
282
|
+
ts.isFunctionDeclaration(node) ||
|
|
283
|
+
ts.isClassDeclaration(node)) &&
|
|
284
|
+
this.#has_export_modifier(node));
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Get the export name from a direct export node.
|
|
288
|
+
*/
|
|
289
|
+
#get_export_name(node) {
|
|
290
|
+
if (ts.isVariableStatement(node) && node.declarationList.declarations.length > 0) {
|
|
291
|
+
const decl = node.declarationList.declarations[0];
|
|
292
|
+
if (ts.isIdentifier(decl.name)) {
|
|
293
|
+
return decl.name.text;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else if (ts.isFunctionDeclaration(node) && node.name) {
|
|
297
|
+
return node.name.text;
|
|
298
|
+
}
|
|
299
|
+
else if (ts.isClassDeclaration(node) && node.name) {
|
|
300
|
+
return node.name.text;
|
|
301
|
+
}
|
|
302
|
+
return undefined;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Check if a node has an export modifier.
|
|
306
|
+
*/
|
|
307
|
+
#has_export_modifier(node) {
|
|
308
|
+
return ((ts.canHaveModifiers(node) &&
|
|
309
|
+
ts.getModifiers(node)?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)) ||
|
|
310
|
+
false);
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Check if a symbol is a function symbol.
|
|
314
|
+
*/
|
|
315
|
+
#is_function_symbol(symbol) {
|
|
316
|
+
return !!(symbol.flags & ts.SymbolFlags.Function || symbol.flags & ts.SymbolFlags.Method);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Check if a symbol is a class symbol.
|
|
320
|
+
*/
|
|
321
|
+
#is_class_symbol(symbol) {
|
|
322
|
+
return !!(symbol.flags & ts.SymbolFlags.Class);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Check if a symbol is a type-only symbol (interface, type alias, etc.).
|
|
326
|
+
*/
|
|
327
|
+
#is_type_symbol(symbol) {
|
|
328
|
+
return !!(symbol.flags & ts.SymbolFlags.Interface ||
|
|
329
|
+
symbol.flags & ts.SymbolFlags.TypeAlias ||
|
|
330
|
+
symbol.flags & ts.SymbolFlags.TypeParameter);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Flavored } from '@fuzdev/fuz_util/types.js';
|
|
2
|
+
import type { PathId } from '@fuzdev/fuz_util/path.js';
|
|
3
|
+
export type ImportSpecifier = Flavored<string, 'ImportSpecifier'>;
|
|
4
|
+
export declare const parse_imports: (id: PathId, contents: string, ignore_types?: boolean) => Array<ImportSpecifier>;
|
|
5
|
+
//# sourceMappingURL=parse_imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse_imports.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/parse_imports.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAExD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAC;AAIrD,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AAyBlE,eAAO,MAAM,aAAa,GACzB,IAAI,MAAM,EACV,UAAU,MAAM,EAChB,sBAAmB,KACjB,KAAK,CAAC,eAAe,CA+IvB,CAAC"}
|