functional-examples 0.0.0-alpha.1
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/README.md +148 -0
- package/dist/cli/commands/generate.d.ts +10 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +64 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +14 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +95 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +20 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +182 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +10 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +65 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +88 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +43 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/plugin-commands.d.ts +17 -0
- package/dist/cli/plugin-commands.d.ts.map +1 -0
- package/dist/cli/plugin-commands.js +45 -0
- package/dist/cli/plugin-commands.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +9 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/index.spec.d.ts +5 -0
- package/dist/config/index.spec.d.ts.map +1 -0
- package/dist/config/index.spec.js +142 -0
- package/dist/config/index.spec.js.map +1 -0
- package/dist/config/loader.d.ts +7 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +85 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merger.d.ts +27 -0
- package/dist/config/merger.d.ts.map +1 -0
- package/dist/config/merger.js +41 -0
- package/dist/config/merger.js.map +1 -0
- package/dist/config/resolver.d.ts +28 -0
- package/dist/config/resolver.d.ts.map +1 -0
- package/dist/config/resolver.js +165 -0
- package/dist/config/resolver.js.map +1 -0
- package/dist/config/schema.d.ts +53 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +42 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/types.d.ts +17 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +5 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validator.d.ts +6 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +17 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/extractors/index.d.ts +9 -0
- package/dist/extractors/index.d.ts.map +1 -0
- package/dist/extractors/index.js +9 -0
- package/dist/extractors/index.js.map +1 -0
- package/dist/extractors/loader.d.ts +19 -0
- package/dist/extractors/loader.d.ts.map +1 -0
- package/dist/extractors/loader.js +120 -0
- package/dist/extractors/loader.js.map +1 -0
- package/dist/extractors/meta-yml-fn.d.ts +19 -0
- package/dist/extractors/meta-yml-fn.d.ts.map +1 -0
- package/dist/extractors/meta-yml-fn.js +66 -0
- package/dist/extractors/meta-yml-fn.js.map +1 -0
- package/dist/extractors/meta-yml.d.ts +24 -0
- package/dist/extractors/meta-yml.d.ts.map +1 -0
- package/dist/extractors/meta-yml.js +65 -0
- package/dist/extractors/meta-yml.js.map +1 -0
- package/dist/extractors/registry.d.ts +58 -0
- package/dist/extractors/registry.d.ts.map +1 -0
- package/dist/extractors/registry.js +114 -0
- package/dist/extractors/registry.js.map +1 -0
- package/dist/extractors/registry.spec.d.ts +2 -0
- package/dist/extractors/registry.spec.d.ts.map +1 -0
- package/dist/extractors/registry.spec.js +102 -0
- package/dist/extractors/registry.spec.js.map +1 -0
- package/dist/extractors/types.d.ts +34 -0
- package/dist/extractors/types.d.ts.map +1 -0
- package/dist/extractors/types.js +8 -0
- package/dist/extractors/types.js.map +1 -0
- package/dist/extractors/yaml-frontmatter-fn.d.ts +18 -0
- package/dist/extractors/yaml-frontmatter-fn.d.ts.map +1 -0
- package/dist/extractors/yaml-frontmatter-fn.js +73 -0
- package/dist/extractors/yaml-frontmatter-fn.js.map +1 -0
- package/dist/extractors/yaml-frontmatter.d.ts +22 -0
- package/dist/extractors/yaml-frontmatter.d.ts.map +1 -0
- package/dist/extractors/yaml-frontmatter.js +83 -0
- package/dist/extractors/yaml-frontmatter.js.map +1 -0
- package/dist/extractors/yaml-frontmatter.spec.d.ts +2 -0
- package/dist/extractors/yaml-frontmatter.spec.d.ts.map +1 -0
- package/dist/extractors/yaml-frontmatter.spec.js +134 -0
- package/dist/extractors/yaml-frontmatter.spec.js.map +1 -0
- package/dist/files/index.d.ts +5 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +5 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/reader.d.ts +50 -0
- package/dist/files/reader.d.ts.map +1 -0
- package/dist/files/reader.js +62 -0
- package/dist/files/reader.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.d.ts +4 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/pipeline.d.ts +11 -0
- package/dist/plugins/pipeline.d.ts.map +1 -0
- package/dist/plugins/pipeline.js +24 -0
- package/dist/plugins/pipeline.js.map +1 -0
- package/dist/plugins/registry.d.ts +57 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +93 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/validation.d.ts +64 -0
- package/dist/plugins/validation.d.ts.map +1 -0
- package/dist/plugins/validation.js +55 -0
- package/dist/plugins/validation.js.map +1 -0
- package/dist/regions/index.d.ts +7 -0
- package/dist/regions/index.d.ts.map +1 -0
- package/dist/regions/index.js +6 -0
- package/dist/regions/index.js.map +1 -0
- package/dist/regions/languages.d.ts +15 -0
- package/dist/regions/languages.d.ts.map +1 -0
- package/dist/regions/languages.js +182 -0
- package/dist/regions/languages.js.map +1 -0
- package/dist/regions/parser.d.ts +63 -0
- package/dist/regions/parser.d.ts.map +1 -0
- package/dist/regions/parser.js +175 -0
- package/dist/regions/parser.js.map +1 -0
- package/dist/regions/parser.spec.d.ts +2 -0
- package/dist/regions/parser.spec.d.ts.map +1 -0
- package/dist/regions/parser.spec.js +190 -0
- package/dist/regions/parser.spec.js.map +1 -0
- package/dist/regions/types.d.ts +37 -0
- package/dist/regions/types.d.ts.map +1 -0
- package/dist/regions/types.js +5 -0
- package/dist/regions/types.js.map +1 -0
- package/dist/scanner/candidates.d.ts +24 -0
- package/dist/scanner/candidates.d.ts.map +1 -0
- package/dist/scanner/candidates.js +83 -0
- package/dist/scanner/candidates.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +6 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/scan.d.ts +40 -0
- package/dist/scanner/scan.d.ts.map +1 -0
- package/dist/scanner/scan.js +44 -0
- package/dist/scanner/scan.js.map +1 -0
- package/dist/scanner/scanner.d.ts +29 -0
- package/dist/scanner/scanner.d.ts.map +1 -0
- package/dist/scanner/scanner.js +296 -0
- package/dist/scanner/scanner.js.map +1 -0
- package/dist/scanner/scanner.spec.d.ts +2 -0
- package/dist/scanner/scanner.spec.d.ts.map +1 -0
- package/dist/scanner/scanner.spec.js +262 -0
- package/dist/scanner/scanner.spec.js.map +1 -0
- package/dist/scanner/types.d.ts +43 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +5 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/merger.d.ts +35 -0
- package/dist/schema/merger.d.ts.map +1 -0
- package/dist/schema/merger.js +161 -0
- package/dist/schema/merger.js.map +1 -0
- package/dist/schema/typegen.d.ts +13 -0
- package/dist/schema/typegen.d.ts.map +1 -0
- package/dist/schema/typegen.js +125 -0
- package/dist/schema/typegen.js.map +1 -0
- package/dist/schema/validator.d.ts +7 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +32 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/types/default-map.d.ts +21 -0
- package/dist/types/default-map.d.ts.map +1 -0
- package/dist/types/default-map.js +32 -0
- package/dist/types/default-map.js.map +1 -0
- package/dist/types/extended-iterable.d.ts +197 -0
- package/dist/types/extended-iterable.d.ts.map +1 -0
- package/dist/types/extended-iterable.js +769 -0
- package/dist/types/extended-iterable.js.map +1 -0
- package/dist/types/guards.d.ts +2 -0
- package/dist/types/guards.d.ts.map +1 -0
- package/dist/types/guards.js +2 -0
- package/dist/types/guards.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
declare const app: import("cli-forge").CLI<{
|
|
3
|
+
unmatched: string[];
|
|
4
|
+
'--'?: string[];
|
|
5
|
+
} & {
|
|
6
|
+
config?: string;
|
|
7
|
+
} & {} & {
|
|
8
|
+
resolvedConfig: import("../config/index.js").ResolvedConfig<Record<string, unknown>>;
|
|
9
|
+
unmatched: string[];
|
|
10
|
+
'--'?: string[];
|
|
11
|
+
config?: string;
|
|
12
|
+
}, void, import("cli-forge").CommandToChildEntry<import("cli-forge").CLI<{
|
|
13
|
+
unmatched: string[];
|
|
14
|
+
'--'?: string[];
|
|
15
|
+
} & {
|
|
16
|
+
directory?: string;
|
|
17
|
+
} & {} & {
|
|
18
|
+
config?: string;
|
|
19
|
+
} & {} & {
|
|
20
|
+
format?: "yaml" | "json" | "table";
|
|
21
|
+
} & {} & {
|
|
22
|
+
output?: string;
|
|
23
|
+
} & {} & {
|
|
24
|
+
include?: string[];
|
|
25
|
+
} & {} & {
|
|
26
|
+
exclude?: string[];
|
|
27
|
+
} & {}, Promise<void>, {}, undefined>, import("cli-forge").CLI<{
|
|
28
|
+
unmatched: string[];
|
|
29
|
+
'--'?: string[];
|
|
30
|
+
} & {
|
|
31
|
+
config?: string;
|
|
32
|
+
} & {} & {
|
|
33
|
+
resolvedConfig: import("../config/index.js").ResolvedConfig<Record<string, unknown>>;
|
|
34
|
+
unmatched: string[];
|
|
35
|
+
'--'?: string[];
|
|
36
|
+
config?: string;
|
|
37
|
+
}, void, {}, undefined>> & import("cli-forge").CommandToChildEntry<import("cli-forge").CLI<{
|
|
38
|
+
unmatched: string[];
|
|
39
|
+
'--'?: string[];
|
|
40
|
+
} & {
|
|
41
|
+
strict?: boolean;
|
|
42
|
+
} & {}, Promise<void>, {}, undefined>, import("cli-forge").CLI<{
|
|
43
|
+
unmatched: string[];
|
|
44
|
+
'--'?: string[];
|
|
45
|
+
} & {
|
|
46
|
+
config?: string;
|
|
47
|
+
} & {} & {
|
|
48
|
+
resolvedConfig: import("../config/index.js").ResolvedConfig<Record<string, unknown>>;
|
|
49
|
+
unmatched: string[];
|
|
50
|
+
'--'?: string[];
|
|
51
|
+
config?: string;
|
|
52
|
+
}, void, {}, undefined>> & import("cli-forge").CommandToChildEntry<import("cli-forge").CLI<{
|
|
53
|
+
unmatched: string[];
|
|
54
|
+
'--'?: string[];
|
|
55
|
+
} & {
|
|
56
|
+
format?: "ts" | "json";
|
|
57
|
+
} & {} & {
|
|
58
|
+
output?: string;
|
|
59
|
+
} & {} & {
|
|
60
|
+
force?: boolean;
|
|
61
|
+
} & {}, Promise<void>, {}, undefined>, import("cli-forge").CLI<{
|
|
62
|
+
unmatched: string[];
|
|
63
|
+
'--'?: string[];
|
|
64
|
+
} & {
|
|
65
|
+
config?: string;
|
|
66
|
+
} & {} & {
|
|
67
|
+
resolvedConfig: import("../config/index.js").ResolvedConfig<Record<string, unknown>>;
|
|
68
|
+
unmatched: string[];
|
|
69
|
+
'--'?: string[];
|
|
70
|
+
config?: string;
|
|
71
|
+
}, void, {}, undefined>> & import("cli-forge").CommandToChildEntry<import("cli-forge").CLI<{
|
|
72
|
+
unmatched: string[];
|
|
73
|
+
'--'?: string[];
|
|
74
|
+
} & {
|
|
75
|
+
output?: string;
|
|
76
|
+
} & {}, Promise<void>, {}, undefined>, import("cli-forge").CLI<{
|
|
77
|
+
unmatched: string[];
|
|
78
|
+
'--'?: string[];
|
|
79
|
+
} & {
|
|
80
|
+
config?: string;
|
|
81
|
+
} & {} & {
|
|
82
|
+
resolvedConfig: import("../config/index.js").ResolvedConfig<Record<string, unknown>>;
|
|
83
|
+
unmatched: string[];
|
|
84
|
+
'--'?: string[];
|
|
85
|
+
config?: string;
|
|
86
|
+
}, void, {}, undefined>>, undefined>;
|
|
87
|
+
export default app;
|
|
88
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AASA,QAAA,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCA+B8D,CAAC;AAMxE,eAAe,GAAG,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cli } from 'cli-forge';
|
|
3
|
+
import { findConfigFile, loadConfig, resolveConfig } from '../config/index.js';
|
|
4
|
+
import { generateCommand } from './commands/generate.js';
|
|
5
|
+
import { initCommand } from './commands/init.js';
|
|
6
|
+
import { scanCommand } from './commands/scan.js';
|
|
7
|
+
import { validateCommand } from './commands/validate.js';
|
|
8
|
+
import { loadPluginCommands } from './plugin-commands.js';
|
|
9
|
+
const app = cli('functional-examples', {
|
|
10
|
+
description: 'Extract and manage code examples',
|
|
11
|
+
builder: (args) => args
|
|
12
|
+
.option('config', {
|
|
13
|
+
alias: ['c'],
|
|
14
|
+
type: 'string',
|
|
15
|
+
})
|
|
16
|
+
.middleware(async (args) => {
|
|
17
|
+
const configPath = args.config ?? (await findConfigFile(process.cwd()));
|
|
18
|
+
if (!configPath) {
|
|
19
|
+
throw new Error('Unable to locate config file');
|
|
20
|
+
}
|
|
21
|
+
args.config = configPath;
|
|
22
|
+
const rawConfig = await loadConfig(configPath);
|
|
23
|
+
const config = await resolveConfig(rawConfig);
|
|
24
|
+
return {
|
|
25
|
+
...args,
|
|
26
|
+
resolvedConfig: config,
|
|
27
|
+
};
|
|
28
|
+
})
|
|
29
|
+
.init(async (cli, args) => {
|
|
30
|
+
const plugins = args.resolvedConfig.plugins;
|
|
31
|
+
const pluginCLIs = await loadPluginCommands(plugins, args.resolvedConfig);
|
|
32
|
+
cli.commands(pluginCLIs);
|
|
33
|
+
}),
|
|
34
|
+
})
|
|
35
|
+
.version('0.0.1')
|
|
36
|
+
.commands(scanCommand, validateCommand, initCommand, generateCommand);
|
|
37
|
+
async function main() {
|
|
38
|
+
app.forge();
|
|
39
|
+
}
|
|
40
|
+
export default app;
|
|
41
|
+
// Run CLI when this is the entry point
|
|
42
|
+
main();
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,GAAG,GAAG,GAAG,CAAC,qBAAqB,EAAE;IACrC,WAAW,EAAE,kCAAkC;IAC/C,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAChB,IAAI;SACD,MAAM,CAAC,QAAQ,EAAE;QAChB,KAAK,EAAE,CAAC,GAAG,CAAC;QACZ,IAAI,EAAE,QAAQ;KACf,CAAC;SACD,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;QACzB,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;QAC9C,OAAO;YACL,GAAG,IAAI;YACP,cAAc,EAAE,MAAM;SACvB,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAC5C,MAAM,UAAU,GAAG,MAAM,kBAAkB,CACzC,OAAO,EACP,IAAI,CAAC,cAAc,CACpB,CAAC;QACF,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC,CAAC;CACP,CAAC;KACC,OAAO,CAAC,OAAO,CAAC;KAChB,QAAQ,CAAC,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;AAExE,KAAK,UAAU,IAAI;IACjB,GAAG,CAAC,KAAK,EAAE,CAAC;AACd,CAAC;AAED,eAAe,GAAG,CAAC;AAEnB,uCAAuC;AACvC,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CLI } from 'cli-forge';
|
|
2
|
+
import type { Plugin, ResolvedConfig } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the CLI namespace for a plugin.
|
|
5
|
+
* Strips @functional-examples/ scope, keeps everything else.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getCommandNamespace(pluginName: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve commands from a plugin (handles static array or function).
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolvePluginCommands<T>(plugin: Plugin<T>, config: ResolvedConfig<T>): Promise<CLI[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Load all plugin commands, wrapping each plugin's commands
|
|
14
|
+
* under its namespace.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadPluginCommands<T>(plugins: Plugin<T>[], config: ResolvedConfig<T>): Promise<CLI[]>;
|
|
17
|
+
//# sourceMappingURL=plugin-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-commands.d.ts","sourceRoot":"","sources":["../../src/cli/plugin-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,GAAG,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EACjB,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,GAAG,EAAE,CAAC,CAShB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EACpB,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,GAAG,EAAE,CAAC,CAsBhB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { cli } from 'cli-forge';
|
|
2
|
+
/**
|
|
3
|
+
* Get the CLI namespace for a plugin.
|
|
4
|
+
* Strips @functional-examples/ scope, keeps everything else.
|
|
5
|
+
*/
|
|
6
|
+
export function getCommandNamespace(pluginName) {
|
|
7
|
+
if (pluginName.startsWith('@functional-examples/')) {
|
|
8
|
+
return pluginName.replace('@functional-examples/', '');
|
|
9
|
+
}
|
|
10
|
+
return pluginName;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve commands from a plugin (handles static array or function).
|
|
14
|
+
*/
|
|
15
|
+
export async function resolvePluginCommands(plugin, config) {
|
|
16
|
+
if (!plugin.commands)
|
|
17
|
+
return [];
|
|
18
|
+
const commands = typeof plugin.commands === 'function'
|
|
19
|
+
? plugin.commands(config)
|
|
20
|
+
: plugin.commands;
|
|
21
|
+
return Promise.resolve(commands);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Load all plugin commands, wrapping each plugin's commands
|
|
25
|
+
* under its namespace.
|
|
26
|
+
*/
|
|
27
|
+
export async function loadPluginCommands(plugins, config) {
|
|
28
|
+
const result = [];
|
|
29
|
+
for (const plugin of plugins) {
|
|
30
|
+
const commands = await resolvePluginCommands(plugin, config);
|
|
31
|
+
if (commands.length === 0)
|
|
32
|
+
continue;
|
|
33
|
+
const namespace = getCommandNamespace(plugin.name);
|
|
34
|
+
// Wrap commands under namespace
|
|
35
|
+
const namespaced = cli(namespace, {
|
|
36
|
+
description: `Commands from ${plugin.name}`,
|
|
37
|
+
});
|
|
38
|
+
for (const command of commands) {
|
|
39
|
+
namespaced.command(command);
|
|
40
|
+
}
|
|
41
|
+
result.push(namespaced);
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=plugin-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-commands.js","sourceRoot":"","sources":["../../src/cli/plugin-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAY,MAAM,WAAW,CAAC;AAG1C;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,IAAI,UAAU,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACnD,OAAO,UAAU,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAiB,EACjB,MAAyB;IAEzB,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEhC,MAAM,QAAQ,GACZ,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU;QACnC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;IAEtB,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAoB,EACpB,MAAyB;IAEzB,MAAM,MAAM,GAAU,EAAE,CAAC;IAEzB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEpC,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEnD,gCAAgC;QAChC,MAAM,UAAU,GAAG,GAAG,CAAC,SAAS,EAAE;YAChC,WAAW,EAAE,iBAAiB,MAAM,CAAC,IAAI,EAAE;SAC5C,CAAC,CAAC;QAEH,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration system for functional-examples
|
|
3
|
+
*/
|
|
4
|
+
export { findConfigFile, loadConfig } from './loader.js';
|
|
5
|
+
export { mergeConfigs } from './merger.js';
|
|
6
|
+
export { resolveConfig, type ConfigValidationError, type ResolvedConfig, } from './resolver.js';
|
|
7
|
+
export { ConfigSchema, ExtractorConfigSchema, ExtractorReferenceSchema, ScanConfigSchema, } from './schema.js';
|
|
8
|
+
export type { ConfigSchemaType } from './schema.js';
|
|
9
|
+
export type { Config, ExtractorConfig, ScanConfig } from './types.js';
|
|
10
|
+
export { validateConfig } from './validator.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration system for functional-examples
|
|
3
|
+
*/
|
|
4
|
+
export { findConfigFile, loadConfig } from './loader.js';
|
|
5
|
+
export { mergeConfigs } from './merger.js';
|
|
6
|
+
export { resolveConfig, } from './resolver.js';
|
|
7
|
+
export { ConfigSchema, ExtractorConfigSchema, ExtractorReferenceSchema, ScanConfigSchema, } from './schema.js';
|
|
8
|
+
export { validateConfig } from './validator.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,aAAa,GAGd,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.d.ts","sourceRoot":"","sources":["../../src/config/index.spec.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for configuration system
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect } from 'vitest';
|
|
5
|
+
import { findConfigFile, validateConfig, mergeConfigs } from './index.js';
|
|
6
|
+
describe('Config System', () => {
|
|
7
|
+
describe('findConfigFile', () => {
|
|
8
|
+
// Test with a directory that definitely won't have a config
|
|
9
|
+
it('should return null when no config exists', async () => {
|
|
10
|
+
const configPath = await findConfigFile('/nonexistent-path-12345');
|
|
11
|
+
expect(configPath).toBeNull();
|
|
12
|
+
});
|
|
13
|
+
it('should search for various config file patterns', async () => {
|
|
14
|
+
// This test verifies the function doesn't throw and handles paths correctly
|
|
15
|
+
// In a real test environment, we would use a temp directory with actual config files
|
|
16
|
+
const configPath = await findConfigFile(process.cwd());
|
|
17
|
+
// The result depends on whether a config file exists - we just verify no errors
|
|
18
|
+
expect(configPath === null || typeof configPath === 'string').toBe(true);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe('validateConfig', () => {
|
|
22
|
+
it('should pass valid config', () => {
|
|
23
|
+
const config = {
|
|
24
|
+
extractors: [
|
|
25
|
+
'@scope/extractor',
|
|
26
|
+
{
|
|
27
|
+
name: 'my-extractor',
|
|
28
|
+
module: '@scope/extractor',
|
|
29
|
+
options: { key: 'value' },
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
scan: {
|
|
33
|
+
include: ['examples/**/*'],
|
|
34
|
+
exclude: ['**/node_modules/**'],
|
|
35
|
+
recursive: true,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
const errors = validateConfig(config);
|
|
39
|
+
expect(errors).toHaveLength(0);
|
|
40
|
+
});
|
|
41
|
+
it('should fail with empty extractors', () => {
|
|
42
|
+
const config = {
|
|
43
|
+
extractors: [],
|
|
44
|
+
};
|
|
45
|
+
const errors = validateConfig(config);
|
|
46
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
47
|
+
expect(errors[0]).toMatchObject({
|
|
48
|
+
path: 'extractors',
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
it('should fail with empty extractor string', () => {
|
|
52
|
+
const config = {
|
|
53
|
+
extractors: [''],
|
|
54
|
+
};
|
|
55
|
+
const errors = validateConfig(config);
|
|
56
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
57
|
+
expect(errors[0].path).toMatch(/extractors/);
|
|
58
|
+
});
|
|
59
|
+
it('should fail with invalid extractor config', () => {
|
|
60
|
+
const config = {
|
|
61
|
+
extractors: [
|
|
62
|
+
{
|
|
63
|
+
name: 'test',
|
|
64
|
+
module: '',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
const errors = validateConfig(config);
|
|
69
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
70
|
+
expect(errors[0].path).toMatch(/extractors.*module/);
|
|
71
|
+
});
|
|
72
|
+
it('should validate scan include patterns', () => {
|
|
73
|
+
const config = {
|
|
74
|
+
extractors: ['@scope/test'],
|
|
75
|
+
scan: {
|
|
76
|
+
include: [''],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
const errors = validateConfig(config);
|
|
80
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
81
|
+
expect(errors.some((e) => e.path.includes('scan') && e.path.includes('include'))).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
it('should validate scan exclude patterns', () => {
|
|
84
|
+
const config = {
|
|
85
|
+
extractors: ['@scope/test'],
|
|
86
|
+
scan: {
|
|
87
|
+
exclude: ['', 'valid'],
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
const errors = validateConfig(config);
|
|
91
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
92
|
+
expect(errors.some((e) => e.path.includes('scan') && e.path.includes('exclude'))).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('mergeConfigs', () => {
|
|
96
|
+
it('should merge extractor arrays', () => {
|
|
97
|
+
const config1 = {
|
|
98
|
+
extractors: ['extractor1'],
|
|
99
|
+
};
|
|
100
|
+
const config2 = {
|
|
101
|
+
extractors: ['extractor2'],
|
|
102
|
+
};
|
|
103
|
+
const merged = mergeConfigs(config1, config2);
|
|
104
|
+
expect(merged.extractors).toEqual(['extractor1', 'extractor2']);
|
|
105
|
+
});
|
|
106
|
+
it('should deep merge scan config', () => {
|
|
107
|
+
const config1 = {
|
|
108
|
+
scan: { include: ['**/*.ts'] },
|
|
109
|
+
};
|
|
110
|
+
const config2 = {
|
|
111
|
+
scan: { exclude: ['**/test/**'] },
|
|
112
|
+
};
|
|
113
|
+
const merged = mergeConfigs(config1, config2);
|
|
114
|
+
expect(merged.scan).toEqual({
|
|
115
|
+
include: ['**/*.ts'],
|
|
116
|
+
exclude: ['**/test/**'],
|
|
117
|
+
recursive: true,
|
|
118
|
+
fileExtensions: ['.ts', '.js', '.tsx', '.jsx', '.py', '.rb', '.go'],
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
it('should provide defaults for scan config', () => {
|
|
122
|
+
const config = {};
|
|
123
|
+
const merged = mergeConfigs(config);
|
|
124
|
+
expect(merged.scan).toEqual({
|
|
125
|
+
include: [],
|
|
126
|
+
exclude: [],
|
|
127
|
+
recursive: true,
|
|
128
|
+
fileExtensions: ['.ts', '.js', '.tsx', '.jsx', '.py', '.rb', '.go'],
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
it('should handle null configs', () => {
|
|
132
|
+
const merged = mergeConfigs(null, undefined, {});
|
|
133
|
+
expect(merged.scan).toEqual({
|
|
134
|
+
include: [],
|
|
135
|
+
exclude: [],
|
|
136
|
+
recursive: true,
|
|
137
|
+
fileExtensions: ['.ts', '.js', '.tsx', '.jsx', '.py', '.rb', '.go'],
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
//# sourceMappingURL=index.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.js","sourceRoot":"","sources":["../../src/config/index.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file discovery and loading
|
|
3
|
+
*/
|
|
4
|
+
import type { ConfigWithRoot } from './types.js';
|
|
5
|
+
export declare function findConfigFile(cwd?: string): Promise<string | null>;
|
|
6
|
+
export declare function loadConfig<TMetadata = Record<string, unknown>>(configPath: string): Promise<ConfigWithRoot<TMetadata>>;
|
|
7
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAU,cAAc,EAAE,MAAM,YAAY,CAAC;AAiBzD,wBAAsB,cAAc,CAClC,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBxB;AAED,wBAAsB,UAAU,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAQpC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration file discovery and loading
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import path, { dirname } from 'node:path';
|
|
6
|
+
import { parseJson } from '@functional-examples/devkit';
|
|
7
|
+
const CONFIG_PATTERNS = [
|
|
8
|
+
'functional-examples.config',
|
|
9
|
+
'.functional-examples',
|
|
10
|
+
'functional-examples',
|
|
11
|
+
'.functional-examplesrc',
|
|
12
|
+
];
|
|
13
|
+
const SUPPORTED_EXTENSIONS = [
|
|
14
|
+
'.ts',
|
|
15
|
+
'.mts',
|
|
16
|
+
'.cts',
|
|
17
|
+
'.json',
|
|
18
|
+
'.jsonc',
|
|
19
|
+
];
|
|
20
|
+
export async function findConfigFile(cwd = process.cwd()) {
|
|
21
|
+
const checkedPaths = [];
|
|
22
|
+
for (const currentDir of getSearchPath(cwd)) {
|
|
23
|
+
for (const pattern of CONFIG_PATTERNS) {
|
|
24
|
+
for (const ext of SUPPORTED_EXTENSIONS) {
|
|
25
|
+
const configPath = path.join(currentDir, `${pattern}${ext}`);
|
|
26
|
+
checkedPaths.push(configPath);
|
|
27
|
+
if (existsSync(configPath)) {
|
|
28
|
+
return configPath;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
export async function loadConfig(configPath) {
|
|
36
|
+
const ext = path.extname(configPath);
|
|
37
|
+
if (ext === '.json' || ext === '.jsonc') {
|
|
38
|
+
return loadJsonConfig(configPath);
|
|
39
|
+
}
|
|
40
|
+
return loadTsConfig(configPath);
|
|
41
|
+
}
|
|
42
|
+
async function loadJsonConfig(configPath) {
|
|
43
|
+
const { readFile } = await import('node:fs/promises');
|
|
44
|
+
const content = await readFile(configPath, 'utf-8');
|
|
45
|
+
const config = await parseJson(content, configPath);
|
|
46
|
+
const configDir = dirname(configPath);
|
|
47
|
+
const root = config.root ? path.resolve(configDir, config.root) : configDir;
|
|
48
|
+
return {
|
|
49
|
+
...config,
|
|
50
|
+
root,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async function loadTsConfig(configPath) {
|
|
54
|
+
const { createJiti } = await import('jiti');
|
|
55
|
+
// Use config file path as base for module resolution
|
|
56
|
+
// This ensures workspace packages can be resolved from the config's location
|
|
57
|
+
const jiti = createJiti(configPath, {
|
|
58
|
+
interopDefault: true,
|
|
59
|
+
});
|
|
60
|
+
const module = await jiti.import(configPath);
|
|
61
|
+
// Handle default export or direct config
|
|
62
|
+
const config = module.default ?? module;
|
|
63
|
+
const configDir = dirname(configPath);
|
|
64
|
+
const root = config.root ? path.resolve(configDir, config.root) : configDir;
|
|
65
|
+
return {
|
|
66
|
+
...config,
|
|
67
|
+
root,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function* getSearchPath(cwd) {
|
|
71
|
+
let current = path.resolve(cwd);
|
|
72
|
+
while (true) {
|
|
73
|
+
yield current;
|
|
74
|
+
const parent = path.dirname(current);
|
|
75
|
+
if (parent === current) {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
current = parent;
|
|
79
|
+
if (current === '/' ||
|
|
80
|
+
(process.platform === 'win32' && current.match(/^[A-Z]:\\$/))) {
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep merge for configuration sources
|
|
3
|
+
*/
|
|
4
|
+
import type { PathMapping } from '../scanner/types.js';
|
|
5
|
+
import type { Config, ExtractorConfigOrFunction, ScanConfig } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Merged configuration with all required fields
|
|
8
|
+
*/
|
|
9
|
+
export interface MergedConfig<TMetadata = Record<string, unknown>> {
|
|
10
|
+
extractors: ExtractorConfigOrFunction<TMetadata>[];
|
|
11
|
+
scan: Required<ScanConfig>;
|
|
12
|
+
pathMappings: PathMapping[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Merge multiple configuration sources with later configs taking precedence.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const config = mergeConfigs(
|
|
20
|
+
* defaultConfig,
|
|
21
|
+
* projectConfig,
|
|
22
|
+
* cliOverrides
|
|
23
|
+
* );
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function mergeConfigs<TMetadata = Record<string, unknown>>(...configs: Array<Partial<Config<TMetadata>> | null | undefined>): MergedConfig<TMetadata>;
|
|
27
|
+
//# sourceMappingURL=merger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merger.d.ts","sourceRoot":"","sources":["../../src/config/merger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/D,UAAU,EAAE,yBAAyB,CAAC,SAAS,CAAC,EAAE,CAAC;IACnD,IAAI,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,GAAG,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GAC/D,YAAY,CAAC,SAAS,CAAC,CA4BzB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep merge for configuration sources
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Merge multiple configuration sources with later configs taking precedence.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const config = mergeConfigs(
|
|
10
|
+
* defaultConfig,
|
|
11
|
+
* projectConfig,
|
|
12
|
+
* cliOverrides
|
|
13
|
+
* );
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function mergeConfigs(...configs) {
|
|
17
|
+
const defaults = {
|
|
18
|
+
include: ['**/*'],
|
|
19
|
+
exclude: ['**/node_modules/**', '**/dist/**', '**/.git/**'],
|
|
20
|
+
root: '.',
|
|
21
|
+
};
|
|
22
|
+
const mergedExtractors = [];
|
|
23
|
+
const mergedPathMappings = [];
|
|
24
|
+
const mergedScan = {};
|
|
25
|
+
for (const config of configs) {
|
|
26
|
+
if (!config)
|
|
27
|
+
continue;
|
|
28
|
+
if (config.pathMappings) {
|
|
29
|
+
mergedPathMappings.push(...config.pathMappings);
|
|
30
|
+
}
|
|
31
|
+
if (config.scan) {
|
|
32
|
+
Object.assign(mergedScan, config.scan);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
extractors: mergedExtractors,
|
|
37
|
+
scan: { ...defaults, ...mergedScan },
|
|
38
|
+
pathMappings: mergedPathMappings,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=merger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merger.js","sourceRoot":"","sources":["../../src/config/merger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAG,OAA6D;IAEhE,MAAM,QAAQ,GAAyB;QACrC,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,OAAO,EAAE,CAAC,oBAAoB,EAAE,YAAY,EAAE,YAAY,CAAC;QAC3D,IAAI,EAAE,GAAG;KACV,CAAC;IAEF,MAAM,gBAAgB,GAA2C,EAAE,CAAC;IACpE,MAAM,kBAAkB,GAAkB,EAAE,CAAC;IAC7C,MAAM,UAAU,GAAwB,EAAE,CAAC;IAE3C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,kBAAkB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO;QACL,UAAU,EAAE,gBAAgB;QAC5B,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,UAAU,EAAE;QACpC,YAAY,EAAE,kBAAkB;KACjC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolver - converts config references to actual extractors
|
|
3
|
+
*/
|
|
4
|
+
import type { ResolvedConfig } from '../types/index.js';
|
|
5
|
+
import type { ConfigWithRoot } from './types.js';
|
|
6
|
+
export type { ConfigValidationError, ResolvedConfig } from '../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a configuration to actual extractor instances.
|
|
9
|
+
*
|
|
10
|
+
* If no extractors are specified, attempts to auto-detect installed extractors.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { resolveConfig } from 'functional-examples';
|
|
15
|
+
*
|
|
16
|
+
* // Auto-detect extractors
|
|
17
|
+
* const config = await resolveConfig({});
|
|
18
|
+
*
|
|
19
|
+
* // Use with scanExamples
|
|
20
|
+
* const result = await scanExamples({
|
|
21
|
+
* root: './examples',
|
|
22
|
+
* extractors: config.extractors,
|
|
23
|
+
* pathMappings: config.pathMappings,
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveConfig<TMetadata = Record<string, unknown>>(config: ConfigWithRoot<TMetadata>): Promise<ResolvedConfig<TMetadata>>;
|
|
28
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/config/resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAIV,cAAc,EAEf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAkB/E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,aAAa,CAAC,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,MAAM,EAAE,cAAc,CAAC,SAAS,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CA0EpC"}
|