argsbarg 6.1.2 → 6.1.3
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/CHANGELOG.md +65 -1
- package/README.md +17 -19
- package/bin/argsbarg +10 -0
- package/docs/README.md +4 -3
- package/docs/ai-skills.md +4 -2
- package/docs/bundled-docs.md +50 -25
- package/docs/cli-program.md +52 -10
- package/docs/config-schema.md +10 -11
- package/docs/configure.md +2 -0
- package/docs/decisions.md +40 -0
- package/docs/developing.md +43 -5
- package/docs/http-server.md +171 -0
- package/docs/json-schema-subset.md +51 -0
- package/docs/mcp.md +4 -2
- package/docs/output-schema.md +55 -62
- package/examples/formats.ts +6 -6
- package/examples/full-example/Formula/full-example.rb +35 -0
- package/examples/full-example/README.md +20 -21
- package/examples/full-example/docs/README.md +1 -1
- package/examples/full-example/docs/cli-schema.json +1790 -98
- package/examples/full-example/docs/cli.md +1990 -0
- package/examples/full-example/docs/http.md +28 -29
- package/examples/full-example/docs/mcp.md +8 -22
- package/examples/full-example/docs/openapi.json +783 -50
- package/examples/full-example/docs/skill.md +10 -10
- package/examples/full-example/justfile +11 -1
- package/examples/full-example/src/commands/render-json/__generated__/RenderJsonInputSchema.json +15 -0
- package/examples/full-example/src/commands/render-json/__generated__/index.ts +5 -0
- package/examples/full-example/src/commands/render-json/command.test.ts +46 -0
- package/examples/full-example/src/commands/render-json/command.ts +30 -0
- package/examples/full-example/src/commands/render-json/types.ts +9 -0
- package/examples/full-example/src/commands/status/__generated__/StatusJsonOutputSchema.json +15 -0
- package/examples/full-example/src/commands/status/__generated__/index.ts +2 -2
- package/examples/full-example/src/commands/status/command.ts +5 -13
- package/examples/full-example/src/commands/status/types.ts +1 -14
- package/examples/full-example/src/commands/workspaces/__generated__/WorkspaceNameInputSchema.json +15 -0
- package/examples/full-example/src/commands/workspaces/__generated__/index.ts +5 -0
- package/examples/full-example/src/commands/workspaces/command.test.ts +58 -0
- package/examples/full-example/src/commands/workspaces/command.ts +94 -0
- package/examples/full-example/src/commands/workspaces/types.ts +6 -0
- package/examples/full-example/src/db/index.test.ts +86 -0
- package/examples/full-example/src/db/index.ts +101 -0
- package/examples/full-example/src/db/migrate.test.ts +35 -0
- package/examples/full-example/src/db/migrate.ts +69 -0
- package/examples/full-example/src/db/migrations/001_workspaces.sql +6 -0
- package/examples/full-example/src/db/tables/workspaces.ts +66 -0
- package/examples/full-example/src/program.ts +11 -36
- package/examples/full-example/src/types/argsbarg.d.ts +11 -0
- package/examples/full-example/src/types/md.d.ts +4 -0
- package/examples/full-example/tsconfig.json +5 -2
- package/examples/mcp-test.ts +1 -2
- package/examples/minimal.ts +1 -7
- package/examples/nested.ts +1 -2
- package/examples/option-required.ts +1 -1
- package/examples/servers.ts +4 -5
- package/index.d.ts +431 -136
- package/package.json +19 -2
- package/src/builtins/builtins.test.ts +7 -7
- package/src/builtins/completion-bash.ts +1 -1
- package/src/builtins/completion-fish.ts +1 -1
- package/src/builtins/completion-group.ts +4 -4
- package/src/builtins/completion-simulate-shared.ts +9 -0
- package/src/builtins/completion-zsh.ts +1 -1
- package/src/builtins/config.test.ts +3 -3
- package/src/builtins/config.ts +9 -9
- package/src/builtins/configure-copy.ts +2 -2
- package/src/builtins/configure.ts +4 -4
- package/src/builtins/dispatch.ts +19 -18
- package/src/builtins/export.ts +7 -5
- package/src/builtins/http.ts +68 -0
- package/src/builtins/mcp.ts +28 -4
- package/src/builtins/presentation.ts +6 -6
- package/src/builtins/registry.ts +6 -6
- package/src/builtins/scopes.ts +2 -2
- package/src/builtins/version.ts +1 -1
- package/src/cli-tool/full-example-capabilities.test.ts +10 -15
- package/src/cli-tool/main.ts +1 -1
- package/src/cli-tool/program.ts +3 -2
- package/src/cli-tool/prompt.ts +1 -1
- package/src/cli-tool/run-schemagen.ts +1 -3
- package/src/cli-tool/schemagen/cleanup.ts +6 -7
- package/src/cli-tool/schemagen/discover-schema-roots.ts +66 -120
- package/src/cli-tool/schemagen/index.ts +2 -2
- package/src/cli-tool/schemagen/names.ts +8 -13
- package/src/cli-tool/schemagen/run.ts +21 -28
- package/src/cli-tool/schemagen/schemagen.test.ts +136 -46
- package/src/config/bindings.test.ts +1 -1
- package/src/config/bindings.ts +1 -1
- package/src/config/bootstrap.test.ts +1 -1
- package/src/config/bootstrap.ts +36 -4
- package/src/config/context.test.ts +1 -1
- package/src/config/context.ts +1 -1
- package/src/config/entry.ts +1 -1
- package/src/config/file.test.ts +1 -1
- package/src/config/file.ts +3 -3
- package/src/config/manifest.ts +1 -1
- package/src/config/resolve.test.ts +1 -1
- package/src/config/resolve.ts +1 -1
- package/src/config/schema.ts +1 -1
- package/src/config/validate.ts +1 -1
- package/src/{install → configure/artifacts}/binary-placement.test.ts +1 -1
- package/src/{install → configure/artifacts}/binary-placement.ts +1 -1
- package/src/{install → configure/artifacts}/gh-release-update.ts +1 -1
- package/src/{install → configure/artifacts}/install-validate.test.ts +3 -3
- package/src/{install → configure/artifacts}/mcp-config.ts +1 -1
- package/src/{install → configure/artifacts}/mcp-opencode.test.ts +1 -1
- package/src/{install → configure/artifacts}/mcp-opencode.ts +1 -1
- package/src/{install → configure/artifacts}/paths.ts +5 -5
- package/src/configure/artifacts/plan.ts +24 -0
- package/src/{install → configure/artifacts}/status.test.ts +1 -1
- package/src/{install → configure/artifacts}/status.ts +2 -2
- package/src/{install → configure/artifacts}/target-base.ts +1 -1
- package/src/{install → configure/artifacts}/target-detect.ts +1 -1
- package/src/{install → configure/artifacts}/target-effective.ts +3 -9
- package/src/{install → configure/artifacts}/target-mcp-cli.ts +1 -1
- package/src/{install → configure/artifacts}/target-mcp-json.ts +1 -1
- package/src/{install → configure/artifacts}/target-plan-build.ts +2 -2
- package/src/{install → configure/artifacts}/target-registry.ts +2 -2
- package/src/{install → configure/artifacts}/target-scope.ts +3 -3
- package/src/{install → configure/artifacts}/target-skill.ts +1 -1
- package/src/{install → configure/artifacts}/target-types.ts +2 -2
- package/src/{install → configure/artifacts}/targets/app.ts +5 -5
- package/src/{install → configure/artifacts}/targets/chatgpt-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-code-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-desktop-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/claude-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/codex-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/codex-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/configure.ts +5 -5
- package/src/{install → configure/artifacts}/targets/cursor-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/cursor-skill.ts +2 -2
- package/src/{install → configure/artifacts}/targets/index.ts +1 -1
- package/src/{install → configure/artifacts}/targets/openclaw-mcp.ts +2 -2
- package/src/{install → configure/artifacts}/targets/openclaw-skill.ts +3 -3
- package/src/{install → configure/artifacts}/targets/opencode-mcp.ts +5 -5
- package/src/{install → configure/artifacts}/targets/opencode-skill.ts +3 -3
- package/src/{install → configure/artifacts}/targets.test.ts +1 -1
- package/src/{install → configure/artifacts}/uninstall.ts +1 -1
- package/src/configure/configure.test.ts +11 -11
- package/src/configure/index.ts +14 -14
- package/src/configure/prompt.ts +2 -2
- package/src/{context.ts → core/context.ts} +26 -20
- package/src/{json-leaf.test.ts → core/json-leaf.test.ts} +4 -4
- package/src/{leaf-inputs.test.ts → core/leaf-inputs.test.ts} +7 -7
- package/src/{leaf-inputs.ts → core/leaf-inputs.ts} +16 -12
- package/src/{parse.test.ts → core/parse.test.ts} +97 -109
- package/src/{parse.ts → core/parse.ts} +129 -31
- package/src/{schema.ts → core/schema.ts} +25 -13
- package/src/{types.ts → core/types.ts} +225 -35
- package/src/{validate.ts → core/validate.ts} +39 -29
- package/src/docs/builtin.ts +8 -19
- package/src/docs/{api-guide.test.ts → cli-guide.test.ts} +21 -21
- package/src/docs/{api-guide.ts → cli-guide.ts} +45 -16
- package/src/docs/docs.test.ts +76 -41
- package/src/docs/http-guide.ts +37 -34
- package/src/docs/mcp-guide.ts +12 -14
- package/src/docs/mcp-resources.test.ts +2 -3
- package/src/docs/mcp-resources.ts +6 -11
- package/src/docs/resolve.ts +22 -30
- package/src/docs/save.ts +3 -3
- package/src/exports/cli.ts +47 -0
- package/src/exports/headless.ts +13 -0
- package/src/exports/http.ts +6 -0
- package/src/exports/mcp.ts +6 -0
- package/src/{headless.test.ts → headless/routing.test.ts} +3 -3
- package/src/{headless.ts → headless/routing.ts} +3 -3
- package/src/headless/tool-call.ts +114 -46
- package/src/help.test.ts +152 -0
- package/src/help.ts +3 -3
- package/src/hooks/builtin.ts +20 -0
- package/src/hooks/run.ts +142 -0
- package/src/http/openapi.ts +182 -0
- package/src/http/readiness.ts +78 -0
- package/src/{api → http}/result.ts +16 -5
- package/src/http/routes.ts +329 -0
- package/src/http/server.ts +225 -0
- package/src/index.ts +36 -25
- package/src/log/ecs.test.ts +43 -0
- package/src/log/ecs.ts +59 -0
- package/src/log/emitter.ts +166 -0
- package/src/mcp/bundle.ts +2 -2
- package/src/mcp/claude.test.ts +1 -1
- package/src/mcp/claude.ts +4 -4
- package/src/{hidden-mcpb.test.ts → mcp/hidden-mcpb.test.ts} +10 -9
- package/src/mcp/result.ts +2 -2
- package/src/mcp/server.ts +54 -6
- package/src/mcp/tools.ts +9 -20
- package/src/{capabilities.ts → runtime/capabilities.ts} +11 -11
- package/src/{cli-errors.ts → runtime/cli-errors.ts} +4 -4
- package/src/{cli.ts → runtime/cli.ts} +159 -49
- package/src/runtime/exposure.ts +102 -0
- package/src/{invoke.test.ts → runtime/invoke.test.ts} +31 -7
- package/src/server/context.ts +25 -0
- package/src/server/overrides.ts +112 -0
- package/src/skill/generate.ts +8 -8
- package/src/skill/hint.ts +1 -1
- package/src/skill/install.ts +2 -2
- package/src/skill/naming.ts +1 -1
- package/src/{test-fixtures.ts → test/fixtures.ts} +3 -2
- package/src/{config.integration.test.ts → test/integration/config.test.ts} +8 -8
- package/src/{api.integration.test.ts → test/integration/http.test.ts} +170 -67
- package/src/{mcp.integration.test.ts → test/integration/mcp.test.ts} +11 -57
- package/docs/api-server.md +0 -141
- package/examples/full-example/docs/api.md +0 -511
- package/examples/full-example/src/commands/status/__generated__/outputSchema.json +0 -28
- package/examples/full-example/src/config/__generated__/configSchema.json +0 -40
- package/examples/full-example/src/config/__generated__/index.ts +0 -5
- package/examples/full-example/src/config/types.ts +0 -24
- package/src/api/openapi.ts +0 -117
- package/src/api/server.ts +0 -120
- package/src/builtins/api.ts +0 -38
- package/src/hidden.ts +0 -30
- package/src/install/plan.ts +0 -53
- /package/src/{install → configure/artifacts}/detect-installed.ts +0 -0
- /package/src/{install → configure/artifacts}/gh-release-update.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-codex.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-codex.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-openclaw.test.ts +0 -0
- /package/src/{install → configure/artifacts}/mcp-openclaw.ts +0 -0
- /package/src/{install → configure/artifacts}/normalize-uninstall.ts +0 -0
- /package/src/{install → configure/artifacts}/normalize.ts +0 -0
- /package/src/{install → configure/artifacts}/opts.ts +0 -0
- /package/src/{install → configure/artifacts}/shell.ts +0 -0
- /package/src/{formats.test.ts → core/formats.test.ts} +0 -0
- /package/src/{formats.ts → core/formats.ts} +0 -0
- /package/src/{respond.ts → core/respond.ts} +0 -0
- /package/src/{types.test.ts → core/types.test.ts} +0 -0
- /package/src/{api → http}/schema-deref.test.ts +0 -0
- /package/src/{api → http}/schema-deref.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { discoverSchemaRoots } from "./discover-schema-roots.ts";
|
|
@@ -39,105 +39,195 @@ function makeTempProject(): string {
|
|
|
39
39
|
return root;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function
|
|
43
|
-
const
|
|
44
|
-
mkdirSync(
|
|
45
|
-
writeFileSync(
|
|
42
|
+
function writeSrcFile(root: string, relPath: string, body: string): void {
|
|
43
|
+
const full = join(root, relPath);
|
|
44
|
+
mkdirSync(join(full, ".."), { recursive: true });
|
|
45
|
+
writeFileSync(full, body);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
describe("schemagen", () => {
|
|
49
|
-
test("discovers
|
|
49
|
+
test("discovers @sg types in full-example", () => {
|
|
50
50
|
const roots = discoverSchemaRoots(exampleRoot);
|
|
51
|
-
expect(roots.map((r) =>
|
|
51
|
+
expect(roots.map((r) => r.typeName).sort()).toEqual(["RenderJsonInput", "StatusJsonOutput", "WorkspaceNameInput"]);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
test("maps
|
|
55
|
-
expect(schemaJsonBasename("
|
|
56
|
-
expect(
|
|
57
|
-
expect(schemaExportName("output")).toBe("outputSchema");
|
|
54
|
+
test("maps type names to __generated__ filenames and export names", () => {
|
|
55
|
+
expect(schemaJsonBasename("StatusJsonOutput")).toBe("StatusJsonOutputSchema.json");
|
|
56
|
+
expect(schemaExportName("RenderJsonInput")).toBe("RenderJsonInputSchema");
|
|
58
57
|
});
|
|
59
58
|
|
|
60
59
|
test("runSchemagen writes __generated__ artifacts in full-example", () => {
|
|
61
60
|
const counts = runSchemagen({ projectRoot: exampleRoot });
|
|
62
|
-
expect(counts).toEqual({
|
|
61
|
+
expect(counts).toEqual({ schemas: 3 });
|
|
63
62
|
});
|
|
64
63
|
|
|
65
|
-
test("discovers roots
|
|
64
|
+
test("discovers @sg roots and writes named schema artifacts", () => {
|
|
66
65
|
const root = makeTempProject();
|
|
67
66
|
const dir = join(root, "src/commands/demo");
|
|
68
|
-
|
|
67
|
+
writeSrcFile(
|
|
69
68
|
root,
|
|
70
|
-
"commands/demo",
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
"src/commands/demo/types.ts",
|
|
70
|
+
`/** @sg */
|
|
71
|
+
export interface DemoOutput {
|
|
72
|
+
ok: boolean;
|
|
73
|
+
}
|
|
75
74
|
`,
|
|
76
75
|
);
|
|
77
76
|
|
|
78
77
|
const roots = discoverSchemaRoots(root);
|
|
79
78
|
expect(roots).toEqual([
|
|
80
79
|
{
|
|
81
|
-
kind: "output",
|
|
82
80
|
typeName: "DemoOutput",
|
|
83
81
|
path: "src/commands/demo/types.ts",
|
|
84
82
|
sourcePath: "src/commands/demo/types.ts",
|
|
85
83
|
},
|
|
86
84
|
]);
|
|
87
85
|
runSchemagen({ projectRoot: root });
|
|
88
|
-
expect(existsSync(join(dir, "__generated__/
|
|
86
|
+
expect(existsSync(join(dir, "__generated__/DemoOutputSchema.json"))).toBe(true);
|
|
87
|
+
expect(existsSync(join(dir, "__generated__/index.ts"))).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("errors on blank line between @sg JSDoc and export", () => {
|
|
91
|
+
const root = makeTempProject();
|
|
92
|
+
writeSrcFile(
|
|
93
|
+
root,
|
|
94
|
+
"src/commands/demo/types.ts",
|
|
95
|
+
`/** @sg */
|
|
96
|
+
|
|
97
|
+
export interface DemoOutput {
|
|
98
|
+
ok: boolean;
|
|
99
|
+
}
|
|
100
|
+
`,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
expect(() => discoverSchemaRoots(root)).toThrow(
|
|
104
|
+
"src/commands/demo/types.ts: @sg JSDoc must be immediately followed by export interface/type",
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("two @sg types in same directory share one index.ts", () => {
|
|
109
|
+
const root = makeTempProject();
|
|
110
|
+
writeSrcFile(
|
|
111
|
+
root,
|
|
112
|
+
"src/commands/demo/types.ts",
|
|
113
|
+
`/** @sg */
|
|
114
|
+
export interface DemoInput {
|
|
115
|
+
id: string;
|
|
116
|
+
}
|
|
117
|
+
`,
|
|
118
|
+
);
|
|
119
|
+
writeSrcFile(
|
|
120
|
+
root,
|
|
121
|
+
"src/commands/demo/command.ts",
|
|
122
|
+
`/** @sg */
|
|
123
|
+
export interface DemoOutput {
|
|
124
|
+
ok: boolean;
|
|
125
|
+
}
|
|
126
|
+
`,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
runSchemagen({ projectRoot: root });
|
|
130
|
+
const generatedDir = join(root, "src/commands/demo/__generated__");
|
|
131
|
+
const text = readFileSync(join(generatedDir, "index.ts"), "utf8");
|
|
132
|
+
expect(text).toContain("DemoInputSchema");
|
|
133
|
+
expect(text).toContain("DemoOutputSchema");
|
|
134
|
+
expect(existsSync(join(generatedDir, "DemoInputSchema.json"))).toBe(true);
|
|
135
|
+
expect(existsSync(join(generatedDir, "DemoOutputSchema.json"))).toBe(true);
|
|
89
136
|
});
|
|
90
137
|
|
|
91
|
-
test("
|
|
138
|
+
test("skips *.test.ts and __generated__ during walk", () => {
|
|
92
139
|
const root = makeTempProject();
|
|
93
|
-
|
|
140
|
+
writeSrcFile(
|
|
94
141
|
root,
|
|
95
|
-
"commands/demo",
|
|
96
|
-
|
|
97
|
-
export interface
|
|
98
|
-
|
|
99
|
-
|
|
142
|
+
"src/commands/demo/types.test.ts",
|
|
143
|
+
`/** @sg */
|
|
144
|
+
export interface ShouldNotDiscover {
|
|
145
|
+
x: string;
|
|
146
|
+
}
|
|
147
|
+
`,
|
|
148
|
+
);
|
|
149
|
+
writeSrcFile(
|
|
150
|
+
root,
|
|
151
|
+
"src/commands/demo/__generated__/orphan.ts",
|
|
152
|
+
`/** @sg */
|
|
153
|
+
export interface AlsoSkipped {
|
|
154
|
+
x: string;
|
|
155
|
+
}
|
|
156
|
+
`,
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
expect(discoverSchemaRoots(root)).toEqual([]);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("removes stale JSON files when a schema root is dropped", () => {
|
|
163
|
+
const root = makeTempProject();
|
|
164
|
+
writeSrcFile(
|
|
165
|
+
root,
|
|
166
|
+
"src/commands/demo/types.ts",
|
|
167
|
+
`/** @sg */
|
|
168
|
+
export interface DemoInput {
|
|
169
|
+
id: string;
|
|
170
|
+
}
|
|
171
|
+
/** @sg */
|
|
172
|
+
export interface DemoOutput {
|
|
173
|
+
ok: boolean;
|
|
174
|
+
}
|
|
100
175
|
`,
|
|
101
176
|
);
|
|
102
177
|
|
|
103
178
|
runSchemagen({ projectRoot: root });
|
|
104
179
|
const generatedDir = join(root, "src/commands/demo/__generated__");
|
|
105
|
-
expect(existsSync(join(generatedDir, "
|
|
106
|
-
expect(existsSync(join(generatedDir, "
|
|
180
|
+
expect(existsSync(join(generatedDir, "DemoInputSchema.json"))).toBe(true);
|
|
181
|
+
expect(existsSync(join(generatedDir, "DemoOutputSchema.json"))).toBe(true);
|
|
107
182
|
|
|
108
|
-
|
|
183
|
+
writeSrcFile(
|
|
109
184
|
root,
|
|
110
|
-
"commands/demo",
|
|
111
|
-
|
|
112
|
-
export
|
|
185
|
+
"src/commands/demo/types.ts",
|
|
186
|
+
`/** @sg */
|
|
187
|
+
export interface DemoOutput {
|
|
188
|
+
ok: boolean;
|
|
189
|
+
}
|
|
113
190
|
`,
|
|
114
191
|
);
|
|
115
192
|
|
|
116
193
|
runSchemagen({ projectRoot: root });
|
|
117
|
-
expect(existsSync(join(generatedDir, "
|
|
118
|
-
expect(existsSync(join(generatedDir, "
|
|
194
|
+
expect(existsSync(join(generatedDir, "DemoInputSchema.json"))).toBe(false);
|
|
195
|
+
expect(existsSync(join(generatedDir, "DemoOutputSchema.json"))).toBe(true);
|
|
119
196
|
expect(existsSync(join(generatedDir, "index.ts"))).toBe(true);
|
|
120
197
|
});
|
|
121
198
|
|
|
122
|
-
test("removes orphan __generated__ when
|
|
199
|
+
test("removes orphan __generated__ when no roots remain in directory", () => {
|
|
123
200
|
const root = makeTempProject();
|
|
124
201
|
const generatedDir = join(root, "src/orphan/__generated__");
|
|
125
202
|
mkdirSync(generatedDir, { recursive: true });
|
|
126
|
-
writeFileSync(join(generatedDir, "
|
|
127
|
-
writeFileSync(join(generatedDir, "index.ts"), "export const
|
|
203
|
+
writeFileSync(join(generatedDir, "DemoOutputSchema.json"), "{}\n");
|
|
204
|
+
writeFileSync(join(generatedDir, "index.ts"), "export const DemoOutputSchema = {};\n");
|
|
128
205
|
|
|
129
206
|
runSchemagen({ projectRoot: root });
|
|
130
207
|
expect(existsSync(generatedDir)).toBe(false);
|
|
131
208
|
});
|
|
132
209
|
|
|
133
|
-
test("
|
|
210
|
+
test("errors on duplicate typeName across files", () => {
|
|
134
211
|
const root = makeTempProject();
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
212
|
+
writeSrcFile(
|
|
213
|
+
root,
|
|
214
|
+
"src/a/types.ts",
|
|
215
|
+
`/** @sg */
|
|
216
|
+
export interface DupType {
|
|
217
|
+
a: string;
|
|
218
|
+
}
|
|
219
|
+
`,
|
|
220
|
+
);
|
|
221
|
+
writeSrcFile(
|
|
222
|
+
root,
|
|
223
|
+
"src/b/types.ts",
|
|
224
|
+
`/** @sg */
|
|
225
|
+
export interface DupType {
|
|
226
|
+
b: string;
|
|
227
|
+
}
|
|
228
|
+
`,
|
|
229
|
+
);
|
|
139
230
|
|
|
140
|
-
|
|
141
|
-
expect(existsSync(generatedDir)).toBe(false);
|
|
231
|
+
expect(() => discoverSchemaRoots(root)).toThrow("duplicate schema root type DupType");
|
|
142
232
|
});
|
|
143
233
|
});
|
package/src/config/bindings.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Per-key config binding metadata (`_bindings`) — records how each schema key is satisfied.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { CliAppConfigEntry } from "
|
|
5
|
+
import type { CliAppConfigEntry } from "~/core/types.ts";
|
|
6
6
|
|
|
7
7
|
/** Reserved top-level config file key for per-entry binding metadata. */
|
|
8
8
|
export const CONFIG_BINDINGS_KEY = "_bindings";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import type { CliAppConfigEntry } from "
|
|
2
|
+
import type { CliAppConfigEntry } from "~/core/types.ts";
|
|
3
3
|
import { shouldWizardPromptConfigKey } from "./bootstrap.ts";
|
|
4
4
|
|
|
5
5
|
const requiredEntry: CliAppConfigEntry = {
|
package/src/config/bootstrap.ts
CHANGED
|
@@ -4,8 +4,9 @@ settings are present before the CLI or MCP server handles a request.
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { readSync } from "node:fs";
|
|
7
|
-
import {
|
|
8
|
-
import type {
|
|
7
|
+
import type { CliAppConfigEntry, CliProgram, ServerRuntime } from "~/core/types.ts";
|
|
8
|
+
import type { LogEmitter } from "~/log/emitter.ts";
|
|
9
|
+
import { readPromptLine as readStdinLine } from "~/prompt.ts";
|
|
9
10
|
import { bindingForKey, clearFileValue, isKeyAddressed, readBindings, setBinding } from "./bindings.ts";
|
|
10
11
|
import { configEntryRequired, configEntrySensitive, defaultConfigEntryTitle, jsonSchemaRequiredKeys } from "./entry.ts";
|
|
11
12
|
import {
|
|
@@ -48,9 +49,40 @@ export interface ConfigBootstrapResult {
|
|
|
48
49
|
resolved: ResolvedConfig;
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
/** Options for {@link bootstrapAppConfig}. */
|
|
53
|
+
export interface BootstrapAppConfigOpts {
|
|
54
|
+
/** `true` = strict validate; `false` = raw read; `"soft"` = validate, log, store error in runtime.state. */
|
|
55
|
+
validateFile: boolean | "soft";
|
|
56
|
+
runtime?: ServerRuntime;
|
|
57
|
+
emitter?: LogEmitter;
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
/** Read the config file, merge env overrides, and export mapped values into `process.env`. */
|
|
52
|
-
export function bootstrapAppConfig(program: CliProgram, opts:
|
|
53
|
-
|
|
61
|
+
export function bootstrapAppConfig(program: CliProgram, opts: BootstrapAppConfigOpts): ConfigBootstrapResult {
|
|
62
|
+
let fileData: Record<string, unknown>;
|
|
63
|
+
if (opts.validateFile === true) {
|
|
64
|
+
fileData = readAppConfigFile(program);
|
|
65
|
+
} else if (opts.validateFile === "soft") {
|
|
66
|
+
try {
|
|
67
|
+
fileData = readAppConfigFile(program);
|
|
68
|
+
if (opts.runtime) {
|
|
69
|
+
delete opts.runtime.state.configFileError;
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
73
|
+
fileData = readAppConfigFileRaw(resolveAppConfigPath(program));
|
|
74
|
+
if (opts.runtime) {
|
|
75
|
+
opts.runtime.state.configFileError = message;
|
|
76
|
+
}
|
|
77
|
+
opts.emitter?.emit({
|
|
78
|
+
level: "warn",
|
|
79
|
+
message,
|
|
80
|
+
action: "config.invalid",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
fileData = readAppConfigFileRaw(resolveAppConfigPath(program));
|
|
85
|
+
}
|
|
54
86
|
const hostEnv = captureMappedHostEnv(program);
|
|
55
87
|
const resolved = resolveAppConfig(program, fileData, hostEnv);
|
|
56
88
|
exportConfigToEnv(program, resolved, hostEnv);
|
|
@@ -6,7 +6,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
|
-
import type { CliProgram } from "
|
|
9
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
10
10
|
import { createAppConfigSnapshot } from "./context.ts";
|
|
11
11
|
import { resolveAppConfigDir, resolveAppConfigPath } from "./file.ts";
|
|
12
12
|
import { resolveAppConfig } from "./resolve.ts";
|
package/src/config/context.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Handler-facing resolved app config snapshot (ctx.appConfig).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { CliProgram } from "
|
|
5
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
6
6
|
import { isFrameworkConfigKey, setBinding } from "./bindings.ts";
|
|
7
7
|
import {
|
|
8
8
|
readAppConfigFileRaw,
|
package/src/config/entry.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Shared helpers for program.appConfig schema entries.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { CliAppConfigEntry, CliProgram } from "
|
|
5
|
+
import type { CliAppConfigEntry, CliProgram } from "~/core/types.ts";
|
|
6
6
|
|
|
7
7
|
/** Default title when `CliAppConfigEntry.title` is omitted. */
|
|
8
8
|
export function defaultConfigEntryTitle(key: string): string {
|
package/src/config/file.test.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
|
-
import type { CliProgram } from "
|
|
9
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
10
10
|
import { CONFIG_BINDINGS_KEY } from "./bindings.ts";
|
|
11
11
|
import { bootstrapAppConfig } from "./bootstrap.ts";
|
|
12
12
|
import {
|
package/src/config/file.ts
CHANGED
|
@@ -4,9 +4,9 @@ JSON app config file path helpers and strict read/write.
|
|
|
4
4
|
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
7
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
8
|
+
import { sanitizeToolSegment } from "~/mcp/tools.ts";
|
|
9
|
+
import { appConfigLibHome, displayHomePath } from "~/paths/host.ts";
|
|
10
10
|
import { isFrameworkConfigKey, validateBindingsShape } from "./bindings.ts";
|
|
11
11
|
import { effectiveJsonSchema } from "./schema.ts";
|
|
12
12
|
import { validateConfigDocument, validateConfigDocumentPartial } from "./validate.ts";
|
package/src/config/manifest.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
MCP bundle / plugin manifest builders for program.appConfig env-mapped entries.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { CliAppConfigEntry, CliProgram } from "
|
|
5
|
+
import type { CliAppConfigEntry, CliProgram } from "~/core/types.ts";
|
|
6
6
|
import {
|
|
7
7
|
configEntryRequired,
|
|
8
8
|
configEntrySensitive,
|
|
@@ -3,7 +3,7 @@ Tests for config/resolve module behavior.
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
|
-
import type { CliProgram } from "
|
|
6
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
7
7
|
import { captureMappedHostEnv, exportConfigToEnv, resolveAppConfig } from "./resolve.ts";
|
|
8
8
|
|
|
9
9
|
const program: CliProgram = {
|
package/src/config/resolve.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Resolve program.appConfig values: defaults, file, env override, export to process.env.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { CliAppConfigEntry, CliAppConfigResolveContext, CliProgram } from "
|
|
5
|
+
import type { CliAppConfigEntry, CliAppConfigResolveContext, CliProgram } from "~/core/types.ts";
|
|
6
6
|
import { configEntryRequired, jsonSchemaRequiredKeys } from "./entry.ts";
|
|
7
7
|
import type { AppConfigFileData } from "./file.ts";
|
|
8
8
|
import { displayAppConfigPath } from "./file.ts";
|
package/src/config/schema.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Effective JSON Schema for program.appConfig (block schema or all-string synthesis).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { CliAppConfigEntry, CliProgram } from "
|
|
5
|
+
import type { CliAppConfigEntry, CliProgram } from "~/core/types.ts";
|
|
6
6
|
import { configEntryRequired, jsonSchemaRequiredKeys } from "./entry.ts";
|
|
7
7
|
|
|
8
8
|
/** Synthesize a draft-07 object schema with string properties from metadata entries. */
|
package/src/config/validate.ts
CHANGED
|
@@ -3,7 +3,7 @@ Draft-07 JSON Schema subset validator for program.appConfig files.
|
|
|
3
3
|
Aligned with common ts-json-schema-generator output (local $ref, objects, scalars).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { parseCommaList, parseDate, parseDateTime } from "
|
|
6
|
+
import { parseCommaList, parseDate, parseDateTime } from "~/core/formats.ts";
|
|
7
7
|
import { isFrameworkConfigKey } from "./bindings.ts";
|
|
8
8
|
|
|
9
9
|
type JsonSchema = Record<string, unknown>;
|
|
@@ -6,7 +6,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { chmodSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import type { CliProgram } from "
|
|
9
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
10
10
|
import { isAppInstalled, isExternallyManagedBinary, resolvePathCommand } from "./binary-placement.ts";
|
|
11
11
|
|
|
12
12
|
const program: CliProgram = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { accessSync, constants, realpathSync } from "node:fs";
|
|
2
2
|
import { delimiter, join } from "node:path";
|
|
3
|
-
import type { CliProgram } from "
|
|
3
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
4
4
|
|
|
5
5
|
/** Resolves a command name on PATH to its real path, if present. */
|
|
6
6
|
export function resolvePathCommand(key: string): string | undefined {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import type { CliUpdateGetLatest } from "
|
|
4
|
+
import type { CliUpdateGetLatest } from "~/core/types.ts";
|
|
5
5
|
|
|
6
6
|
/** Config for {@link ghReleaseUpdateGetLatest}. */
|
|
7
7
|
export interface GhReleaseUpdateConfig {
|
|
@@ -3,9 +3,9 @@ Tests for install/install-validate module behavior.
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
|
-
import type { CliProgram } from "
|
|
7
|
-
import { CliSchemaValidationError } from "
|
|
8
|
-
import { cliValidateProgram } from "
|
|
6
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
7
|
+
import { CliSchemaValidationError } from "~/core/types.ts";
|
|
8
|
+
import { cliValidateProgram } from "~/core/validate.ts";
|
|
9
9
|
|
|
10
10
|
const base: CliProgram = {
|
|
11
11
|
key: "app",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
-
import type { CliProgram } from "
|
|
3
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
4
4
|
|
|
5
5
|
export interface McpServerEntry {
|
|
6
6
|
command: string;
|
|
@@ -6,7 +6,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import type { CliProgram } from "
|
|
9
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
10
10
|
import {
|
|
11
11
|
detectOpenCodeMcpConfigPath,
|
|
12
12
|
expectedOpenCodeMcpEntry,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import type { CliProgram } from "
|
|
3
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
4
4
|
import { expectedMcpEntry } from "./mcp-config.ts";
|
|
5
5
|
|
|
6
6
|
export const OPENCODE_CONFIG_SCHEMA = "https://opencode.ai/config.json";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
3
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
4
|
+
import { mcpServerId, sanitizeToolSegment } from "~/mcp/tools.ts";
|
|
5
|
+
import { displayHomePath, userHome, xdgConfigHome } from "~/paths/host.ts";
|
|
6
|
+
import { skillDirNameForTarget } from "~/skill/install.ts";
|
|
7
7
|
import { resolveOpenclawConfigPath } from "./mcp-openclaw.ts";
|
|
8
8
|
import { resolveOpenCodeConfigPathForInstall } from "./mcp-opencode.ts";
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ export interface InstallPaths {
|
|
|
24
24
|
skillDirName: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export { userHome } from "
|
|
27
|
+
export { userHome } from "~/paths/host.ts";
|
|
28
28
|
|
|
29
29
|
/** Format an absolute path for user-facing install output. */
|
|
30
30
|
export function displayInstallPath(path: string): string {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
2
|
+
import type { InstallPaths } from "./paths.ts";
|
|
3
|
+
import { buildInstallPlanFromTargets } from "./target-plan-build.ts";
|
|
4
|
+
import type { InstallAction, InstallOpts } from "./target-types.ts";
|
|
5
|
+
|
|
6
|
+
export type { InstallAction, InstallActionKind, InstallOpts } from "./target-types.ts";
|
|
7
|
+
|
|
8
|
+
/** Builds install actions for normal mode (--all / scoped targets). */
|
|
9
|
+
export function buildInstallPlan(root: CliProgram, paths: InstallPaths, opts: InstallOpts): InstallAction[] {
|
|
10
|
+
return buildInstallPlanFromTargets(root, paths, opts);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Builds update/reinstall actions; greenfield fallback when nothing detected. */
|
|
14
|
+
export function buildUpdatePlan(root: CliProgram, paths: InstallPaths, opts: InstallOpts): InstallAction[] {
|
|
15
|
+
const refresh = buildInstallPlanFromTargets(root, paths, {
|
|
16
|
+
...opts,
|
|
17
|
+
reinstall: true,
|
|
18
|
+
all: true,
|
|
19
|
+
});
|
|
20
|
+
if (refresh.length > 0) {
|
|
21
|
+
return refresh;
|
|
22
|
+
}
|
|
23
|
+
return buildInstallPlanFromTargets(root, paths, { ...opts, reinstall: false, all: true });
|
|
24
|
+
}
|
|
@@ -6,7 +6,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
|
6
6
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
-
import type { CliProgram } from "
|
|
9
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
10
10
|
import { resolveInstallPaths } from "./paths.ts";
|
|
11
11
|
import { printInstallStatus } from "./status.ts";
|
|
12
12
|
import { resolveInstallTargetPreview } from "./target-scope.ts";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { appConfigStatus } from "
|
|
2
|
-
import type { CliProgram } from "
|
|
1
|
+
import { appConfigStatus } from "~/config/bootstrap.ts";
|
|
2
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
3
3
|
import { buildInstallStatus, detectInstalledArtifacts } from "./detect-installed.ts";
|
|
4
4
|
import { resolveInstallPaths } from "./paths.ts";
|
|
5
5
|
import { resolveInstallTargetPreview } from "./target-scope.ts";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CliProgram } from "
|
|
1
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
2
2
|
import type { InstallPaths } from "./paths.ts";
|
|
3
3
|
import { INSTALL_TARGETS } from "./target-registry.ts";
|
|
4
4
|
import type { InstalledArtifacts, InstallStatus } from "./target-types.ts";
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { resolveCapabilities } from "../capabilities.ts";
|
|
2
1
|
import type {
|
|
3
2
|
CliConfigureConfig,
|
|
4
3
|
CliConfigureTargets,
|
|
5
4
|
CliProgram,
|
|
6
5
|
InstallAgentIntegration,
|
|
7
6
|
InstallTargetSpec,
|
|
8
|
-
} from "
|
|
9
|
-
import
|
|
7
|
+
} from "~/core/types.ts";
|
|
8
|
+
import { resolveCapabilities } from "~/runtime/capabilities.ts";
|
|
10
9
|
import {
|
|
11
10
|
AGENT_PAIRS,
|
|
12
11
|
INSTALL_ARTIFACT_KEYS,
|
|
@@ -15,7 +14,7 @@ import {
|
|
|
15
14
|
} from "./target-registry.ts";
|
|
16
15
|
import type { CliInstallArtifactKey, InstallPlanMode } from "./target-types.ts";
|
|
17
16
|
|
|
18
|
-
export type { InstallTargetSpec, ResolvedInstallTarget } from "
|
|
17
|
+
export type { InstallTargetSpec, ResolvedInstallTarget } from "~/core/types.ts";
|
|
19
18
|
|
|
20
19
|
export type { InstallPlanMode, InstallScope } from "./target-types.ts";
|
|
21
20
|
|
|
@@ -124,8 +123,3 @@ export function resolveInstallPlanMode(opts: {
|
|
|
124
123
|
if (opts.all) return "install-all";
|
|
125
124
|
return "install-scoped";
|
|
126
125
|
}
|
|
127
|
-
|
|
128
|
-
/** @deprecated Use target registry. */
|
|
129
|
-
export function isInstallTargetAvailable(key: CliInstallArtifactKey, root: CliProgram, paths: InstallPaths): boolean {
|
|
130
|
-
return installTargetForKey(key)?.isAvailable(root, paths) ?? false;
|
|
131
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CliProgram } from "
|
|
1
|
+
import type { CliProgram } from "~/core/types.ts";
|
|
2
2
|
import { checkCodexMcpConflict, codexMcpHasServer, mergeCodexMcpConfig, removeCodexMcpConfig } from "./mcp-codex.ts";
|
|
3
3
|
import { expectedMcpEntry } from "./mcp-config.ts";
|
|
4
4
|
import {
|