@canonical/pragma-cli 0.36.0 → 0.38.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 +3 -2
- package/bundled-skills/adoption-a1-styles/SKILL.md +24 -0
- package/bundled-skills/adoption-a2-components/SKILL.md +22 -6
- package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +1397 -327
- package/bundled-skills/anatomy-author/SKILL.md +840 -137
- package/bundled-skills/design-auditor/SKILL.md +133 -9
- package/bundled-skills/implement-component/SKILL.md +192 -23
- package/bundled-skills/specify-component/SKILL.md +124 -12
- package/bundled-skills/specify-pattern/SKILL.md +47 -8
- package/dist/package.json +23 -20
- package/dist/pragma.conf.js +963 -40
- package/dist/pragma.conf.js.map +1 -1
- package/dist/src/capabilities/capabilities/catalog.js +14 -5
- package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
- package/dist/src/capabilities/capabilities/hints.js +33 -5
- package/dist/src/capabilities/capabilities/hints.js.map +1 -1
- package/dist/src/capabilities/config/show.render.js +30 -2
- package/dist/src/capabilities/config/show.render.js.map +1 -1
- package/dist/src/capabilities/create/create.verb.js +2 -1
- package/dist/src/capabilities/create/create.verb.js.map +1 -1
- package/dist/src/capabilities/create/createSurface.generated.js +23 -1
- package/dist/src/capabilities/create/createSurface.generated.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +11 -6
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js +38 -0
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/targetHealth.js +104 -14
- package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
- package/dist/src/capabilities/graph/connect.render.js +101 -0
- package/dist/src/capabilities/graph/connect.render.js.map +1 -0
- package/dist/src/capabilities/graph/connect.types.js +21 -0
- package/dist/src/capabilities/graph/connect.types.js.map +1 -0
- package/dist/src/capabilities/graph/connect.verb.js +147 -0
- package/dist/src/capabilities/graph/connect.verb.js.map +1 -0
- package/dist/src/capabilities/graph/index.js +5 -3
- package/dist/src/capabilities/graph/index.js.map +1 -1
- package/dist/src/capabilities/graph/queryText.js +206 -0
- package/dist/src/capabilities/graph/queryText.js.map +1 -0
- package/dist/src/capabilities/graph/relationIndex.js +302 -0
- package/dist/src/capabilities/graph/relationIndex.js.map +1 -0
- package/dist/src/capabilities/graph/runConnect.js +456 -0
- package/dist/src/capabilities/graph/runConnect.js.map +1 -0
- package/dist/src/capabilities/graph/runQuery.js +21 -4
- package/dist/src/capabilities/graph/runQuery.js.map +1 -1
- package/dist/src/capabilities/setup/buildPlan.js +6 -2
- package/dist/src/capabilities/setup/buildPlan.js.map +1 -1
- package/dist/src/capabilities/setup/operations/index.js +7 -2
- package/dist/src/capabilities/setup/operations/index.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupCompletions.js +6 -2
- package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupConfig.js +4 -2
- package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupGenerator.js +72 -14
- package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupLsp.js +372 -62
- package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupMcp.js +150 -5
- package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupSkills.js +4 -2
- package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -1
- package/dist/src/capabilities/setup/operations/writability.js +114 -0
- package/dist/src/capabilities/setup/operations/writability.js.map +1 -0
- package/dist/src/capabilities/setup/plan.js.map +1 -1
- package/dist/src/capabilities/setup/setup.verb.js +80 -31
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/setup/targets.js +124 -42
- package/dist/src/capabilities/setup/targets.js.map +1 -1
- package/dist/src/capabilities/shared/index.js +1 -1
- package/dist/src/capabilities/shared/index.js.map +1 -1
- package/dist/src/constants.js +7 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/error/renderError.js +3 -2
- package/dist/src/kernel/error/renderError.js.map +1 -1
- package/dist/src/kernel/error/validOptions.js +41 -0
- package/dist/src/kernel/error/validOptions.js.map +1 -0
- package/dist/src/kernel/packs/compile.js +90 -6
- package/dist/src/kernel/packs/compile.js.map +1 -1
- package/dist/src/kernel/packs/cursor.js +135 -0
- package/dist/src/kernel/packs/cursor.js.map +1 -0
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js +9 -2
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js.map +1 -1
- package/dist/src/kernel/packs/paging.js +108 -0
- package/dist/src/kernel/packs/paging.js.map +1 -0
- package/dist/src/kernel/packs/renderPack.js +154 -5
- package/dist/src/kernel/packs/renderPack.js.map +1 -1
- package/dist/src/kernel/packs/resolveEntity.js +118 -19
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
- package/dist/src/kernel/packs/runBodies.js +156 -18
- package/dist/src/kernel/packs/runBodies.js.map +1 -1
- package/dist/src/kernel/packs/schema.js +160 -12
- package/dist/src/kernel/packs/schema.js.map +1 -1
- package/dist/src/kernel/packs/sparql/authorQuery.js +227 -0
- package/dist/src/kernel/packs/sparql/authorQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildListQuery.js +251 -0
- package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +125 -22
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/filterValues.js +145 -0
- package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -0
- package/dist/src/kernel/packs/sparql/index.js +24 -14
- package/dist/src/kernel/packs/sparql/index.js.map +1 -1
- package/dist/src/kernel/packs/sparql/runSelect.js +10 -4
- package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
- package/dist/src/kernel/packs/sparql/searchTerm.js +25 -0
- package/dist/src/kernel/packs/sparql/searchTerm.js.map +1 -0
- package/dist/src/kernel/packs/storyRules.js +151 -0
- package/dist/src/kernel/packs/storyRules.js.map +1 -0
- package/dist/src/kernel/packs/tierScope.js +310 -0
- package/dist/src/kernel/packs/tierScope.js.map +1 -0
- package/dist/src/kernel/packs/types.js +80 -0
- package/dist/src/kernel/packs/types.js.map +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js +10 -1
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
- package/dist/src/kernel/project/cli/dispatch.js +104 -3
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
- package/dist/src/kernel/project/cli/rootHelp.js +8 -5
- package/dist/src/kernel/project/cli/rootHelp.js.map +1 -1
- package/dist/src/kernel/project/cli/suggestNames.js +31 -7
- package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
- package/dist/src/kernel/project/mcp/registerVerb.js +5 -1
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
- package/dist/src/kernel/render/renderers.js +34 -2
- package/dist/src/kernel/render/renderers.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +2 -3
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js +4 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded.js +13 -6
- package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/read.js +17 -10
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
- package/dist/src/kernel/runtime/loadSession.js +3 -1
- package/dist/src/kernel/runtime/loadSession.js.map +1 -1
- package/dist/src/kernel/runtime/probe.js +1 -1
- package/dist/src/kernel/runtime/probe.js.map +1 -1
- package/dist/src/kernel/runtime/readEntity.js +19 -4
- package/dist/src/kernel/runtime/readEntity.js.map +1 -1
- package/dist/src/kernel/runtime/refs/parseRef.js +17 -1
- package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -1
- package/dist/src/kernel/runtime/refs/resolve.js +38 -5
- package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
- package/dist/src/kernel/spec/emitReference.js +1 -1
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/package.json +23 -20
- package/pragma.conf.ts +983 -40
- package/src/capabilities/block.parity.test.ts +207 -27
- package/src/capabilities/block.shipped.exec.test.ts +156 -14
- package/src/capabilities/block.tierRank.exec.test.ts +46 -9
- package/src/capabilities/capabilities/catalog.ts +14 -5
- package/src/capabilities/capabilities/hints.ts +40 -5
- package/src/capabilities/config/collectConfigShow.test.ts +1 -0
- package/src/capabilities/config/set.test.ts +24 -25
- package/src/capabilities/config/show.render.test.ts +9 -4
- package/src/capabilities/config/show.render.ts +30 -2
- package/src/capabilities/create/byteEquality.test.ts +28 -1
- package/src/capabilities/create/create.test.ts +1 -0
- package/src/capabilities/create/create.verb.ts +2 -1
- package/src/capabilities/create/createGrammar.test.ts +4 -1
- package/src/capabilities/create/createSurface.generated.ts +23 -1
- package/src/capabilities/create/crossCli.subprocess.test.ts +10 -3
- package/src/capabilities/distribution.parity.test.ts +12 -11
- package/src/capabilities/distribution.test.ts +77 -7
- package/src/capabilities/doctor/checks/checkNodeVersion.test.ts +49 -0
- package/src/capabilities/doctor/checks/checkNodeVersion.ts +11 -7
- package/src/capabilities/doctor/checks/harnessInventory.test.ts +13 -6
- package/src/capabilities/doctor/checks/harnessInventory.ts +8 -4
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.test.ts +111 -0
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.ts +34 -0
- package/src/capabilities/doctor/checks/mcpCommand.test.ts +7 -1
- package/src/capabilities/doctor/checks/targetHealth.ts +114 -13
- package/src/capabilities/doctor/doctor.test.ts +327 -36
- package/src/capabilities/emptyRecovery.test.ts +84 -28
- package/src/capabilities/graph/connect.render.ts +141 -0
- package/src/capabilities/graph/connect.shipped.exec.test.ts +370 -0
- package/src/capabilities/graph/connect.test.ts +361 -0
- package/src/capabilities/graph/connect.types.ts +136 -0
- package/src/capabilities/graph/connect.verb.ts +165 -0
- package/src/capabilities/graph/index.ts +5 -3
- package/src/capabilities/graph/query.shipped.exec.test.ts +66 -0
- package/src/capabilities/graph/query.test.ts +17 -0
- package/src/capabilities/graph/queryText.test.ts +121 -0
- package/src/capabilities/graph/queryText.ts +240 -0
- package/src/capabilities/graph/relationIndex.ts +372 -0
- package/src/capabilities/graph/runConnect.ts +577 -0
- package/src/capabilities/graph/runQuery.ts +21 -6
- package/src/capabilities/lazy.test.ts +32 -2
- package/src/capabilities/listBudget.shipped.exec.test.ts +239 -0
- package/src/capabilities/listLookup.shipped.exec.test.ts +387 -0
- package/src/capabilities/listQuery.shipped.exec.test.ts +400 -0
- package/src/capabilities/resources/resources.test.ts +38 -2
- package/src/capabilities/setup/buildPlan.ts +7 -1
- package/src/capabilities/setup/operations/index.ts +14 -0
- package/src/capabilities/setup/operations/setupCompletions.ts +9 -2
- package/src/capabilities/setup/operations/setupConfig.ts +7 -2
- package/src/capabilities/setup/operations/setupGenerator.ts +93 -15
- package/src/capabilities/setup/operations/setupLsp.ts +544 -85
- package/src/capabilities/setup/operations/setupMcp.ts +212 -4
- package/src/capabilities/setup/operations/setupSkills.ts +7 -2
- package/src/capabilities/setup/operations/writability.test.ts +151 -0
- package/src/capabilities/setup/operations/writability.ts +135 -0
- package/src/capabilities/setup/plan.ts +11 -0
- package/src/capabilities/setup/setup.test.ts +992 -16
- package/src/capabilities/setup/setup.verb.ts +84 -36
- package/src/capabilities/setup/targets.ts +152 -48
- package/src/capabilities/setup/types.ts +41 -5
- package/src/capabilities/shared/index.ts +1 -0
- package/src/capabilities/sources/sources.test.ts +55 -0
- package/src/capabilities/surface.test.ts +59 -11
- package/src/capabilities/tier.parity.test.ts +2 -2
- package/src/capabilities/token.parity.test.ts +784 -0
- package/src/capabilities/tokenGraph.cli.test.ts +279 -0
- package/src/capabilities/tokenGraph.shipped.exec.test.ts +653 -0
- package/src/capabilities/variable.parity.test.ts +448 -0
- package/src/constants.ts +8 -0
- package/src/kernel/completion/shellDrive.test.ts +32 -30
- package/src/kernel/config/defaults.test.ts +21 -2
- package/src/kernel/config/readConfig.test.ts +1 -1
- package/src/kernel/error/renderError.ts +3 -2
- package/src/kernel/error/validOptions.test.ts +57 -0
- package/src/kernel/error/validOptions.ts +45 -0
- package/src/kernel/packs/collect.test.ts +2 -0
- package/src/kernel/packs/compile.test.ts +188 -15
- package/src/kernel/packs/compile.ts +109 -14
- package/src/kernel/packs/cursor.ts +135 -0
- package/src/kernel/packs/filteredEmpty.test.ts +213 -0
- package/src/kernel/packs/graphql/buildLookupDocument.ts +16 -9
- package/src/kernel/packs/graphqlSource.test.ts +152 -0
- package/src/kernel/packs/listNotice.test.ts +156 -0
- package/src/kernel/packs/paging.ts +110 -0
- package/src/kernel/packs/renderPack.ts +186 -13
- package/src/kernel/packs/resolveEntity.test.ts +62 -3
- package/src/kernel/packs/resolveEntity.ts +186 -26
- package/src/kernel/packs/runBodies.ts +196 -26
- package/src/kernel/packs/schema.ts +180 -13
- package/src/kernel/packs/sparql/authorQuery.test.ts +179 -0
- package/src/kernel/packs/sparql/authorQuery.ts +257 -0
- package/src/kernel/packs/sparql/buildListQuery.test.ts +344 -0
- package/src/kernel/packs/sparql/buildListQuery.ts +344 -0
- package/src/kernel/packs/sparql/buildLookupQuery.test.ts +138 -0
- package/src/kernel/packs/sparql/buildLookupQuery.ts +140 -20
- package/src/kernel/packs/sparql/filterValues.test.ts +86 -0
- package/src/kernel/packs/sparql/filterValues.ts +182 -0
- package/src/kernel/packs/sparql/index.ts +30 -14
- package/src/kernel/packs/sparql/runSelect.test.ts +63 -0
- package/src/kernel/packs/sparql/runSelect.ts +42 -2
- package/src/kernel/packs/sparql/searchTerm.ts +29 -0
- package/src/kernel/packs/storyRules.ts +180 -0
- package/src/kernel/packs/tierScope.test.ts +487 -0
- package/src/kernel/packs/tierScope.ts +409 -0
- package/src/kernel/packs/toolDescription.test.ts +13 -10
- package/src/kernel/packs/types.ts +311 -9
- package/src/kernel/project/cli/buildProgram.ts +17 -1
- package/src/kernel/project/cli/dispatch.test.ts +87 -0
- package/src/kernel/project/cli/dispatch.ts +114 -4
- package/src/kernel/project/cli/rootHelp.ts +8 -5
- package/src/kernel/project/cli/suggest.test.ts +35 -0
- package/src/kernel/project/cli/suggestNames.ts +34 -7
- package/src/kernel/project/mcp/registerVerb.ts +5 -1
- package/src/kernel/render/contracts.ts +2 -0
- package/src/kernel/render/prefixes.test.ts +2 -0
- package/src/kernel/render/renderers.test.ts +43 -0
- package/src/kernel/render/renderers.ts +34 -1
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +2 -3
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
- package/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +14 -6
- package/src/kernel/runtime/graphpack/graphpack.test.ts +31 -5
- package/src/kernel/runtime/graphpack/read.ts +17 -13
- package/src/kernel/runtime/loadSession.ts +3 -1
- package/src/kernel/runtime/probe.ts +1 -1
- package/src/kernel/runtime/readEntity.ts +19 -4
- package/src/kernel/runtime/refs/parseRef.test.ts +49 -1
- package/src/kernel/runtime/refs/parseRef.ts +25 -1
- package/src/kernel/runtime/refs/resolve.ts +39 -5
- package/src/kernel/runtime/types.ts +30 -0
- package/src/kernel/spec/emitReference.ts +1 -1
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/types.ts +17 -0
- package/src/testing/PARITY_GAPS.ts +4 -4
- package/src/testing/behavioral/agentSession.mcp.test.ts +43 -39
- package/src/testing/behavioral/completion.test.ts +7 -6
- package/src/testing/behavioral/disclosure.test.ts +39 -37
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +82 -64
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +11 -10
- package/src/testing/behavioral/journeys.cli.test.ts +71 -32
- package/src/testing/behavioral/journeys.defaultPack.test.ts +6 -4
- package/src/testing/behavioral/journeys.firstInstall.test.ts +70 -5
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +4 -3
- package/src/testing/behavioral/journeys.packageStories.test.ts +2 -1
- package/src/testing/behavioral/mcpSurface.test.ts +28 -25
- package/src/testing/behavioral/parity.test.ts +25 -23
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +20 -0
- package/src/testing/eval/cases/effectful.ts +7 -1
- package/src/testing/eval/cases/readNouns.ts +100 -11
- package/src/testing/fixtures/blockGraph.ts +89 -5
- package/src/testing/fixtures/connectGraph.ts +159 -0
- package/src/testing/fixtures/graph/canonical.ts +128 -32
- package/src/testing/helpers/fsProbe.ts +88 -0
- package/src/testing/helpers/runCli.test.ts +44 -0
- package/src/testing/helpers/runCli.ts +27 -3
- package/src/testing/perf/budgets.test.ts +3 -1
- package/src/testing/perf/budgets.ts +138 -54
- package/dist/src/kernel/packs/sparql/applyFilters.js +0 -167
- package/dist/src/kernel/packs/sparql/applyFilters.js.map +0 -1
- package/dist/src/kernel/packs/sparql/applySearch.js +0 -25
- package/dist/src/kernel/packs/sparql/applySearch.js.map +0 -1
- package/src/kernel/packs/sparql/applyFilters.ts +0 -203
- package/src/kernel/packs/sparql/applySearch.ts +0 -33
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* and which properties to read; the query text is generated here so
|
|
6
6
|
* user-supplied names are always escaped SPARQL string literals, and level-gated
|
|
7
7
|
* fields below the active level are excluded from the projection (fetch-gating).
|
|
8
|
-
* Matching on the name is exact and case
|
|
8
|
+
* Matching on the name is exact, and insensitive to case and to surrounding
|
|
9
|
+
* whitespace — see {@link nameFilter}.
|
|
9
10
|
*
|
|
10
11
|
* WHAT an entity's name IS lives in one place — {@link nameBinding} — and every
|
|
11
12
|
* form here uses it: the asserted `by` value, plus, for a lookup that DECLARES
|
|
@@ -48,7 +49,39 @@
|
|
|
48
49
|
* TOTAL order rather than a better arbitrary one.
|
|
49
50
|
*/
|
|
50
51
|
import { activeExpands, activeFields } from "../disclosure.js";
|
|
52
|
+
import { RESERVED_VARIABLE_PREFIX, } from "../types.js";
|
|
51
53
|
import { escapeSparqlString, formatTerm } from "./escape.js";
|
|
54
|
+
/**
|
|
55
|
+
* The variable a scoped name resolve reports each match's tier in.
|
|
56
|
+
*
|
|
57
|
+
* Under the reserved prefix because it is the kernel's, not the story's: it
|
|
58
|
+
* exists so the resolver can tell an in-scope match from an out-of-scope one,
|
|
59
|
+
* and it is stripped before an entity is handed to a formatter
|
|
60
|
+
* ({@link ../resolveEntity}) so no answer grows a field a caller did not ask
|
|
61
|
+
* for.
|
|
62
|
+
*/
|
|
63
|
+
export const SCOPE_TIER_VARIABLE = "__pragmaTier";
|
|
64
|
+
/**
|
|
65
|
+
* Report each match's tier, for a name resolve over a SCOPED noun.
|
|
66
|
+
*
|
|
67
|
+
* A name resolve RANKS and returns everything the name reaches, so the scope
|
|
68
|
+
* does not need to be a filter here — the resolver prefers the in-scope matches
|
|
69
|
+
* and falls back to the rest, which is what lets `block lookup button` answer
|
|
70
|
+
* the global Button while still being able to answer at all for a name that
|
|
71
|
+
* lives only in one product's tier. All it needs from the query is WHICH tier
|
|
72
|
+
* each match belongs to.
|
|
73
|
+
*
|
|
74
|
+
* `OPTIONAL`, so an entity with no tier is still reached: not being in any tier
|
|
75
|
+
* is not a reason to be unaddressable by name.
|
|
76
|
+
*/
|
|
77
|
+
function scopeTierProjection(via) {
|
|
78
|
+
if (via === undefined)
|
|
79
|
+
return { variable: "", optional: "" };
|
|
80
|
+
return {
|
|
81
|
+
variable: ` ?${SCOPE_TIER_VARIABLE}`,
|
|
82
|
+
optional: ` OPTIONAL { ?uri ${formatTerm(via)} ?${SCOPE_TIER_VARIABLE} . }`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
52
85
|
/**
|
|
53
86
|
* The class-constraint clause for a lookup: a single `a` triple for `type`, a
|
|
54
87
|
* VALUES-constrained type triple for `types`, or nothing. All terms are
|
|
@@ -109,13 +142,17 @@ const DERIVED_NAME = 'REPLACE(REPLACE(STR(?uri), "^.*[#/]", ""), "\\\\.", "/")';
|
|
|
109
142
|
*
|
|
110
143
|
* A story whose `list` SYNTHESIZES a name instead of reading one declares
|
|
111
144
|
* `nameFallback: "iri"`, and then the triple becomes OPTIONAL with
|
|
112
|
-
* {@link DERIVED_NAME} behind it. `standard` is the case that exists
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* `
|
|
117
|
-
* answered ENTITY_NOT_FOUND with
|
|
118
|
-
* addressable population was the ~13%
|
|
145
|
+
* {@link DERIVED_NAME} behind it. `standard` is the case that exists. When the
|
|
146
|
+
* defect was measured, 22 of the then-156 live code standards carried a
|
|
147
|
+
* `cs:name`, and the code-standards ontology said so deliberately — "an
|
|
148
|
+
* optional human-readable display title" that "never participates in
|
|
149
|
+
* identity". `standard list` published `react/component/tsdoc` while
|
|
150
|
+
* `standard lookup react/component/tsdoc` answered ENTITY_NOT_FOUND with
|
|
151
|
+
* empty suggestions, because the only addressable population was the ~13%
|
|
152
|
+
* carrying an asserted name. (Upstream has since retired `cs:name` for
|
|
153
|
+
* `rdfs:label`, which every standard carries; the fallback stays because a
|
|
154
|
+
* pack is data, and a dropped label must degrade to the derived name rather
|
|
155
|
+
* than become unaddressable.)
|
|
119
156
|
*
|
|
120
157
|
* INFERRING the fallback from the mere PRESENCE of a class constraint is what
|
|
121
158
|
* this option replaced, and it was over-reach in both directions of the same
|
|
@@ -317,25 +354,57 @@ function rankingClause(lookup) {
|
|
|
317
354
|
orderBy: "ORDER BY DESC(?score) STR(?uri)",
|
|
318
355
|
};
|
|
319
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* The name FILTER both name-addressed resolves share.
|
|
359
|
+
*
|
|
360
|
+
* A name is matched insensitively to case AND to the whitespace it is padded
|
|
361
|
+
* with, because the padding is an artefact of where the name came from rather
|
|
362
|
+
* than part of the name. Sixty-six `ds:name` literals in the shipped graph end
|
|
363
|
+
* in a space, copied across from the source document, and `block lookup
|
|
364
|
+
* Timeline` answered ENTITY_NOT_FOUND while offering "Timeline " straight back
|
|
365
|
+
* as a suggestion — the query and the answer differing by a character no
|
|
366
|
+
* surface prints and no user can type deliberately. The upstream transform is
|
|
367
|
+
* being corrected separately; a resolve a stray space can defeat is a defect on
|
|
368
|
+
* its own, and this is where that half is fixed.
|
|
369
|
+
*
|
|
370
|
+
* BOTH sides are trimmed, never one: the store side by REPLACE over the two
|
|
371
|
+
* anchored runs, the argument side in TypeScript before it is escaped into the
|
|
372
|
+
* literal. Trimming only `?name` would leave `block lookup "Button "` — a name
|
|
373
|
+
* pasted out of a table cell — missing an entity whose own name is clean.
|
|
374
|
+
*
|
|
375
|
+
* The regex the engine reads is `^\s+|\s+$` — the doubled backslashes in the
|
|
376
|
+
* source are the SPARQL string-literal escape and not part of the pattern.
|
|
377
|
+
* Verified against the pinned oxigraph, whose REPLACE takes both the `\s`
|
|
378
|
+
* class and the alternation, and whose `^`/`$` anchor the whole value rather
|
|
379
|
+
* than each line of it.
|
|
380
|
+
*
|
|
381
|
+
* @param name - The user-supplied name, untrimmed and unescaped.
|
|
382
|
+
* @returns The FILTER line to splice into the WHERE clause.
|
|
383
|
+
*/
|
|
384
|
+
function nameFilter(name) {
|
|
385
|
+
return ` FILTER (LCASE(REPLACE(STR(?name), "^\\\\s+|\\\\s+$", "")) = LCASE("${escapeSparqlString(name.trim())}"))`;
|
|
386
|
+
}
|
|
320
387
|
/**
|
|
321
388
|
* Build the SELECT retrieving the entities a name reaches, with their declared
|
|
322
389
|
* fields, best first. The caller answers with the first and names the rest.
|
|
323
390
|
*
|
|
324
391
|
* @param lookup - The pack's lookup declaration.
|
|
325
|
-
* @param name - User-supplied entity name (escaped here).
|
|
392
|
+
* @param name - User-supplied entity name (trimmed and escaped here).
|
|
326
393
|
* @param level - Active canonical level; gated fields below it are excluded.
|
|
327
394
|
* @returns SPARQL SELECT text, ranked and unlimited.
|
|
328
395
|
*/
|
|
329
|
-
export function buildLookupQuery(lookup, name, level) {
|
|
396
|
+
export function buildLookupQuery(lookup, name, level, scopeVia) {
|
|
330
397
|
const { header, constraint, optionals } = lookupProjection(lookup, level);
|
|
331
398
|
const ranking = rankingClause(lookup);
|
|
399
|
+
const scope = scopeTierProjection(scopeVia);
|
|
332
400
|
return [
|
|
333
|
-
header,
|
|
401
|
+
header.replace(" WHERE {", `${scope.variable} WHERE {`),
|
|
334
402
|
constraint,
|
|
335
403
|
nameBinding(lookup),
|
|
336
404
|
ranking.binds,
|
|
337
405
|
optionals,
|
|
338
|
-
|
|
406
|
+
scope.optional,
|
|
407
|
+
nameFilter(name),
|
|
339
408
|
"}",
|
|
340
409
|
ranking.orderBy,
|
|
341
410
|
]
|
|
@@ -373,7 +442,7 @@ export function buildLookupByIriQuery(lookup, iri, level) {
|
|
|
373
442
|
* Build the minimal name→URI resolve for a graphql-sourced lookup (and the
|
|
374
443
|
* shared entry point for the sparql path's name form): maps the user-supplied
|
|
375
444
|
* name to the entity IRIs, everything else comes from the field fetch. The name
|
|
376
|
-
* is
|
|
445
|
+
* is a trimmed, escaped literal; all terms are validated pack terms.
|
|
377
446
|
*
|
|
378
447
|
* Ranked and unlimited, exactly like {@link buildLookupQuery} — the two paths
|
|
379
448
|
* differ in where the VALUES come from, never in which entities a name reaches.
|
|
@@ -381,14 +450,16 @@ export function buildLookupByIriQuery(lookup, iri, level) {
|
|
|
381
450
|
* caller's business, and projecting it would leak a ranking artefact into
|
|
382
451
|
* `--format json`.
|
|
383
452
|
*/
|
|
384
|
-
export function buildNameResolveQuery(lookup, name) {
|
|
453
|
+
export function buildNameResolveQuery(lookup, name, scopeVia) {
|
|
385
454
|
const ranking = rankingClause(lookup);
|
|
455
|
+
const scope = scopeTierProjection(scopeVia);
|
|
386
456
|
return [
|
|
387
|
-
|
|
457
|
+
`SELECT ?uri ?name${scope.variable} WHERE {`,
|
|
388
458
|
buildTypeConstraint(lookup).trimEnd(),
|
|
389
459
|
nameBinding(lookup),
|
|
390
460
|
ranking.binds,
|
|
391
|
-
|
|
461
|
+
scope.optional,
|
|
462
|
+
nameFilter(name),
|
|
392
463
|
"}",
|
|
393
464
|
ranking.orderBy,
|
|
394
465
|
]
|
|
@@ -436,22 +507,54 @@ export function buildLookupIrisQuery(lookup) {
|
|
|
436
507
|
*
|
|
437
508
|
* Injection-safe: the only interpolated value is `entityUri`, the IRI the base
|
|
438
509
|
* lookup already resolved from the store (never user input); the
|
|
439
|
-
* relation/properties
|
|
440
|
-
*
|
|
510
|
+
* relation/properties, the ordering names and the entity's identity property
|
|
511
|
+
* are validated pack terms. SPARQL expands are single-hop, so every select
|
|
512
|
+
* entry here is a plain field.
|
|
513
|
+
*
|
|
514
|
+
* `lookup` is read for ONE thing — the entity's own identity property, which a
|
|
515
|
+
* `blankWhenSelf` field compares its value against. A lookup declaring no such
|
|
516
|
+
* field never binds it.
|
|
441
517
|
*/
|
|
442
|
-
export function buildExpandQuery(expand, entityUri) {
|
|
518
|
+
export function buildExpandQuery(expand, entityUri, lookup) {
|
|
443
519
|
const vars = expand.select.map((field) => `?${field.name}`).join(" ");
|
|
444
520
|
const optionals = expand.select
|
|
445
|
-
.map((field) => "property" in field
|
|
446
|
-
? ` OPTIONAL { ?child ${formatTerm(field.property)} ?${field.name} . }`
|
|
447
|
-
: "")
|
|
521
|
+
.map((field) => "property" in field ? expandFieldClause(field, entityUri, lookup) : "")
|
|
448
522
|
.filter((line) => line !== "")
|
|
449
523
|
.join("\n");
|
|
524
|
+
const order = expand.orderBy && expand.orderBy.length > 0
|
|
525
|
+
? `ORDER BY ${expand.orderBy.map((name) => `?${name}`).join(" ")}`
|
|
526
|
+
: "";
|
|
450
527
|
return [
|
|
451
528
|
`SELECT ${vars} WHERE {`,
|
|
452
529
|
` <${entityUri}> ${formatTerm(expand.relation)} ?child .`,
|
|
453
530
|
optionals,
|
|
454
531
|
"}",
|
|
532
|
+
order,
|
|
533
|
+
]
|
|
534
|
+
.filter((line) => line !== "")
|
|
535
|
+
.join("\n");
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* The OPTIONAL clause reading one child field.
|
|
539
|
+
*
|
|
540
|
+
* A plain field is one line. A `blankWhenSelf` field binds the ENTITY's own
|
|
541
|
+
* identity value beside the child's and keeps the row only where the two
|
|
542
|
+
* differ — inside the OPTIONAL, so a match leaves the variable UNBOUND (the
|
|
543
|
+
* blank cell) rather than dropping the child row. Compared as strings, because
|
|
544
|
+
* the identity value is a literal and the cell may be read through a path that
|
|
545
|
+
* ends at one too.
|
|
546
|
+
*/
|
|
547
|
+
function expandFieldClause(field, entityUri, lookup) {
|
|
548
|
+
const read = `?child ${formatTerm(field.property)} ?${field.name} .`;
|
|
549
|
+
if (!field.blankWhenSelf || !lookup)
|
|
550
|
+
return ` OPTIONAL { ${read} }`;
|
|
551
|
+
const self = `?${RESERVED_VARIABLE_PREFIX}Self`;
|
|
552
|
+
return [
|
|
553
|
+
" OPTIONAL {",
|
|
554
|
+
` ${read}`,
|
|
555
|
+
` <${entityUri}> ${formatTerm(lookup.by)} ${self} .`,
|
|
556
|
+
` FILTER(STR(?${field.name}) != STR(${self}))`,
|
|
557
|
+
" }",
|
|
455
558
|
].join("\n");
|
|
456
559
|
}
|
|
457
560
|
/** Build the SELECT listing all entity names — lookup-miss suggestions. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildLookupQuery.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/buildLookupQuery.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"buildLookupQuery.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/buildLookupQuery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admit (or refuse) the values a caller supplied for a list story's declared
|
|
3
|
+
* filters, and hand the admitted ones to the query builder.
|
|
4
|
+
*
|
|
5
|
+
* This is the half of filtering that does NOT move into the query. Deciding
|
|
6
|
+
* whether a value is admissible is a question about the graph's vocabulary;
|
|
7
|
+
* deciding which rows carry it is a question about the population. Keeping them
|
|
8
|
+
* apart is what makes the two answers a caller gets distinguishable, and that
|
|
9
|
+
* distinction is load-bearing:
|
|
10
|
+
*
|
|
11
|
+
* - a value the vocabulary does NOT admit is `INVALID_INPUT`, carrying the
|
|
12
|
+
* admissible values as `validOptions` — the caller mistyped;
|
|
13
|
+
* - a value it DOES admit that no row carries is a calm empty list, exit 0,
|
|
14
|
+
* with the story's own `emptyRecovery` as the hint — `standard categories`
|
|
15
|
+
* reports a category with count 0, and asking for it is not a mistake.
|
|
16
|
+
*
|
|
17
|
+
* WHICH part of the graph is the vocabulary matters, and it is not the rows.
|
|
18
|
+
* Before the filters moved inside the query the rows were the FALLBACK
|
|
19
|
+
* vocabulary for a filter that declared none — knowingly narrower than the
|
|
20
|
+
* truth, but the only evidence there was. A page makes that fallback actively
|
|
21
|
+
* wrong: a real value outside the window would be refused as a bad argument,
|
|
22
|
+
* with a truncated list of alternatives. So the fallback is gone and the
|
|
23
|
+
* declaration rule replaces it — a filter declares `values` or a `vocabulary`
|
|
24
|
+
* query, and one that declares neither is refused where it is declared
|
|
25
|
+
* ({@link ../schema}) rather than misanswering at run time.
|
|
26
|
+
*/
|
|
27
|
+
import { PragmaError } from "../../error/index.js";
|
|
28
|
+
/**
|
|
29
|
+
* Turn the filter arguments a caller supplied into query predicates.
|
|
30
|
+
*
|
|
31
|
+
* @param filters - The story's declared filters (absent means none).
|
|
32
|
+
* @param params - Story parameters as provided by the surface.
|
|
33
|
+
* @param vocabularies - Authoritative values per value-free filter param.
|
|
34
|
+
* @param label - The story's label, for a configuration diagnosis.
|
|
35
|
+
* @returns One predicate per filter the caller supplied a value for.
|
|
36
|
+
* @throws PragmaError INVALID_INPUT when a value is not in a filter's declared
|
|
37
|
+
* set or its graph vocabulary, or when a value-free filter receives a
|
|
38
|
+
* non-string value; CONFIG_ERROR when a value-free filter declares no
|
|
39
|
+
* vocabulary.
|
|
40
|
+
*/
|
|
41
|
+
export function resolveFilterPredicates(filters, params, vocabularies, label) {
|
|
42
|
+
const predicates = [];
|
|
43
|
+
for (const filter of filters ?? []) {
|
|
44
|
+
const provided = params[filter.param];
|
|
45
|
+
if (provided === undefined)
|
|
46
|
+
continue;
|
|
47
|
+
// A repeated CLI flag accumulates into an array; MCP args stay scalar.
|
|
48
|
+
// Several values for ONE filter are a union (a row matches any of them);
|
|
49
|
+
// several filters still combine conjunctively.
|
|
50
|
+
const occurrences = Array.isArray(provided) ? provided : [provided];
|
|
51
|
+
if (occurrences.length === 0)
|
|
52
|
+
continue;
|
|
53
|
+
const values = filter.values;
|
|
54
|
+
const terms = occurrences.map((occurrence) => values === undefined
|
|
55
|
+
? requireStringValue(occurrence, filter)
|
|
56
|
+
: canonicalizeFilterValue(occurrence, filter, values));
|
|
57
|
+
if (values === undefined) {
|
|
58
|
+
rejectUnknownValue(requireVocabulary(filter, vocabularies, label), filter, occurrences, terms);
|
|
59
|
+
}
|
|
60
|
+
predicates.push({
|
|
61
|
+
variable: filter.variable,
|
|
62
|
+
match: filter.match ?? "exact",
|
|
63
|
+
terms,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return predicates;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The vocabulary a value-free filter is checked against.
|
|
70
|
+
*
|
|
71
|
+
* @throws PragmaError CONFIG_ERROR when the filter declares neither `values`
|
|
72
|
+
* nor a `vocabulary` — the declaration rule the schema enforces, restated at
|
|
73
|
+
* the point of use so a story that reached here another way still says why.
|
|
74
|
+
*/
|
|
75
|
+
function requireVocabulary(filter, vocabularies, label) {
|
|
76
|
+
const vocabulary = vocabularies?.get(filter.param);
|
|
77
|
+
if (vocabulary)
|
|
78
|
+
return vocabulary;
|
|
79
|
+
throw PragmaError.configError(`Filter "--${filter.param}" in ${label} declares neither "values" nor a ` +
|
|
80
|
+
'"vocabulary" query, so there is nothing to check a caller\'s value against.');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Reject a value-free filter value the vocabulary does not admit, naming the
|
|
84
|
+
* ones it does.
|
|
85
|
+
*
|
|
86
|
+
* Silent when the vocabulary is EMPTY: an unbuilt or genuinely-empty store is
|
|
87
|
+
* not the caller's mistake, and the list's own `emptyRecovery` is the right
|
|
88
|
+
* voice for it.
|
|
89
|
+
*
|
|
90
|
+
* A value the vocabulary admits is never rejected here even when no row carries
|
|
91
|
+
* it — a real slug with zero standards is a calm empty list, which is what the
|
|
92
|
+
* tool descriptions document and what `standard categories` reporting count 0
|
|
93
|
+
* promises.
|
|
94
|
+
*
|
|
95
|
+
* @throws PragmaError INVALID_INPUT when a term matches none of the admissible
|
|
96
|
+
* values, carrying them as `validOptions`.
|
|
97
|
+
*/
|
|
98
|
+
function rejectUnknownValue(vocabulary, filter, occurrences, terms) {
|
|
99
|
+
const admissible = new Map();
|
|
100
|
+
for (const value of vocabulary) {
|
|
101
|
+
const key = value.normalize("NFC").toLowerCase();
|
|
102
|
+
if (!admissible.has(key))
|
|
103
|
+
admissible.set(key, value.normalize("NFC"));
|
|
104
|
+
}
|
|
105
|
+
if (admissible.size === 0)
|
|
106
|
+
return;
|
|
107
|
+
const index = terms.findIndex((term) => !admissible.has(term.toLowerCase()));
|
|
108
|
+
if (index === -1)
|
|
109
|
+
return;
|
|
110
|
+
const validOptions = [...admissible.values()].sort();
|
|
111
|
+
// The VALUES ride `validOptions`, which every renderer already prints (and
|
|
112
|
+
// truncates, and counts). Repeating them in the recovery printed the same
|
|
113
|
+
// 40-name, 1.4KB list twice on one error — see `error/validOptions.ts`.
|
|
114
|
+
throw PragmaError.invalidInput(filter.param, String(occurrences[index]), {
|
|
115
|
+
validOptions,
|
|
116
|
+
recovery: {
|
|
117
|
+
message: `Pick one of the ${validOptions.length} values --${filter.param} accepts.`,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/** @throws PragmaError INVALID_INPUT when a value-free filter value is not a string. */
|
|
122
|
+
function requireStringValue(provided, filter) {
|
|
123
|
+
if (typeof provided !== "string") {
|
|
124
|
+
throw PragmaError.invalidInput(filter.param, String(provided), {
|
|
125
|
+
recovery: { message: `Provide a string value for --${filter.param}.` },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return provided.trim().normalize("NFC");
|
|
129
|
+
}
|
|
130
|
+
/** @throws PragmaError INVALID_INPUT when the value is not in the declared set. */
|
|
131
|
+
function canonicalizeFilterValue(provided, filter, values) {
|
|
132
|
+
if (typeof provided === "string") {
|
|
133
|
+
const normalized = provided.trim().normalize("NFC");
|
|
134
|
+
const match = values.find((value) => value.normalize("NFC").toLowerCase() === normalized.toLowerCase());
|
|
135
|
+
if (match !== undefined)
|
|
136
|
+
return match.normalize("NFC");
|
|
137
|
+
}
|
|
138
|
+
throw PragmaError.invalidInput(filter.param, String(provided), {
|
|
139
|
+
validOptions: [...values],
|
|
140
|
+
recovery: {
|
|
141
|
+
message: `Pick one of the ${values.length} values --${filter.param} accepts.`,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=filterValues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterValues.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/filterValues.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The SPARQL path — every generated read a pack story performs
|
|
3
|
-
* row operations that must NOT be generated.
|
|
2
|
+
* The SPARQL path — every generated read a pack story performs.
|
|
4
3
|
*
|
|
5
4
|
* The domain is organised around one invariant: user input never reaches query
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* goes through, which is what
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
5
|
+
* TEXT. The query builders compose only from validated pack terms, the page's
|
|
6
|
+
* own integers, and escaped literals bound through `VALUES` — so a name a user
|
|
7
|
+
* typed becomes a SPARQL string literal or nothing; `runSelect` is the single
|
|
8
|
+
* choke point every one of those trusted queries goes through, which is what
|
|
9
|
+
* makes "a generated query failed" distinguishable from "the user's own
|
|
10
|
+
* `graph query` failed".
|
|
11
|
+
*
|
|
12
|
+
* Filtering and search used to sit here as predicates over the resolved ROWS —
|
|
13
|
+
* kept in this domain precisely because they were the operations it would
|
|
14
|
+
* otherwise be tempting to express as query text. They are query text now, and
|
|
15
|
+
* the temptation is answered a different way: {@link ./buildListQuery} is the
|
|
16
|
+
* only thing that composes a predicate, it binds every caller-supplied value,
|
|
17
|
+
* and it never edits the author's own query. What stayed on the row side is the
|
|
18
|
+
* part that was never about rows at all — deciding whether a value is
|
|
19
|
+
* ADMISSIBLE ({@link ./filterValues}), which is a question about the graph's
|
|
20
|
+
* vocabulary and is what keeps a refusal distinguishable from a calm empty
|
|
21
|
+
* answer.
|
|
15
22
|
*
|
|
16
23
|
* The escaping primitives stay internal. They are how the builders keep that
|
|
17
24
|
* invariant, not a service for composing query text elsewhere — a caller with
|
|
18
25
|
* the escaper is a caller who can build an unvalidated query, which is exactly
|
|
19
|
-
* the shape this domain exists to prevent.
|
|
26
|
+
* the shape this domain exists to prevent. {@link ./projection}'s reader is
|
|
27
|
+
* internal for the same reason: it exists so a wrapping select can reproduce
|
|
28
|
+
* the author's own projection, not so callers can reason about author text.
|
|
20
29
|
*
|
|
21
30
|
* Two names re-exported by `buildLookupQuery.ts` for its own callers'
|
|
22
31
|
* convenience — the disclosure-level field and expand selectors — are also
|
|
@@ -24,8 +33,9 @@
|
|
|
24
33
|
* through here would make this domain look like their owner and freeze a
|
|
25
34
|
* pass-through that has no reason to be permanent.
|
|
26
35
|
*/
|
|
27
|
-
export {
|
|
28
|
-
export { applyPackSearch } from "./applySearch.js";
|
|
36
|
+
export { buildListQuery } from "./buildListQuery.js";
|
|
29
37
|
export { buildExpandQuery, buildLookupByIriQuery, buildLookupNamesQuery, buildLookupQuery, buildNameResolveQuery, } from "./buildLookupQuery.js";
|
|
38
|
+
export { resolveFilterPredicates } from "./filterValues.js";
|
|
30
39
|
export { runSelect } from "./runSelect.js";
|
|
40
|
+
export { readSearchTerm } from "./searchTerm.js";
|
|
31
41
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAOH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -68,15 +68,18 @@ function unboundPrefixError(source) {
|
|
|
68
68
|
* Returns the inferred facade result type, so this module stays clear of a
|
|
69
69
|
* static `@canonical/ke` import (the lazy-dispatch guard).
|
|
70
70
|
*/
|
|
71
|
-
async function queryOrRemap(rt, query, source) {
|
|
71
|
+
async function queryOrRemap(rt, query, source, degradeOnUnboundPrefix) {
|
|
72
72
|
try {
|
|
73
73
|
return await rt.query.sparql(query);
|
|
74
74
|
}
|
|
75
75
|
catch (error) {
|
|
76
76
|
if (error instanceof PragmaError)
|
|
77
77
|
throw error;
|
|
78
|
-
if (isUnseededStoreError(error))
|
|
78
|
+
if (isUnseededStoreError(error)) {
|
|
79
|
+
if (degradeOnUnboundPrefix)
|
|
80
|
+
return undefined;
|
|
79
81
|
throw unboundPrefixError(source);
|
|
82
|
+
}
|
|
80
83
|
throw error;
|
|
81
84
|
}
|
|
82
85
|
}
|
|
@@ -85,14 +88,17 @@ async function queryOrRemap(rt, query, source) {
|
|
|
85
88
|
* @param query - SPARQL SELECT text (prefixes auto-applied by the store).
|
|
86
89
|
* @param source - The story's provenance: its label for attribution, and the
|
|
87
90
|
* layer that declared it, which decides how an unbound prefix is diagnosed.
|
|
91
|
+
* @param options - See {@link RunSelectOptions}; defaults to raising.
|
|
88
92
|
* @returns One record per row, keyed by SELECT variable name.
|
|
89
93
|
* @throws PragmaError CONFIG_ERROR when the query is not a SELECT, or when a
|
|
90
94
|
* config/package story names a prefix the graph does not bind;
|
|
91
95
|
* STORE_UNAVAILABLE (exit 3) when a distribution story finds one.
|
|
92
96
|
* @note Impure — queries the store through the facade.
|
|
93
97
|
*/
|
|
94
|
-
export async function runSelect(rt, query, source) {
|
|
95
|
-
const result = await queryOrRemap(rt, query, source);
|
|
98
|
+
export async function runSelect(rt, query, source, options = {}) {
|
|
99
|
+
const result = await queryOrRemap(rt, query, source, options.degradeOnUnboundPrefix === true);
|
|
100
|
+
if (result === undefined)
|
|
101
|
+
return [];
|
|
96
102
|
if (result.type !== "select") {
|
|
97
103
|
throw PragmaError.configError(`Story query in ${source.label} must be a SELECT (got ${result.type}).`);
|
|
98
104
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runSelect.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/runSelect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIhE;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,oBAAoB,CAAC,KAAc;IAC1C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,kBAAkB,CAAC,MAAmB;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACrC,OAAO,WAAW,CAAC,WAAW,CAC5B,kBAAkB,MAAM,CAAC,KAAK,0CAA0C;YACtE,2EAA2E,CAC9E,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,gBAAgB,CACjC,mFAAmF,EACnF;QACE,QAAQ,EAAE,WAAW,CACnB,gBAAgB,EAChB,kDAAkD;QAClD,qEAAqE;QACrE,oDAAoD;QACpD,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAC3B;KACF,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,YAAY,CACzB,EAAgC,EAChC,KAAa,EACb,MAAmB;
|
|
1
|
+
{"version":3,"file":"runSelect.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/runSelect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIhE;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,oBAAoB,CAAC,KAAc;IAC1C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,kBAAkB,CAAC,MAAmB;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,cAAc,EAAE,CAAC;QACrC,OAAO,WAAW,CAAC,WAAW,CAC5B,kBAAkB,MAAM,CAAC,KAAK,0CAA0C;YACtE,2EAA2E,CAC9E,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,gBAAgB,CACjC,mFAAmF,EACnF;QACE,QAAQ,EAAE,WAAW,CACnB,gBAAgB,EAChB,kDAAkD;QAClD,qEAAqE;QACrE,oDAAoD;QACpD,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAC3B;KACF,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,YAAY,CACzB,EAAgC,EAChC,KAAa,EACb,MAAmB,EACnB,sBAA+B;IAE/B,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW;YAAE,MAAM,KAAK,CAAC;QAC9C,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,sBAAsB;gBAAE,OAAO,SAAS,CAAC;YAC7C,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AA8BD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,EAAgC,EAChC,KAAa,EACb,MAAmB,EACnB,UAA4B,EAAE;IAE9B,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,EAAE,EACF,KAAK,EACL,MAAM,EACN,OAAO,CAAC,sBAAsB,KAAK,IAAI,CACxC,CAAC;IACF,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACpC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,WAAW,CAAC,WAAW,CAC3B,kBAAkB,MAAM,CAAC,KAAK,0BAA0B,MAAM,CAAC,IAAI,IAAI,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,QAAqB,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a list story's free-text search argument.
|
|
3
|
+
*
|
|
4
|
+
* The comparison itself compiles into the query
|
|
5
|
+
* ({@link ./buildListQuery.buildListQuery}); what stays here is the reading of
|
|
6
|
+
* the argument — NFC-normalised and trimmed, with a non-string or empty term a
|
|
7
|
+
* no-op rather than a predicate that matches everything. Normalising on this
|
|
8
|
+
* side is the whole of it: the store has no normaliser, so the graph's own
|
|
9
|
+
* spelling is compared as it is stored.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* @param search - The declared search (absent means the story has none).
|
|
13
|
+
* @param params - Story parameters as provided by the surface.
|
|
14
|
+
* @returns The search to compile, or `undefined` when there is nothing to search for.
|
|
15
|
+
*/
|
|
16
|
+
export function readSearchTerm(search, params) {
|
|
17
|
+
const provided = params.search;
|
|
18
|
+
if (search === undefined || typeof provided !== "string")
|
|
19
|
+
return undefined;
|
|
20
|
+
const term = provided.trim().normalize("NFC");
|
|
21
|
+
if (term === "")
|
|
22
|
+
return undefined;
|
|
23
|
+
return { variables: search.variables, term };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=searchTerm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchTerm.js","sourceRoot":"","sources":["../../../../../src/kernel/packs/sparql/searchTerm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,MAA8B,EAC9B,MAA+B;IAE/B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/B,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC3E,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;AAC/C,CAAC"}
|