@canonical/pragma-cli 0.30.0 → 0.31.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/README.md +64 -35
- package/dist/pragma +0 -0
- package/package.json +15 -13
- package/src/completions/constants.ts +7 -0
- package/src/completions/handleQuery.test.ts +32 -0
- package/src/completions/handleQuery.ts +20 -1
- package/src/completions/queryCompletions.test.ts +5 -0
- package/src/completions/queryCompletions.ts +17 -3
- package/src/completions/querySocket.test.ts +31 -0
- package/src/completions/querySocket.ts +36 -9
- package/src/config/parseConfigValues.ts +2 -0
- package/src/config/readConfigLayers.test.ts +2 -0
- package/src/config/readConfigLayers.ts +3 -0
- package/src/config/types.ts +7 -0
- package/src/constants.ts +3 -1
- package/src/domains/block/commands/sample.ts +2 -1
- package/src/domains/block/formatters/list.test.ts +3 -3
- package/src/domains/block/formatters/lookup.test.ts +5 -5
- package/src/domains/block/orchestration/enrichBlocks.ts +6 -3
- package/src/domains/block/stories.ts +9 -3
- package/src/domains/config/commands/channel.test.ts +16 -0
- package/src/domains/config/commands/channel.ts +14 -1
- package/src/domains/config/commands/framework.test.ts +14 -0
- package/src/domains/config/commands/framework.ts +13 -1
- package/src/domains/config/commands/tier.test.ts +7 -0
- package/src/domains/config/commands/tier.ts +14 -1
- package/src/domains/config/operations/validateTier.test.ts +9 -0
- package/src/domains/config/operations/validateTier.ts +10 -2
- package/src/domains/create/generatorPack/bundled.ts +49 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.test.ts +159 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.ts +312 -0
- package/src/domains/create/index.ts +13 -7
- package/src/domains/create/mcp/specs.ts +6 -161
- package/src/domains/create/renderGeneratorUi.test.ts +103 -0
- package/src/domains/create/renderGeneratorUi.ts +65 -0
- package/src/domains/doctor/formatters/doctor.test.ts +50 -2
- package/src/domains/doctor/formatters/doctor.ts +90 -38
- package/src/domains/doctor/operations/checks/checkMcpCommands.ts +9 -6
- package/src/domains/doctor/operations/checks/checkPackageRefs.ts +30 -12
- package/src/domains/doctor/operations/checks.test.ts +6 -4
- package/src/domains/doctor/operations/types.ts +23 -1
- package/src/domains/graph/commands/inspect.test.ts +2 -2
- package/src/domains/graph/commands/query.test.ts +5 -3
- package/src/domains/graph/formatters/inspect.ts +7 -7
- package/src/domains/graph/formatters/query.test.ts +87 -0
- package/src/domains/graph/formatters/query.ts +42 -5
- package/src/domains/graph/operations/inspectUri.test.ts +5 -5
- package/src/domains/graphql/commands/serve.test.ts +12 -6
- package/src/domains/graphql/commands/serve.ts +16 -6
- package/src/domains/graphql/helpers/parsePrefixes.test.ts +3 -3
- package/src/domains/graphql/helpers/parsePrefixes.ts +3 -3
- package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +9 -0
- package/src/domains/graphql/helpers/resolveSourceFiles.ts +24 -3
- package/src/domains/graphql/operations/compileSchema.test.ts +2 -2
- package/src/domains/graphql/operations/createSchemaServer.test.ts +2 -2
- package/src/domains/graphql/operations/ensureSchemaArtifact.test.ts +167 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.ts +178 -0
- package/src/domains/graphql/operations/index.ts +5 -0
- package/src/domains/info/formatters/upgrade.test.ts +7 -4
- package/src/domains/info/formatters/upgrade.ts +3 -1
- package/src/domains/info/operations/collectEntityCounts.test.ts +156 -0
- package/src/domains/info/operations/collectEntityCounts.ts +123 -0
- package/src/domains/info/operations/index.ts +1 -0
- package/src/domains/info/types.ts +13 -0
- package/src/domains/llm/capabilities.test.ts +23 -3
- package/src/domains/llm/commands/capabilities.ts +12 -3
- package/src/domains/llm/commands/llm.ts +5 -1
- package/src/domains/llm/data/commandReference.ts +20 -11
- package/src/domains/llm/data/decisionTrees.ts +10 -5
- package/src/domains/llm/data/toolCatalog.ts +49 -18
- package/src/domains/llm/formatters/orientation.ts +5 -1
- package/src/domains/llm/llmCommand.test.ts +11 -3
- package/src/domains/llm/mcp/specs.ts +3 -4
- package/src/domains/llm/operations/collectContext.test.ts +64 -0
- package/src/domains/llm/operations/collectContext.ts +7 -17
- package/src/domains/modifier/commands/sample.ts +2 -1
- package/src/domains/modifier/operations/lookup.ts +5 -3
- package/src/domains/modifier/stories.ts +9 -0
- package/src/domains/ontology/commands/list.test.ts +5 -3
- package/src/domains/ontology/commands/show.test.ts +85 -9
- package/src/domains/ontology/formatters/index.ts +1 -0
- package/src/domains/ontology/formatters/list.ts +37 -12
- package/src/domains/ontology/formatters/show.ts +358 -67
- package/src/domains/ontology/helpers/buildClassTree.ts +89 -0
- package/src/domains/ontology/helpers/completeClassNames.ts +43 -0
- package/src/domains/ontology/helpers/expandOntologyIris.ts +79 -0
- package/src/domains/ontology/helpers/index.ts +14 -0
- package/src/domains/ontology/helpers/queryClasses.ts +32 -16
- package/src/domains/ontology/helpers/queryProperties.ts +39 -6
- package/src/domains/ontology/helpers/queryTboxFacts.ts +160 -0
- package/src/domains/ontology/operations/listOntologies.test.ts +80 -3
- package/src/domains/ontology/operations/listOntologies.ts +126 -30
- package/src/domains/ontology/operations/showOntology.test.ts +131 -12
- package/src/domains/ontology/operations/showOntology.ts +289 -7
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +4 -2
- package/src/domains/ontology/stories.ts +53 -8
- package/src/domains/refs/operations/updateRefs.ts +0 -1
- package/src/domains/setup/commands/index.ts +1 -0
- package/src/domains/setup/commands/setup.ts +70 -0
- package/src/domains/setup/index.ts +7 -3
- package/src/domains/setup/operations/setupLsp.test.ts +3 -2
- package/src/domains/setup/operations/setupLsp.ts +7 -2
- package/src/domains/shared/bootStore.bareCore.test.ts +63 -0
- package/src/domains/shared/bootStore.test.ts +82 -0
- package/src/domains/shared/bootStore.ts +56 -20
- package/src/domains/shared/emptyErrorRecovery.test.ts +23 -26
- package/src/domains/shared/extractLocalName.test.ts +3 -3
- package/src/domains/shared/formatters.ts +23 -2
- package/src/domains/shared/listTiers.ts +40 -0
- package/src/domains/shared/loaders/bundledLoader.ts +48 -0
- package/src/domains/shared/loaders/gitLoader.ts +1 -2
- package/src/domains/shared/loaders/localLoader.ts +2 -18
- package/src/domains/shared/loaders/readPackageDir.test.ts +58 -0
- package/src/domains/shared/loaders/readPackageDir.ts +46 -8
- package/src/domains/shared/lookupMany.test.ts +15 -0
- package/src/domains/shared/lookupMany.ts +22 -6
- package/src/domains/shared/namespaces.ts +13 -5
- package/src/domains/shared/parseSampleCount.test.ts +47 -0
- package/src/domains/shared/parseSampleCount.ts +45 -0
- package/src/domains/shared/prefixes.test.ts +211 -0
- package/src/domains/shared/prefixes.ts +182 -15
- package/src/domains/shared/renderers.ts +5 -5
- package/src/domains/shared/resolveLookupExitCode.test.ts +48 -0
- package/src/domains/shared/resolveLookupExitCode.ts +42 -0
- package/src/domains/shared/semanticPackage.test.ts +89 -0
- package/src/domains/shared/semanticPackage.ts +17 -2
- package/src/domains/shared/stories/compileLookupCommand.ts +3 -1
- package/src/domains/shared/stories/compileLookupTool.ts +1 -1
- package/src/domains/shared/stories/pack/applyPackFilters.test.ts +49 -0
- package/src/domains/shared/stories/pack/applyPackFilters.ts +46 -11
- package/src/domains/shared/stories/pack/applyPackSearch.test.ts +57 -0
- package/src/domains/shared/stories/pack/applyPackSearch.ts +41 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +30 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.ts +75 -1
- package/src/domains/shared/stories/pack/bundled/index.ts +23 -0
- package/src/domains/shared/stories/pack/bundled/standardPack.ts +164 -0
- package/src/domains/shared/stories/pack/bundled/tierPack.ts +50 -0
- package/src/domains/shared/stories/pack/collectPackStories.test.ts +305 -7
- package/src/domains/shared/stories/pack/collectPackStories.ts +90 -8
- package/src/domains/shared/stories/pack/compilePackCommands.ts +17 -7
- package/src/domains/shared/stories/pack/compilePackStories.test.ts +607 -2
- package/src/domains/shared/stories/pack/compilePackStories.ts +544 -73
- package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +20 -8
- package/src/domains/shared/stories/pack/index.ts +14 -0
- package/src/domains/shared/stories/pack/reservedVerbs.test.ts +213 -0
- package/src/domains/shared/stories/pack/reservedVerbs.ts +170 -0
- package/src/domains/shared/stories/pack/standardParity.test.ts +293 -220
- package/src/domains/shared/stories/pack/types.ts +123 -3
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +502 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +475 -24
- package/src/domains/shared/stories/types.ts +9 -1
- package/src/domains/shared/types/index.ts +5 -9
- package/src/domains/shared/types/ontology.ts +119 -24
- package/src/domains/shared/types/standard.ts +9 -52
- package/src/domains/token/commands/lookup.test.ts +8 -0
- package/src/domains/token/commands/lookup.ts +12 -0
- package/src/domains/token/commands/sample.ts +2 -1
- package/src/domains/token/featureFlag.ts +17 -0
- package/src/domains/token/index.ts +5 -0
- package/src/domains/token/mcp/specs.ts +13 -1
- package/src/domains/trace/commands/resolveTraceLimit.test.ts +31 -0
- package/src/domains/trace/commands/show.ts +30 -4
- package/src/index.ts +1 -13
- package/src/mcp/registerResources.test.ts +2 -2
- package/src/mcp/resources/pickPrimaryType.test.ts +5 -5
- package/src/mcp/tools/index.ts +18 -10
- package/src/mcp/tools/registerTools.test.ts +106 -30
- package/src/pipeline/collectCommands.test.ts +151 -1
- package/src/pipeline/collectCommands.ts +34 -19
- package/src/pipeline/createProgram.test.ts +5 -1
- package/src/pipeline/createProgram.ts +2 -2
- package/src/pipeline/firstRun.test.ts +80 -0
- package/src/pipeline/firstRun.ts +99 -0
- package/src/pipeline/parseGlobalFlags.test.ts +102 -1
- package/src/pipeline/parseGlobalFlags.ts +98 -9
- package/src/pipeline/resolveCommandKind.test.ts +12 -0
- package/src/pipeline/resolveCommandKind.ts +4 -0
- package/src/pipeline/rootHelp.test.ts +87 -0
- package/src/pipeline/rootHelp.ts +265 -0
- package/src/pipeline/runCli.orchestration.test.ts +28 -12
- package/src/pipeline/runCli.test.ts +17 -4
- package/src/pipeline/runCli.ts +162 -19
- package/src/testing/cli.ts +30 -2
- package/src/testing/dsFixtures.ts +21 -4
- package/src/testing/index.ts +1 -4
- package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +4 -4
- package/src/testing/integration/cli-user-stories.test.ts +63 -0
- package/src/testing/integration/cross-binary-byte-equality.test.ts +2 -2
- package/src/testing/integration/edge-cases.test.ts +62 -50
- package/src/testing/integration/executor-execution.test.ts +6 -4
- package/src/testing/integration/executor-golden.test.ts +2 -2
- package/src/testing/integration/mcp-surface.test.ts +40 -15
- package/src/testing/integration/parity.test.ts +119 -70
- package/src/testing/setupXdgIsolation.ts +16 -5
- package/src/testing/standardParityFixtures.ts +26 -83
- package/src/testing/store.ts +4 -4
- package/src/domains/create/commands/component.test.ts +0 -166
- package/src/domains/create/commands/component.ts +0 -123
- package/src/domains/create/commands/index.ts +0 -3
- package/src/domains/create/commands/package.test.ts +0 -35
- package/src/domains/create/commands/package.ts +0 -21
- package/src/domains/create/generators.ts +0 -8
- package/src/domains/standard/commands/categories.test.ts +0 -70
- package/src/domains/standard/commands/categories.ts +0 -48
- package/src/domains/standard/commands/index.ts +0 -6
- package/src/domains/standard/commands/list.test.ts +0 -105
- package/src/domains/standard/commands/list.ts +0 -11
- package/src/domains/standard/commands/lookup.test.ts +0 -135
- package/src/domains/standard/commands/lookup.ts +0 -14
- package/src/domains/standard/commands/sample.ts +0 -57
- package/src/domains/standard/formatters/categories.test.ts +0 -44
- package/src/domains/standard/formatters/categories.ts +0 -38
- package/src/domains/standard/formatters/index.ts +0 -10
- package/src/domains/standard/formatters/list.test.ts +0 -169
- package/src/domains/standard/formatters/list.ts +0 -184
- package/src/domains/standard/formatters/lookup.test.ts +0 -95
- package/src/domains/standard/formatters/lookup.ts +0 -101
- package/src/domains/standard/formatters/sample.ts +0 -15
- package/src/domains/standard/formatters/types.ts +0 -31
- package/src/domains/standard/index.ts +0 -40
- package/src/domains/standard/mcp/index.ts +0 -2
- package/src/domains/standard/mcp/specs.ts +0 -89
- package/src/domains/standard/operations/categories.test.ts +0 -61
- package/src/domains/standard/operations/categories.ts +0 -38
- package/src/domains/standard/operations/index.ts +0 -6
- package/src/domains/standard/operations/list.test.ts +0 -75
- package/src/domains/standard/operations/list.ts +0 -64
- package/src/domains/standard/operations/lookup.test.ts +0 -58
- package/src/domains/standard/operations/lookup.ts +0 -151
- package/src/domains/standard/operations/sample.ts +0 -35
- package/src/domains/standard/orchestration/buildStandardFilters.ts +0 -11
- package/src/domains/standard/orchestration/index.ts +0 -4
- package/src/domains/standard/orchestration/resolveStandardList.ts +0 -45
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +0 -33
- package/src/domains/standard/orchestration/standardEmptyError.test.ts +0 -33
- package/src/domains/standard/orchestration/standardEmptyError.ts +0 -29
- package/src/domains/standard/standardConfig.ts +0 -42
- package/src/domains/standard/stories.test.ts +0 -24
- package/src/domains/standard/stories.ts +0 -151
- package/src/domains/standard/types.ts +0 -15
- package/src/domains/tier/commands/index.ts +0 -3
- package/src/domains/tier/commands/list.test.ts +0 -67
- package/src/domains/tier/commands/list.ts +0 -9
- package/src/domains/tier/formatters/index.ts +0 -3
- package/src/domains/tier/formatters/list.test.ts +0 -33
- package/src/domains/tier/formatters/list.ts +0 -45
- package/src/domains/tier/index.ts +0 -17
- package/src/domains/tier/mcp/index.ts +0 -2
- package/src/domains/tier/mcp/specs.ts +0 -12
- package/src/domains/tier/operations/index.ts +0 -3
- package/src/domains/tier/operations/list.test.ts +0 -32
- package/src/domains/tier/operations/list.ts +0 -33
- package/src/domains/tier/stories.test.ts +0 -22
- package/src/domains/tier/stories.ts +0 -52
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module Standard domain — CLI commands and operations.
|
|
3
|
-
*
|
|
4
|
-
* Commands: `pragma standard list`, `pragma standard lookup <name>`,
|
|
5
|
-
* `pragma standard categories`.
|
|
6
|
-
* Operations: {@link lookupStandard}, {@link listStandards}, {@link listCategories}.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { CommandDefinition } from "@canonical/cli-core";
|
|
10
|
-
import type { PragmaContext } from "../shared/context.js";
|
|
11
|
-
import {
|
|
12
|
-
categoriesCommand,
|
|
13
|
-
listCommand,
|
|
14
|
-
lookupCommand,
|
|
15
|
-
sampleCommand,
|
|
16
|
-
} from "./commands/index.js";
|
|
17
|
-
|
|
18
|
-
export function commands(ctx: PragmaContext): CommandDefinition[] {
|
|
19
|
-
return [
|
|
20
|
-
listCommand(ctx),
|
|
21
|
-
lookupCommand(ctx),
|
|
22
|
-
categoriesCommand(ctx),
|
|
23
|
-
sampleCommand(ctx),
|
|
24
|
-
];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export { specs as mcpSpecs } from "./mcp/index.js";
|
|
28
|
-
export {
|
|
29
|
-
listCategories,
|
|
30
|
-
listStandards,
|
|
31
|
-
lookupStandard,
|
|
32
|
-
sampleStandards,
|
|
33
|
-
} from "./operations/index.js";
|
|
34
|
-
export {
|
|
35
|
-
buildStandardFilters,
|
|
36
|
-
resolveStandardList,
|
|
37
|
-
resolveStandardLookup,
|
|
38
|
-
standardEmptyError,
|
|
39
|
-
} from "./orchestration/index.js";
|
|
40
|
-
export { standardConfig } from "./standardConfig.js";
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP tool specs for the standard domain — standard_list, standard_lookup,
|
|
3
|
-
* standard_categories, standard_sample.
|
|
4
|
-
*
|
|
5
|
-
* The list and lookup tools are compiled from the standard read stories in
|
|
6
|
-
* `../stories.ts`; categories and sample are spec'd by hand. The adapter
|
|
7
|
-
* layer converts these into registered MCP tools via `registerFromSpec()`.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
compileLookupTool,
|
|
12
|
-
compileReadTool,
|
|
13
|
-
condense,
|
|
14
|
-
} from "../../shared/stories/index.js";
|
|
15
|
-
import type { ToolSpec } from "../../shared/ToolSpec.js";
|
|
16
|
-
import {
|
|
17
|
-
categoriesFormatters as standardCatFmt,
|
|
18
|
-
sampleFormatters as standardSampleFmt,
|
|
19
|
-
} from "../formatters/index.js";
|
|
20
|
-
import { listCategories, sampleStandards } from "../operations/index.js";
|
|
21
|
-
import { standardListStory, standardLookupStory } from "../stories.js";
|
|
22
|
-
|
|
23
|
-
const specs: readonly ToolSpec[] = [
|
|
24
|
-
compileReadTool(standardListStory),
|
|
25
|
-
compileLookupTool(standardLookupStory),
|
|
26
|
-
{
|
|
27
|
-
name: "standard_categories",
|
|
28
|
-
description: "List all code standard categories.",
|
|
29
|
-
params: {
|
|
30
|
-
condensed: {
|
|
31
|
-
type: "boolean",
|
|
32
|
-
description: "Token-optimized output",
|
|
33
|
-
optional: true,
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
readOnly: true,
|
|
37
|
-
async execute(rt, { condensed }) {
|
|
38
|
-
const result = await listCategories(rt.store);
|
|
39
|
-
|
|
40
|
-
if (condensed) {
|
|
41
|
-
return condense(standardCatFmt.llm(result));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return { data: result, meta: { count: result.length } };
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: "standard_sample",
|
|
49
|
-
description:
|
|
50
|
-
"Return 1–5 randomly selected complete code standard instances as exemplars. Use BEFORE writing queries to see actual data shapes, property names, and value formats. Each call returns different instances.",
|
|
51
|
-
params: {
|
|
52
|
-
count: {
|
|
53
|
-
type: "string",
|
|
54
|
-
description: "Number of samples (1–5, default 2)",
|
|
55
|
-
optional: true,
|
|
56
|
-
},
|
|
57
|
-
condensed: {
|
|
58
|
-
type: "boolean",
|
|
59
|
-
description: "Token-optimized output",
|
|
60
|
-
optional: true,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
readOnly: true,
|
|
64
|
-
async execute(rt, { count, condensed }) {
|
|
65
|
-
const n = Number(count ?? 2);
|
|
66
|
-
const result = await sampleStandards(rt.store, n);
|
|
67
|
-
const nextSteps = [
|
|
68
|
-
`These are ${result.samples.length} of ${result.totalCount} total standards.`,
|
|
69
|
-
"Use standard_lookup to inspect specific standards by name.",
|
|
70
|
-
"Use standard_list with category param to filter by category.",
|
|
71
|
-
];
|
|
72
|
-
|
|
73
|
-
if (condensed) {
|
|
74
|
-
return condense(standardSampleFmt.llm({ ...result, nextSteps }));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
data: {
|
|
79
|
-
samples: result.samples,
|
|
80
|
-
totalCount: result.totalCount,
|
|
81
|
-
nextSteps,
|
|
82
|
-
},
|
|
83
|
-
meta: { count: result.samples.length },
|
|
84
|
-
};
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
] as const;
|
|
88
|
-
|
|
89
|
-
export default specs;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { Store } from "@canonical/ke";
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
4
|
-
import { PREFIX_MAP } from "../../shared/prefixes.js";
|
|
5
|
-
import listCategories from "./categories.js";
|
|
6
|
-
|
|
7
|
-
let store: Store;
|
|
8
|
-
let cleanup: () => void;
|
|
9
|
-
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
12
|
-
store = result.store;
|
|
13
|
-
cleanup = result.cleanup;
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterAll(() => cleanup());
|
|
17
|
-
|
|
18
|
-
describe("listCategories", () => {
|
|
19
|
-
it("returns categories with standard counts", async () => {
|
|
20
|
-
const result = await listCategories(store);
|
|
21
|
-
expect(result.length).toBe(2);
|
|
22
|
-
|
|
23
|
-
const react = result.find((c) => c.name === "react");
|
|
24
|
-
expect(react?.standardCount).toBe(2);
|
|
25
|
-
|
|
26
|
-
const code = result.find((c) => c.name === "code");
|
|
27
|
-
expect(code?.standardCount).toBe(1);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("returns sorted by name", async () => {
|
|
31
|
-
const result = await listCategories(store);
|
|
32
|
-
const names = result.map((c) => c.name);
|
|
33
|
-
const sorted = [...names].sort();
|
|
34
|
-
expect(names).toEqual(sorted);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("includes categories with zero standards", async () => {
|
|
38
|
-
const ttlWithEmptyCategory = `
|
|
39
|
-
@prefix cs: <${PREFIX_MAP.cs}> .
|
|
40
|
-
cs:empty_cat a cs:Category ; cs:slug "empty" .
|
|
41
|
-
cs:filled_cat a cs:Category ; cs:slug "filled" .
|
|
42
|
-
cs:s1 a cs:CodeStandard ;
|
|
43
|
-
cs:name "filled/one" ;
|
|
44
|
-
cs:hasCategory cs:filled_cat ;
|
|
45
|
-
cs:description "A standard" .
|
|
46
|
-
`;
|
|
47
|
-
const { store: testStore, cleanup: testCleanup } = await createTestStore({
|
|
48
|
-
ttl: ttlWithEmptyCategory,
|
|
49
|
-
});
|
|
50
|
-
try {
|
|
51
|
-
const result = await listCategories(testStore);
|
|
52
|
-
const empty = result.find((c) => c.name === "empty");
|
|
53
|
-
expect(empty).toBeDefined();
|
|
54
|
-
expect(empty?.standardCount).toBe(0);
|
|
55
|
-
const filled = result.find((c) => c.name === "filled");
|
|
56
|
-
expect(filled?.standardCount).toBe(1);
|
|
57
|
-
} finally {
|
|
58
|
-
testCleanup();
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lists all standard categories with the number of standards in each.
|
|
3
|
-
*
|
|
4
|
-
* @param store - ke store to query
|
|
5
|
-
* @returns array of category summaries ordered by name, empty when none exist
|
|
6
|
-
* @note Queries ke store
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Store } from "@canonical/ke";
|
|
10
|
-
import { buildQuery } from "../../shared/buildQuery.js";
|
|
11
|
-
import { P } from "../../shared/prefixes.js";
|
|
12
|
-
import type { CategorySummary } from "../../shared/types/index.js";
|
|
13
|
-
|
|
14
|
-
export default async function listCategories(
|
|
15
|
-
store: Store,
|
|
16
|
-
): Promise<CategorySummary[]> {
|
|
17
|
-
const result = await store.query(
|
|
18
|
-
buildQuery(`
|
|
19
|
-
SELECT ?categoryName (COUNT(?standard) AS ?count)
|
|
20
|
-
WHERE {
|
|
21
|
-
?cat a ${P.cs}Category ;
|
|
22
|
-
${P.cs}slug ?categoryName .
|
|
23
|
-
OPTIONAL {
|
|
24
|
-
?standard a ${P.cs}CodeStandard ;
|
|
25
|
-
${P.cs}hasCategory ?cat .
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
GROUP BY ?categoryName
|
|
29
|
-
ORDER BY ?categoryName
|
|
30
|
-
`),
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
if (result.type !== "select") return [];
|
|
34
|
-
return result.bindings.map((b) => ({
|
|
35
|
-
name: b.categoryName ?? "",
|
|
36
|
-
standardCount: Number.parseInt(b.count ?? "0", 10) || 0,
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/** @module Re-exports standard operations (`listCategories`, `listStandards`, `lookupStandard`, `sampleStandards`). */
|
|
2
|
-
|
|
3
|
-
export { default as listCategories } from "./categories.js";
|
|
4
|
-
export { default as listStandards } from "./list.js";
|
|
5
|
-
export { default as lookupStandard } from "./lookup.js";
|
|
6
|
-
export { default as sampleStandards } from "./sample.js";
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { Store } from "@canonical/ke";
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
4
|
-
import listStandards from "./list.js";
|
|
5
|
-
|
|
6
|
-
let store: Store;
|
|
7
|
-
let cleanup: () => void;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
11
|
-
store = result.store;
|
|
12
|
-
cleanup = result.cleanup;
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
afterAll(() => cleanup());
|
|
16
|
-
|
|
17
|
-
describe("listStandards", () => {
|
|
18
|
-
it("returns all standards", async () => {
|
|
19
|
-
const result = await listStandards(store);
|
|
20
|
-
expect(result.length).toBe(3);
|
|
21
|
-
const names = result.map((s) => s.name);
|
|
22
|
-
expect(names).toContain("react/component/folder-structure");
|
|
23
|
-
expect(names).toContain("react/component/props");
|
|
24
|
-
expect(names).toContain("code/function/purity");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("includes category names", async () => {
|
|
28
|
-
const result = await listStandards(store);
|
|
29
|
-
const folder = result.find(
|
|
30
|
-
(s) => s.name === "react/component/folder-structure",
|
|
31
|
-
);
|
|
32
|
-
expect(folder?.category).toBe("react");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("returns sorted by name", async () => {
|
|
36
|
-
const result = await listStandards(store);
|
|
37
|
-
const names = result.map((s) => s.name);
|
|
38
|
-
const sorted = [...names].sort();
|
|
39
|
-
expect(names).toEqual(sorted);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("filters by category", async () => {
|
|
43
|
-
const result = await listStandards(store, { category: "react" });
|
|
44
|
-
expect(result.length).toBe(2);
|
|
45
|
-
for (const s of result) {
|
|
46
|
-
expect(s.category).toBe("react");
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("filters by search term in name", async () => {
|
|
51
|
-
const result = await listStandards(store, { search: "folder" });
|
|
52
|
-
expect(result.length).toBe(1);
|
|
53
|
-
expect(result[0]?.name).toBe("react/component/folder-structure");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("filters by search term in description", async () => {
|
|
57
|
-
const result = await listStandards(store, { search: "pure" });
|
|
58
|
-
expect(result.length).toBe(1);
|
|
59
|
-
expect(result[0]?.name).toBe("code/function/purity");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("returns empty for non-matching category", async () => {
|
|
63
|
-
const result = await listStandards(store, { category: "nonexistent" });
|
|
64
|
-
expect(result.length).toBe(0);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("combines category and search filters", async () => {
|
|
68
|
-
const result = await listStandards(store, {
|
|
69
|
-
category: "react",
|
|
70
|
-
search: "props",
|
|
71
|
-
});
|
|
72
|
-
expect(result.length).toBe(1);
|
|
73
|
-
expect(result[0]?.name).toBe("react/component/props");
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lists all code standards, optionally filtered by category or search term.
|
|
3
|
-
*
|
|
4
|
-
* @param store - ke store to query
|
|
5
|
-
* @param filters - optional category and/or search text filters
|
|
6
|
-
* @returns array of standard summaries ordered by name, empty when none match
|
|
7
|
-
* @note Queries ke store
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { Store, URI } from "@canonical/ke";
|
|
11
|
-
import { escapeSparqlValue } from "@canonical/ke";
|
|
12
|
-
import { buildQuery } from "../../shared/buildQuery.js";
|
|
13
|
-
import { P } from "../../shared/prefixes.js";
|
|
14
|
-
import type {
|
|
15
|
-
StandardListFilters,
|
|
16
|
-
StandardSummary,
|
|
17
|
-
} from "../../shared/types/index.js";
|
|
18
|
-
|
|
19
|
-
export default async function listStandards(
|
|
20
|
-
store: Store,
|
|
21
|
-
filters?: StandardListFilters,
|
|
22
|
-
): Promise<StandardSummary[]> {
|
|
23
|
-
const filterClauses: string[] = [];
|
|
24
|
-
|
|
25
|
-
if (filters?.category) {
|
|
26
|
-
const escaped = escapeSparqlValue(filters.category.toLowerCase());
|
|
27
|
-
filterClauses.push(
|
|
28
|
-
`?standard ${P.cs}hasCategory ?filterCat . ?filterCat ${P.cs}slug ?catSlug . FILTER(?catSlug = ${escaped})`,
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (filters?.search) {
|
|
33
|
-
const escaped = escapeSparqlValue(filters.search.toLowerCase());
|
|
34
|
-
filterClauses.push(
|
|
35
|
-
`FILTER(CONTAINS(LCASE(?name), ${escaped}) || CONTAINS(LCASE(?description), ${escaped}))`,
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = await store.query(
|
|
40
|
-
buildQuery(`
|
|
41
|
-
SELECT ?standard ?name ?categoryName ?description
|
|
42
|
-
WHERE {
|
|
43
|
-
?standard a ${P.cs}CodeStandard ;
|
|
44
|
-
${P.cs}name ?name ;
|
|
45
|
-
${P.cs}description ?description .
|
|
46
|
-
OPTIONAL {
|
|
47
|
-
?standard ${P.cs}hasCategory ?cat .
|
|
48
|
-
?cat ${P.cs}slug ?categoryName .
|
|
49
|
-
}
|
|
50
|
-
${filterClauses.join("\n ")}
|
|
51
|
-
}
|
|
52
|
-
ORDER BY ?name
|
|
53
|
-
`),
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
if (result.type !== "select") return [];
|
|
57
|
-
|
|
58
|
-
return result.bindings.map((b) => ({
|
|
59
|
-
uri: (b.standard ?? "") as URI,
|
|
60
|
-
name: b.name ?? "",
|
|
61
|
-
category: b.categoryName ?? "",
|
|
62
|
-
description: b.description ?? "",
|
|
63
|
-
}));
|
|
64
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { Store } from "@canonical/ke";
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { PragmaError } from "#error";
|
|
4
|
-
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
5
|
-
import lookupStandard from "./lookup.js";
|
|
6
|
-
|
|
7
|
-
let store: Store;
|
|
8
|
-
let cleanup: () => void;
|
|
9
|
-
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
12
|
-
store = result.store;
|
|
13
|
-
cleanup = result.cleanup;
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterAll(() => cleanup());
|
|
17
|
-
|
|
18
|
-
describe("lookupStandard", () => {
|
|
19
|
-
it("returns detailed data with dos and donts", async () => {
|
|
20
|
-
const result = await lookupStandard(
|
|
21
|
-
store,
|
|
22
|
-
"react/component/folder-structure",
|
|
23
|
-
);
|
|
24
|
-
expect(result.name).toBe("react/component/folder-structure");
|
|
25
|
-
expect(result.category).toBe("react");
|
|
26
|
-
expect(result.dos.length).toBeGreaterThan(0);
|
|
27
|
-
expect(result.donts.length).toBeGreaterThan(0);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("throws PragmaError.notFound for unknown standard", async () => {
|
|
31
|
-
await expect(lookupStandard(store, "nonexistent")).rejects.toThrow(
|
|
32
|
-
PragmaError,
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await lookupStandard(store, "nonexistent");
|
|
37
|
-
} catch (e) {
|
|
38
|
-
expect((e as PragmaError).code).toBe("ENTITY_NOT_FOUND");
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("resolves prefixed IRIs and compacts extends", async () => {
|
|
43
|
-
const result = await lookupStandard(store, "cs:react_props");
|
|
44
|
-
expect(result.name).toBe("react/component/props");
|
|
45
|
-
expect(result.extends).toBe("cs:react_folder");
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("resolves full IRIs", async () => {
|
|
49
|
-
const result = await lookupStandard(
|
|
50
|
-
store,
|
|
51
|
-
"http://pragma.canonical.com/codestandards#react_props",
|
|
52
|
-
);
|
|
53
|
-
expect(result.name).toBe("react/component/props");
|
|
54
|
-
expect(result.uri).toBe(
|
|
55
|
-
"http://pragma.canonical.com/codestandards#react_props",
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Look up detailed information for a single code standard by name.
|
|
3
|
-
*
|
|
4
|
-
* Queries the base standard data plus its dos and donts code blocks,
|
|
5
|
-
* then assembles a {@link StandardDetailed} object.
|
|
6
|
-
*
|
|
7
|
-
* @param store - ke store to query
|
|
8
|
-
* @param name - standard name (e.g. "react/component/folder-structure")
|
|
9
|
-
* @returns full standard detail including dos/donts code blocks
|
|
10
|
-
* @throws PragmaError.notFound if the standard does not exist
|
|
11
|
-
* @note Queries ke store
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { Store, URI } from "@canonical/ke";
|
|
15
|
-
import { escapeSparqlValue } from "@canonical/ke";
|
|
16
|
-
import { PragmaError } from "#error";
|
|
17
|
-
import resolveUri from "../../graph/helpers/resolveUri.js";
|
|
18
|
-
import { buildQuery } from "../../shared/buildQuery.js";
|
|
19
|
-
import compactUri from "../../shared/compactUri.js";
|
|
20
|
-
import { P } from "../../shared/prefixes.js";
|
|
21
|
-
import {
|
|
22
|
-
detectCrossDomain,
|
|
23
|
-
listDomainNames,
|
|
24
|
-
suggestNames,
|
|
25
|
-
} from "../../shared/suggestions/index.js";
|
|
26
|
-
import type { CodeBlock, StandardDetailed } from "../../shared/types/index.js";
|
|
27
|
-
|
|
28
|
-
export default async function lookupStandard(
|
|
29
|
-
store: Store,
|
|
30
|
-
nameOrUri: string,
|
|
31
|
-
): Promise<StandardDetailed> {
|
|
32
|
-
const subjectClause = buildLookupSubjectClause(nameOrUri, store.prefixes);
|
|
33
|
-
const bindClause =
|
|
34
|
-
subjectClause === null ? "" : `BIND(${subjectClause} AS ?standard)`;
|
|
35
|
-
const matchClause =
|
|
36
|
-
subjectClause === null
|
|
37
|
-
? `?standard ${P.cs}name ${escapeSparqlValue(nameOrUri)} .`
|
|
38
|
-
: "";
|
|
39
|
-
|
|
40
|
-
const baseResult = await store.query(
|
|
41
|
-
buildQuery(`
|
|
42
|
-
SELECT ?standard ?name ?categoryName ?description ?extends
|
|
43
|
-
WHERE {
|
|
44
|
-
${bindClause}
|
|
45
|
-
?standard a ${P.cs}CodeStandard ;
|
|
46
|
-
${P.cs}name ?name ;
|
|
47
|
-
${P.cs}description ?description .
|
|
48
|
-
${matchClause}
|
|
49
|
-
OPTIONAL {
|
|
50
|
-
?standard ${P.cs}hasCategory ?cat .
|
|
51
|
-
?cat ${P.cs}slug ?categoryName .
|
|
52
|
-
}
|
|
53
|
-
OPTIONAL { ?standard ${P.cs}extends ?extends }
|
|
54
|
-
}
|
|
55
|
-
LIMIT 1
|
|
56
|
-
`),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
if (baseResult.type !== "select" || baseResult.bindings.length === 0) {
|
|
60
|
-
const candidates = await listDomainNames(store, "standard");
|
|
61
|
-
const crossDomain = await detectCrossDomain(nameOrUri, "standard", store);
|
|
62
|
-
throw PragmaError.notFound("standard", nameOrUri, {
|
|
63
|
-
suggestions: suggestNames(nameOrUri, candidates),
|
|
64
|
-
recovery: {
|
|
65
|
-
message: "List available standards.",
|
|
66
|
-
cli: "pragma standard list",
|
|
67
|
-
mcp: { tool: "standard_list" },
|
|
68
|
-
},
|
|
69
|
-
crossDomain: crossDomain ?? undefined,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Safe: length check above guarantees bindings[0] exists
|
|
74
|
-
const base = baseResult.bindings[0] as (typeof baseResult.bindings)[number];
|
|
75
|
-
const standardUri = base.standard;
|
|
76
|
-
|
|
77
|
-
// Fetch dos (cs:do → cs:Example with cs:description, cs:language, cs:code)
|
|
78
|
-
const dosResult = await store.query(
|
|
79
|
-
buildQuery(`
|
|
80
|
-
SELECT ?description ?language ?code
|
|
81
|
-
WHERE {
|
|
82
|
-
<${standardUri}> ${P.cs}do ?example .
|
|
83
|
-
OPTIONAL { ?example ${P.cs}description ?description }
|
|
84
|
-
OPTIONAL { ?example ${P.cs}language ?language }
|
|
85
|
-
OPTIONAL { ?example ${P.cs}code ?code }
|
|
86
|
-
}
|
|
87
|
-
`),
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const dos: CodeBlock[] =
|
|
91
|
-
dosResult.type === "select"
|
|
92
|
-
? dosResult.bindings.map((b) => ({
|
|
93
|
-
language: b.language ?? "typescript",
|
|
94
|
-
code: b.code ?? "",
|
|
95
|
-
caption: b.description,
|
|
96
|
-
}))
|
|
97
|
-
: [];
|
|
98
|
-
|
|
99
|
-
// Fetch donts (cs:dont → cs:Example with cs:description, cs:language, cs:code)
|
|
100
|
-
const dontsResult = await store.query(
|
|
101
|
-
buildQuery(`
|
|
102
|
-
SELECT ?description ?language ?code
|
|
103
|
-
WHERE {
|
|
104
|
-
<${standardUri}> ${P.cs}dont ?example .
|
|
105
|
-
OPTIONAL { ?example ${P.cs}description ?description }
|
|
106
|
-
OPTIONAL { ?example ${P.cs}language ?language }
|
|
107
|
-
OPTIONAL { ?example ${P.cs}code ?code }
|
|
108
|
-
}
|
|
109
|
-
`),
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
const donts: CodeBlock[] =
|
|
113
|
-
dontsResult.type === "select"
|
|
114
|
-
? dontsResult.bindings.map((b) => ({
|
|
115
|
-
language: b.language ?? "typescript",
|
|
116
|
-
code: b.code ?? "",
|
|
117
|
-
caption: b.description,
|
|
118
|
-
}))
|
|
119
|
-
: [];
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
uri: (standardUri ?? "") as URI,
|
|
123
|
-
name: base.name ?? nameOrUri,
|
|
124
|
-
category: base.categoryName ?? "",
|
|
125
|
-
description: base.description ?? "",
|
|
126
|
-
extends: base.extends
|
|
127
|
-
? compactUri(base.extends, store.prefixes)
|
|
128
|
-
: undefined,
|
|
129
|
-
dos,
|
|
130
|
-
donts,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function buildLookupSubjectClause(
|
|
135
|
-
query: string,
|
|
136
|
-
prefixes: Readonly<Record<string, string>>,
|
|
137
|
-
): string | null {
|
|
138
|
-
if (!looksLikeUri(query)) {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return `<${resolveUri(query, prefixes)}>`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function looksLikeUri(query: string): boolean {
|
|
146
|
-
return (
|
|
147
|
-
query.startsWith("http://") ||
|
|
148
|
-
query.startsWith("https://") ||
|
|
149
|
-
query.includes(":")
|
|
150
|
-
);
|
|
151
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns a small number of complete standard instances as exemplars.
|
|
3
|
-
*
|
|
4
|
-
* Composes the existing list and lookup operations to avoid duplicating
|
|
5
|
-
* any SPARQL logic. Agents use this to learn the data shape before querying.
|
|
6
|
-
*
|
|
7
|
-
* @param store - ke store to query
|
|
8
|
-
* @param count - number of samples (clamped 1–5, default 2)
|
|
9
|
-
* @returns sample result with detailed standards and total count
|
|
10
|
-
* @note Queries ke store
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import type { Store } from "@canonical/ke";
|
|
14
|
-
import pickRandom from "../../shared/pickRandom.js";
|
|
15
|
-
import type {
|
|
16
|
-
SampleResult,
|
|
17
|
-
StandardDetailed,
|
|
18
|
-
} from "../../shared/types/index.js";
|
|
19
|
-
import listStandards from "./list.js";
|
|
20
|
-
import lookupStandard from "./lookup.js";
|
|
21
|
-
|
|
22
|
-
export default async function sampleStandards(
|
|
23
|
-
store: Store,
|
|
24
|
-
count = 2,
|
|
25
|
-
): Promise<SampleResult<StandardDetailed>> {
|
|
26
|
-
const clamped = Math.max(1, Math.min(5, count));
|
|
27
|
-
const all = await listStandards(store);
|
|
28
|
-
const selected = pickRandom(all, clamped);
|
|
29
|
-
|
|
30
|
-
const samples = await Promise.all(
|
|
31
|
-
selected.map((s) => lookupStandard(store, s.name)),
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
return { samples, totalCount: all.length };
|
|
35
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { StandardListFilters } from "../../shared/types/index.js";
|
|
2
|
-
|
|
3
|
-
export default function buildStandardFilters(params: {
|
|
4
|
-
category?: string;
|
|
5
|
-
search?: string;
|
|
6
|
-
}): StandardListFilters {
|
|
7
|
-
return {
|
|
8
|
-
category: params.category,
|
|
9
|
-
search: params.search,
|
|
10
|
-
};
|
|
11
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { default as buildStandardFilters } from "./buildStandardFilters.js";
|
|
2
|
-
export { default as resolveStandardList } from "./resolveStandardList.js";
|
|
3
|
-
export { default as resolveStandardLookup } from "./resolveStandardLookup.js";
|
|
4
|
-
export { default as standardEmptyError } from "./standardEmptyError.js";
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { ListParams } from "../../shared/contracts.js";
|
|
2
|
-
import type { PragmaRuntime } from "../../shared/runtime.js";
|
|
3
|
-
import type {
|
|
4
|
-
Disclosure,
|
|
5
|
-
StandardListFilters,
|
|
6
|
-
} from "../../shared/types/index.js";
|
|
7
|
-
import { listStandards, lookupStandard } from "../operations/index.js";
|
|
8
|
-
import type { StandardListResolution } from "../types.js";
|
|
9
|
-
import buildStandardFilters from "./buildStandardFilters.js";
|
|
10
|
-
import standardEmptyError from "./standardEmptyError.js";
|
|
11
|
-
|
|
12
|
-
export default async function resolveStandardList(
|
|
13
|
-
rt: Pick<PragmaRuntime, "store">,
|
|
14
|
-
params: ListParams & StandardListFilters,
|
|
15
|
-
): Promise<StandardListResolution> {
|
|
16
|
-
const filters = buildStandardFilters(params);
|
|
17
|
-
const items = await listStandards(rt.store, filters);
|
|
18
|
-
|
|
19
|
-
if (items.length === 0) {
|
|
20
|
-
throw standardEmptyError(filters);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const disclosure: Disclosure = params.detailed
|
|
24
|
-
? { level: "detailed" }
|
|
25
|
-
: params.digest
|
|
26
|
-
? { level: "digest" }
|
|
27
|
-
: { level: "summary" };
|
|
28
|
-
|
|
29
|
-
const details =
|
|
30
|
-
disclosure.level === "summary"
|
|
31
|
-
? undefined
|
|
32
|
-
: await Promise.all(
|
|
33
|
-
items.map((item) =>
|
|
34
|
-
lookupStandard(rt.store, item.name).catch(() => null),
|
|
35
|
-
),
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
return {
|
|
39
|
-
params,
|
|
40
|
-
items,
|
|
41
|
-
filters,
|
|
42
|
-
disclosure,
|
|
43
|
-
details,
|
|
44
|
-
};
|
|
45
|
-
}
|