@lucern/graph-primitives 1.0.28 → 1.0.30
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/dist/{beliefDecay-DZ6tkLYq.d.ts → beliefDecay-BmkEk5OJ.d.ts} +3 -3
- package/dist/beliefDecay.d.ts +1 -1
- package/dist/beliefDecay.js +448 -314
- package/dist/beliefDecay.js.map +1 -1
- package/dist/{beliefEvidenceLinks-CWOXxxJg.d.ts → beliefEvidenceLinks-BzfjON_6.d.ts} +13 -13
- package/dist/beliefEvidenceLinks.d.ts +1 -1
- package/dist/beliefEvidenceLinks.js +843 -624
- package/dist/beliefEvidenceLinks.js.map +1 -1
- package/dist/beliefEvidenceLinks.operational.d.ts +7 -5
- package/dist/beliefEvidenceLinks.operational.js +91 -18
- package/dist/beliefEvidenceLinks.operational.js.map +1 -1
- package/dist/beliefLifecycle.js.map +1 -1
- package/dist/confidencePropagationDispatch.d.ts +28 -27
- package/dist/confidencePropagationDispatch.js +157 -99
- package/dist/confidencePropagationDispatch.js.map +1 -1
- package/dist/{contradictions-51VLsESq.d.ts → contradictions-BATPuZTL.d.ts} +10 -10
- package/dist/contradictions.d.ts +1 -1
- package/dist/contradictions.js +398 -228
- package/dist/contradictions.js.map +1 -1
- package/dist/convex.d.ts +65 -30
- package/dist/convex.js +7 -3
- package/dist/convex.js.map +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/edgeValidation.js +293 -85
- package/dist/edgeValidation.js.map +1 -1
- package/dist/edges/contains.d.ts +1 -1
- package/dist/edges/contains.js.map +1 -1
- package/dist/edges/contradicts.d.ts +1 -1
- package/dist/edges/contradicts.js.map +1 -1
- package/dist/edges/{dependsOn.d.ts → depends-on.d.ts} +1 -1
- package/dist/edges/{dependsOn.js → depends-on.js} +4 -4
- package/dist/edges/depends-on.js.map +1 -0
- package/dist/edges/{derivedFrom.d.ts → derived-from.d.ts} +1 -1
- package/dist/edges/{derivedFrom.js → derived-from.js} +3 -3
- package/dist/edges/derived-from.js.map +1 -0
- package/dist/edges/elaborates.d.ts +1 -1
- package/dist/edges/elaborates.js.map +1 -1
- package/dist/edges/index.d.ts +7 -3
- package/dist/edges/index.js +7 -4
- package/dist/edges/index.js.map +1 -1
- package/dist/edges/informs.d.ts +1 -1
- package/dist/edges/informs.js.map +1 -1
- package/dist/edges/{propagationTypes.d.ts → propagation-types.d.ts} +14 -14
- package/dist/edges/{propagationTypes.js → propagation-types.js} +3 -3
- package/dist/edges/propagation-types.js.map +1 -0
- package/dist/edges/refutes.d.ts +1 -1
- package/dist/edges/refutes.js.map +1 -1
- package/dist/edges/supports.d.ts +1 -1
- package/dist/edges/supports.js.map +1 -1
- package/dist/edges/tests.d.ts +1 -1
- package/dist/edges/tests.js.map +1 -1
- package/dist/edges/utils.d.ts +1 -1
- package/dist/edges/utils.js.map +1 -1
- package/dist/embeddingTrigger.d.ts +14 -6
- package/dist/embeddingTrigger.js +11 -14
- package/dist/embeddingTrigger.js.map +1 -1
- package/dist/{entityBridge-DMaKooYn.d.ts → entityBridge-BhVDM3pc.d.ts} +5 -5
- package/dist/entityBridge.d.ts +1 -1
- package/dist/entityBridge.js +602 -225
- package/dist/entityBridge.js.map +1 -1
- package/dist/entityCanonicalMatch.d.ts +14 -12
- package/dist/entityCanonicalMatch.js.map +1 -1
- package/dist/{entityLifecycle-CvgSK5FV.d.ts → entityLifecycle-BsfCz9pS.d.ts} +5 -9
- package/dist/entityLifecycle.d.ts +1 -1
- package/dist/entityLifecycle.js +857 -515
- package/dist/entityLifecycle.js.map +1 -1
- package/dist/{entityValidation-KLZ_Xl2D.d.ts → entityValidation-B1yNEHJx.d.ts} +7 -6
- package/dist/entityValidation.d.ts +3 -1
- package/dist/entityValidation.js +60 -8
- package/dist/entityValidation.js.map +1 -1
- package/dist/{epistemicAnswers-C5ib4z6_.d.ts → epistemicAnswers-f47YMu9U.d.ts} +6 -6
- package/dist/epistemicAnswers.d.ts +1 -1
- package/dist/epistemicAnswers.js +587 -545
- package/dist/epistemicAnswers.js.map +1 -1
- package/dist/epistemicBeliefs.admin.d.ts +8 -8
- package/dist/epistemicBeliefs.admin.js +366 -203
- package/dist/epistemicBeliefs.admin.js.map +1 -1
- package/dist/epistemicBeliefs.backfills.d.ts +8 -8
- package/dist/epistemicBeliefs.backfills.js +655 -308
- package/dist/epistemicBeliefs.backfills.js.map +1 -1
- package/dist/epistemicBeliefs.confidence.d.ts +19 -14
- package/dist/epistemicBeliefs.confidence.js +634 -423
- package/dist/epistemicBeliefs.confidence.js.map +1 -1
- package/dist/epistemicBeliefs.core.d.ts +6 -6
- package/dist/epistemicBeliefs.core.js +719 -411
- package/dist/epistemicBeliefs.core.js.map +1 -1
- package/dist/epistemicBeliefs.d.ts +11 -8
- package/dist/epistemicBeliefs.forkEvidence.d.ts +2 -0
- package/dist/epistemicBeliefs.forkEvidence.js +8 -28
- package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
- package/dist/epistemicBeliefs.helpers.d.ts +69 -74
- package/dist/epistemicBeliefs.helpers.js +359 -248
- package/dist/epistemicBeliefs.helpers.js.map +1 -1
- package/dist/epistemicBeliefs.internal.d.ts +5 -5
- package/dist/epistemicBeliefs.internal.js +1246 -1044
- package/dist/epistemicBeliefs.internal.js.map +1 -1
- package/dist/epistemicBeliefs.js +4922 -3608
- package/dist/epistemicBeliefs.js.map +1 -1
- package/dist/epistemicBeliefs.lifecycle.d.ts +5 -5
- package/dist/epistemicBeliefs.lifecycle.js +1137 -818
- package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
- package/dist/epistemicBeliefs.links.d.ts +7 -7
- package/dist/epistemicBeliefs.links.js +408 -307
- package/dist/epistemicBeliefs.links.js.map +1 -1
- package/dist/epistemicBeliefs.queries.d.ts +4 -4
- package/dist/epistemicBeliefs.queries.js +175 -20
- package/dist/epistemicBeliefs.queries.js.map +1 -1
- package/dist/epistemicBeliefs.topicAnchor.d.ts +6 -4
- package/dist/epistemicBeliefs.topicAnchor.js +12 -5
- package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
- package/dist/epistemicContracts.d.ts +28 -3
- package/dist/epistemicContracts.evaluators.d.ts +2 -0
- package/dist/epistemicContracts.evaluators.js +1063 -613
- package/dist/epistemicContracts.evaluators.js.map +1 -1
- package/dist/epistemicContracts.handlers.d.ts +15 -32
- package/dist/epistemicContracts.handlers.js +2086 -1644
- package/dist/epistemicContracts.handlers.js.map +1 -1
- package/dist/epistemicContracts.js +1131 -672
- package/dist/epistemicContracts.js.map +1 -1
- package/dist/epistemicContracts.metrics.d.ts +2 -0
- package/dist/epistemicContracts.metrics.js +375 -158
- package/dist/epistemicContracts.metrics.js.map +1 -1
- package/dist/epistemicContracts.types.d.ts +87 -81
- package/dist/epistemicEdgeCreation.d.ts +2 -0
- package/dist/epistemicEdgeCreation.js +87 -16
- package/dist/epistemicEdgeCreation.js.map +1 -1
- package/dist/{epistemicEdges-BF-cn4i3.d.ts → epistemicEdges-BGBh0QSP.d.ts} +4 -7
- package/dist/epistemicEdges.d.ts +6 -5
- package/dist/epistemicEdges.handlers.d.ts +3 -3
- package/dist/epistemicEdges.handlers.js +129 -24
- package/dist/epistemicEdges.handlers.js.map +1 -1
- package/dist/epistemicEdges.helpers.d.ts +6 -4
- package/dist/epistemicEdges.helpers.js +37 -2
- package/dist/epistemicEdges.helpers.js.map +1 -1
- package/dist/epistemicEdges.js +1969 -1205
- package/dist/epistemicEdges.js.map +1 -1
- package/dist/epistemicEdges.mutations.d.ts +7 -7
- package/dist/epistemicEdges.mutations.js +960 -583
- package/dist/epistemicEdges.mutations.js.map +1 -1
- package/dist/epistemicEdges.queries.d.ts +16 -16
- package/dist/epistemicEdges.queries.js +639 -367
- package/dist/epistemicEdges.queries.js.map +1 -1
- package/dist/epistemicEdges.types.d.ts +10 -8
- package/dist/epistemicEvidence.d.ts +4 -1
- package/dist/epistemicEvidence.js +937 -536
- package/dist/epistemicEvidence.js.map +1 -1
- package/dist/epistemicEvidenceHelpers.d.ts +26 -10
- package/dist/epistemicEvidenceHelpers.js +239 -200
- package/dist/epistemicEvidenceHelpers.js.map +1 -1
- package/dist/epistemicEvidenceMutations.d.ts +8 -8
- package/dist/epistemicEvidenceMutations.js +844 -696
- package/dist/epistemicEvidenceMutations.js.map +1 -1
- package/dist/epistemicEvidenceQueries.d.ts +8 -8
- package/dist/epistemicEvidenceQueries.js +514 -238
- package/dist/epistemicEvidenceQueries.js.map +1 -1
- package/dist/epistemicHelpers.d.ts +4 -2
- package/dist/epistemicHelpers.js +308 -134
- package/dist/epistemicHelpers.js.map +1 -1
- package/dist/epistemicInsert.d.ts +16 -4
- package/dist/epistemicInsert.js +6 -3
- package/dist/epistemicInsert.js.map +1 -1
- package/dist/epistemicLayerRules.d.ts +10 -8
- package/dist/epistemicLayerRules.js +1 -5
- package/dist/epistemicLayerRules.js.map +1 -1
- package/dist/{epistemicLinking-CfE00tHJ.d.ts → epistemicLinking-CsCDv2cN.d.ts} +3 -3
- package/dist/epistemicLinking.d.ts +1 -1
- package/dist/epistemicLinking.js +177 -100
- package/dist/epistemicLinking.js.map +1 -1
- package/dist/epistemicNodeCreation.d.ts +2 -0
- package/dist/epistemicNodeCreation.js +203 -40
- package/dist/epistemicNodeCreation.js.map +1 -1
- package/dist/{epistemicNodes-BCQxpYx_.d.ts → epistemicNodes-CokAgBHg.d.ts} +3 -3
- package/dist/epistemicNodes.d.ts +3 -3
- package/dist/epistemicNodes.helpers.d.ts +24 -15
- package/dist/epistemicNodes.helpers.js.map +1 -1
- package/dist/epistemicNodes.internal.d.ts +6 -6
- package/dist/epistemicNodes.internal.js +389 -319
- package/dist/epistemicNodes.internal.js.map +1 -1
- package/dist/epistemicNodes.js +704 -508
- package/dist/epistemicNodes.js.map +1 -1
- package/dist/epistemicNodes.mutations.d.ts +6 -6
- package/dist/epistemicNodes.mutations.js +564 -467
- package/dist/epistemicNodes.mutations.js.map +1 -1
- package/dist/epistemicNodes.queries.d.ts +8 -8
- package/dist/epistemicNodes.queries.js +311 -314
- package/dist/epistemicNodes.queries.js.map +1 -1
- package/dist/epistemicNodes.validators.d.ts +2 -2
- package/dist/epistemicNodes.validators.js.map +1 -1
- package/dist/epistemicQuestions.conviction.d.ts +8 -8
- package/dist/epistemicQuestions.conviction.js +665 -484
- package/dist/epistemicQuestions.conviction.js.map +1 -1
- package/dist/epistemicQuestions.create.d.ts +4 -4
- package/dist/epistemicQuestions.create.js +640 -612
- package/dist/epistemicQuestions.create.js.map +1 -1
- package/dist/epistemicQuestions.d.ts +8 -5
- package/dist/epistemicQuestions.evidence.d.ts +2 -2
- package/dist/epistemicQuestions.evidence.js +475 -383
- package/dist/epistemicQuestions.evidence.js.map +1 -1
- package/dist/epistemicQuestions.helpers.d.ts +125 -24
- package/dist/epistemicQuestions.helpers.js +240 -209
- package/dist/epistemicQuestions.helpers.js.map +1 -1
- package/dist/epistemicQuestions.js +3474 -2823
- package/dist/epistemicQuestions.js.map +1 -1
- package/dist/epistemicQuestions.lifecycle.d.ts +2 -2
- package/dist/epistemicQuestions.lifecycle.js +607 -546
- package/dist/epistemicQuestions.lifecycle.js.map +1 -1
- package/dist/epistemicQuestions.queries.d.ts +12 -7
- package/dist/epistemicQuestions.queries.js +305 -244
- package/dist/epistemicQuestions.queries.js.map +1 -1
- package/dist/epistemicQuestions.sprint.d.ts +2 -2
- package/dist/epistemicQuestions.sprint.js +600 -394
- package/dist/epistemicQuestions.sprint.js.map +1 -1
- package/dist/epistemicQuestions.tail.d.ts +6 -6
- package/dist/epistemicQuestions.tail.js +572 -433
- package/dist/epistemicQuestions.tail.js.map +1 -1
- package/dist/{epistemicSources-dlKj58Jp.d.ts → epistemicSources-DQtaEkWs.d.ts} +4 -4
- package/dist/epistemicSources.d.ts +1 -1
- package/dist/epistemicSources.js +352 -312
- package/dist/epistemicSources.js.map +1 -1
- package/dist/evaluators/index.d.ts +8 -6
- package/dist/evaluators/index.js +399 -167
- package/dist/evaluators/index.js.map +1 -1
- package/dist/evaluators/lint-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{lintCheckerEvaluator.js → lint-checker-evaluator.js} +10 -5
- package/dist/evaluators/lint-checker-evaluator.js.map +1 -0
- package/dist/evaluators/{sentryCheckerEvaluator.d.ts → sentry-checker-evaluator.d.ts} +7 -2
- package/dist/evaluators/{sentryCheckerEvaluator.js → sentry-checker-evaluator.js} +3 -3
- package/dist/evaluators/sentry-checker-evaluator.js.map +1 -0
- package/dist/evaluators/shared.d.ts +2 -2
- package/dist/evaluators/shared.js +3 -1
- package/dist/evaluators/shared.js.map +1 -1
- package/dist/evaluators/{testRunnerEvaluator.d.ts → test-runner-evaluator.d.ts} +6 -1
- package/dist/evaluators/{testRunnerEvaluator.js → test-runner-evaluator.js} +6 -4
- package/dist/evaluators/test-runner-evaluator.js.map +1 -0
- package/dist/evaluators/tsc-checker-evaluator.d.ts +16 -0
- package/dist/evaluators/{tscCheckerEvaluator.js → tsc-checker-evaluator.js} +10 -5
- package/dist/evaluators/tsc-checker-evaluator.js.map +1 -0
- package/dist/graphTypes.js +6 -2
- package/dist/graphTypes.js.map +1 -1
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.js +313 -93
- package/dist/helpers.js.map +1 -1
- package/dist/{index-C-Kyd7hD.d.ts → index-DZxyC9Pb.d.ts} +7 -6
- package/dist/index.d.ts +87 -83
- package/dist/index.js +15677 -10594
- package/dist/index.js.map +1 -1
- package/dist/invariantEnforcement.d.ts +3 -3
- package/dist/invariantEnforcement.js.map +1 -1
- package/dist/logicalRoleInference.d.ts +2 -0
- package/dist/logicalRoleInference.js +1 -1
- package/dist/logicalRoleInference.js.map +1 -1
- package/dist/matcherFeedbackUtils.d.ts +2 -2
- package/dist/matcherFeedbackUtils.js.map +1 -1
- package/dist/{ontology-matching-C6rrz2VP.d.ts → ontology-matching-C-mYFrir.d.ts} +16 -16
- package/dist/ontology-matching.d.ts +1 -1
- package/dist/{ontologyApproval-CFYmqKmk.d.ts → ontologyApproval-BVt0feJi.d.ts} +10 -10
- package/dist/ontologyApproval.d.ts +1 -1
- package/dist/ontologyApproval.js +7 -1
- package/dist/ontologyApproval.js.map +1 -1
- package/dist/ontologyDefinitions.d.ts +14 -24
- package/dist/ontologyDefinitions.js +269 -34
- package/dist/ontologyDefinitions.js.map +1 -1
- package/dist/ontologyHelpers.d.ts +13 -13
- package/dist/ontologyHelpers.js.map +1 -1
- package/dist/{ontologyRegistry-B67rPJ16.d.ts → ontologyRegistry-CljS-ENv.d.ts} +2 -2
- package/dist/ontologyRegistry.d.ts +1 -1
- package/dist/ontologyRegistry.js +34 -6
- package/dist/ontologyRegistry.js.map +1 -1
- package/dist/{projectionReconciliation-jww2fBI0.d.ts → projectionReconciliation-DnrSgHSQ.d.ts} +4 -4
- package/dist/projectionReconciliation.d.ts +1 -1
- package/dist/projectionReconciliation.js +57 -10
- package/dist/projectionReconciliation.js.map +1 -1
- package/dist/{projectionStaleness-CmdbpjVK.d.ts → projectionStaleness-C8ImQ2zP.d.ts} +17 -17
- package/dist/projectionStaleness.d.ts +1 -1
- package/dist/projectionStaleness.js +8 -2
- package/dist/projectionStaleness.js.map +1 -1
- package/dist/proof-attestation.json +1 -1
- package/dist/{questionEvidenceLinks-DFlyPpAj.d.ts → questionEvidenceLinks-_nPRa-LY.d.ts} +10 -10
- package/dist/questionEvidenceLinks.d.ts +1 -1
- package/dist/questionEvidenceLinks.js +564 -347
- package/dist/questionEvidenceLinks.js.map +1 -1
- package/dist/{resolverTypes-CC8Ea2E2.d.ts → resolverTypes-BOXPxLET.d.ts} +8 -7
- package/dist/resolverTypes.d.ts +4 -2
- package/dist/{resolvers-Br1a6eLV.d.ts → resolvers-B1TIBmRO.d.ts} +3 -1
- package/dist/resolvers.d.ts +5 -3
- package/dist/resolvers.js +121 -77
- package/dist/resolvers.js.map +1 -1
- package/dist/scopeResolverCompat.d.ts +10 -7
- package/dist/scopeResolverCompat.js +106 -123
- package/dist/scopeResolverCompat.js.map +1 -1
- package/dist/{text-matching-DNg4M5Wd.d.ts → text-matching-DzFooju6.d.ts} +7 -7
- package/dist/text-matching.d.ts +1 -1
- package/dist/topicOntologyResolver.d.ts +22 -21
- package/dist/topicOntologyResolver.js +54 -32
- package/dist/topicOntologyResolver.js.map +1 -1
- package/dist/topicProjectOverlay.d.ts +30 -20
- package/dist/topicProjectOverlay.js +120 -76
- package/dist/topicProjectOverlay.js.map +1 -1
- package/dist/{topicScope-7zhyeGl7.d.ts → topicScope-DJVa0mLa.d.ts} +22 -7
- package/dist/topicScope.d.ts +3 -1
- package/dist/topicScope.js +104 -119
- package/dist/topicScope.js.map +1 -1
- package/dist/workflowBridge.d.ts +26 -15
- package/dist/workflowBridge.js +140 -144
- package/dist/workflowBridge.js.map +1 -1
- package/dist/workspaceIsolation.d.ts +14 -12
- package/dist/workspaceIsolation.js +108 -122
- package/dist/workspaceIsolation.js.map +1 -1
- package/package.json +4 -4
- package/dist/edges/dependsOn.js.map +0 -1
- package/dist/edges/derivedFrom.js.map +0 -1
- package/dist/edges/propagationTypes.js.map +0 -1
- package/dist/evaluators/lintCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/lintCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/sentryCheckerEvaluator.js.map +0 -1
- package/dist/evaluators/testRunnerEvaluator.js.map +0 -1
- package/dist/evaluators/tscCheckerEvaluator.d.ts +0 -11
- package/dist/evaluators/tscCheckerEvaluator.js.map +0 -1
- package/dist/{epistemicQuestions-bwHd2FWE.d.ts → epistemicQuestions-Do1fhYm5.d.ts} +4 -4
|
@@ -9,15 +9,16 @@ import { QueryCtx, MutationCtx } from './convex.js';
|
|
|
9
9
|
* @module graph-primitives/entityValidation
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
type
|
|
13
|
-
|
|
12
|
+
type EntitySchemaConfigFieldType = "string" | "number" | "boolean";
|
|
13
|
+
interface FieldSchema {
|
|
14
14
|
required: boolean;
|
|
15
|
-
|
|
15
|
+
type: EntitySchemaConfigFieldType;
|
|
16
|
+
}
|
|
16
17
|
type EntitySchema = Record<string, FieldSchema>;
|
|
17
|
-
|
|
18
|
-
valid: boolean;
|
|
18
|
+
interface ValidationResult {
|
|
19
19
|
errors: string[];
|
|
20
|
-
|
|
20
|
+
valid: boolean;
|
|
21
|
+
}
|
|
21
22
|
/**
|
|
22
23
|
* Fetch the registered metadata schema for an entity type.
|
|
23
24
|
* Returns null if no schema is registered.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import './convex.js';
|
|
2
|
-
export { g as getEntityTypeSchema, i as isRegisteredEntityType, v as validateEntityMetadata } from './entityValidation-
|
|
2
|
+
export { g as getEntityTypeSchema, i as isRegisteredEntityType, v as validateEntityMetadata } from './entityValidation-B1yNEHJx.js';
|
|
3
|
+
import '@lucern/access-control/convex';
|
|
4
|
+
import '@lucern/contracts/convex/unsafeAnyApi';
|
|
3
5
|
import 'convex/values';
|
package/dist/entityValidation.js
CHANGED
|
@@ -1,23 +1,75 @@
|
|
|
1
1
|
// src/entityValidation.ts
|
|
2
|
+
function isObjectLike(value) {
|
|
3
|
+
return value !== null && typeof value === "object";
|
|
4
|
+
}
|
|
5
|
+
function isEntitySchemaConfigField(value) {
|
|
6
|
+
if (!isObjectLike(value)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const required = value.required;
|
|
10
|
+
const type = value.type;
|
|
11
|
+
return typeof required === "boolean" && (type === "string" || type === "number" || type === "boolean");
|
|
12
|
+
}
|
|
13
|
+
function readEntitySchema(value) {
|
|
14
|
+
if (!isObjectLike(value)) {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
const schema = {};
|
|
18
|
+
for (const [fieldName, fieldValue] of Object.entries(value)) {
|
|
19
|
+
if (!isEntitySchemaConfigField(fieldValue)) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
schema[fieldName] = fieldValue;
|
|
23
|
+
}
|
|
24
|
+
return schema;
|
|
25
|
+
}
|
|
26
|
+
function readSchemaEnumConfigRow(row) {
|
|
27
|
+
if (!isObjectLike(row)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const value = row.value;
|
|
31
|
+
if (typeof value !== "string") {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
value,
|
|
36
|
+
status: typeof row.status === "string" ? row.status : void 0,
|
|
37
|
+
metadata: isObjectLike(row.metadata) ? row.metadata : void 0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function readEntitySchemaFromConfig(row) {
|
|
41
|
+
const parsed = readSchemaEnumConfigRow(row);
|
|
42
|
+
if (parsed?.status !== "active" || !parsed?.metadata) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const schema = parsed.metadata.schema;
|
|
46
|
+
if (!schema) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return readEntitySchema(schema);
|
|
50
|
+
}
|
|
2
51
|
async function getEntityTypeSchema(ctx, nodeType, tenantId) {
|
|
3
52
|
if (tenantId) {
|
|
4
|
-
const
|
|
53
|
+
const tenantEntries = await ctx.db.query("schemaEnumConfig").withIndex(
|
|
5
54
|
"by_tenant_category",
|
|
6
55
|
(q) => q.eq("tenantId", tenantId).eq("category", "entity_type")
|
|
7
56
|
).collect();
|
|
8
|
-
const tenantMatch =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
57
|
+
const tenantMatch = tenantEntries.find((entry) => {
|
|
58
|
+
const parsed = readSchemaEnumConfigRow(entry);
|
|
59
|
+
return parsed !== null && parsed.value === nodeType && parsed.status === "active";
|
|
60
|
+
});
|
|
61
|
+
const tenantSchema = readEntitySchemaFromConfig(tenantMatch);
|
|
62
|
+
if (tenantSchema !== null) {
|
|
63
|
+
return tenantSchema;
|
|
13
64
|
}
|
|
14
65
|
}
|
|
15
66
|
const platformEntry = await ctx.db.query("schemaEnumConfig").withIndex(
|
|
16
67
|
"by_category_value",
|
|
17
68
|
(q) => q.eq("category", "entity_type").eq("value", nodeType)
|
|
18
69
|
).first();
|
|
19
|
-
|
|
20
|
-
|
|
70
|
+
const platformSchema = readEntitySchemaFromConfig(platformEntry);
|
|
71
|
+
if (platformSchema !== null) {
|
|
72
|
+
return platformSchema;
|
|
21
73
|
}
|
|
22
74
|
return null;
|
|
23
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/entityValidation.ts"],"names":[],"mappings":"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","file":"entityValidation.js","sourcesContent":["/**\n * Entity Metadata Validation\n *\n * Validates entity metadata against registered schemas in schemaEnumConfig.\n * Strict on create (must pass), lenient on read (existing data tolerance).\n *\n * @module graph-primitives/entityValidation\n */\n\nimport type { MutationCtx, QueryCtx } from \"./convex\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype FieldSchema = {\n type: \"string\" | \"number\" | \"boolean\";\n required: boolean;\n};\n\ntype EntitySchema = Record<string, FieldSchema>;\n\ntype ValidationResult = {\n valid: boolean;\n errors: string[];\n};\n\n// =============================================================================\n// SCHEMA LOOKUP\n// =============================================================================\n\n/**\n * Fetch the registered metadata schema for an entity type.\n * Returns null if no schema is registered.\n */\nexport async function getEntityTypeSchema(\n ctx: QueryCtx | MutationCtx,\n nodeType: string,\n tenantId?: string\n): Promise<EntitySchema | null> {\n // Try tenant-specific first, then platform default\n if (tenantId) {\n const tenantEntry = await (ctx.db as any)\n .query(\"schemaEnumConfig\")\n .withIndex(\"by_tenant_category\", (q: any) =>\n q.eq(\"tenantId\", tenantId).eq(\"category\", \"entity_type\")\n )\n .collect();\n\n const tenantMatch = tenantEntry.find(\n (e: any) => e.value === nodeType && e.status === \"active\"\n );\n if (tenantMatch?.metadata?.schema) {\n return tenantMatch.metadata.schema as EntitySchema;\n }\n }\n\n // Fall back to platform default\n const platformEntry = await (ctx.db as any)\n .query(\"schemaEnumConfig\")\n .withIndex(\"by_category_value\", (q: any) =>\n q.eq(\"category\", \"entity_type\").eq(\"value\", nodeType)\n )\n .first();\n\n if (platformEntry?.metadata?.schema && platformEntry.status === \"active\") {\n return platformEntry.metadata.schema as EntitySchema;\n }\n\n return null;\n}\n\n// =============================================================================\n// VALIDATION\n// =============================================================================\n\n/**\n * Validate entity metadata against the registered schema.\n *\n * Policy: strict on create (unregistered types fail), lenient on read.\n *\n * @param ctx - Convex query/mutation context\n * @param nodeType - The entity nodeType (e.g., \"company\", \"person\")\n * @param metadata - The metadata object to validate\n * @param tenantId - Optional tenant ID for tenant-specific schemas\n * @returns ValidationResult with errors if invalid\n */\nexport async function validateEntityMetadata(\n ctx: QueryCtx | MutationCtx,\n nodeType: string,\n metadata: Record<string, unknown> | undefined | null,\n tenantId?: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const schema = await getEntityTypeSchema(ctx, nodeType, tenantId);\n\n if (!schema) {\n return {\n valid: false,\n errors: [\n `No registered schema for entity type \"${nodeType}\". Register it in schemaEnumConfig (category=\"entity_type\") before creating entities of this type.`,\n ],\n };\n }\n\n const meta = metadata || {};\n\n // Check required fields\n for (const [fieldName, fieldDef] of Object.entries(schema)) {\n if (fieldDef.required) {\n const value = meta[fieldName];\n if (value === undefined || value === null || value === \"\") {\n errors.push(`Required field \"${fieldName}\" is missing or empty`);\n }\n }\n }\n\n // Check field types for provided fields\n for (const [fieldName, value] of Object.entries(meta)) {\n const fieldDef = schema[fieldName];\n if (!fieldDef) {\n // Extra fields are allowed (loose metadata tolerance)\n continue;\n }\n\n if (value === undefined || value === null) {\n // null/undefined are allowed for optional fields (already caught above for required)\n continue;\n }\n\n const actualType = typeof value;\n if (actualType !== fieldDef.type) {\n errors.push(\n `Field \"${fieldName}\" expected type \"${fieldDef.type}\" but got \"${actualType}\"`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Check if a nodeType is a registered entity type (platform or tenant).\n */\nexport async function isRegisteredEntityType(\n ctx: QueryCtx | MutationCtx,\n nodeType: string,\n tenantId?: string\n): Promise<boolean> {\n const schema = await getEntityTypeSchema(ctx, nodeType, tenantId);\n return schema !== null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/entityValidation.ts"],"names":[],"mappings":"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","file":"entityValidation.js","sourcesContent":["// biome-ignore-all lint/style/useFilenamingConvention: Public ABI surface; rename requires a cross-package migration update.\n/**\n * Entity Metadata Validation\n *\n * Validates entity metadata against registered schemas in schemaEnumConfig.\n * Strict on create (must pass), lenient on read (existing data tolerance).\n *\n * @module graph-primitives/entityValidation\n */\n\nimport type { MutationCtx, QueryCtx } from \"./convex\";\n\ninterface UnknownRecord {\n [key: string]: unknown;\n}\n\n// =============================================================================\n// TYPES\n// =============================================================================\n\ntype EntitySchemaConfigFieldType = \"string\" | \"number\" | \"boolean\";\n\ninterface EntitySchemaConfigEntry {\n required: boolean;\n type: EntitySchemaConfigFieldType;\n}\n\ninterface FieldSchema {\n required: boolean;\n type: EntitySchemaConfigFieldType;\n}\n\ntype EntitySchema = Record<string, FieldSchema>;\n\ninterface SchemaEnumConfigRow {\n metadata?: UnknownRecord;\n status?: string;\n value?: string;\n}\n\nfunction isObjectLike(value: unknown): value is UnknownRecord {\n return value !== null && typeof value === \"object\";\n}\n\nfunction isEntitySchemaConfigField(\n value: unknown\n): value is EntitySchemaConfigEntry {\n if (!isObjectLike(value)) {\n return false;\n }\n const required = value.required;\n const type = value.type;\n return (\n typeof required === \"boolean\" &&\n (type === \"string\" || type === \"number\" || type === \"boolean\")\n );\n}\n\nfunction readEntitySchema(value: unknown): EntitySchema {\n if (!isObjectLike(value)) {\n return {};\n }\n const schema: EntitySchema = {};\n for (const [fieldName, fieldValue] of Object.entries(value)) {\n if (!isEntitySchemaConfigField(fieldValue)) {\n continue;\n }\n schema[fieldName] = fieldValue;\n }\n return schema;\n}\n\nfunction readSchemaEnumConfigRow(row: unknown): SchemaEnumConfigRow | null {\n if (!isObjectLike(row)) {\n return null;\n }\n\n const value = row.value;\n if (typeof value !== \"string\") {\n return null;\n }\n\n return {\n value,\n status: typeof row.status === \"string\" ? row.status : undefined,\n metadata: isObjectLike(row.metadata) ? row.metadata : undefined,\n };\n}\n\nfunction readEntitySchemaFromConfig(row: unknown): EntitySchema | null {\n const parsed = readSchemaEnumConfigRow(row);\n if (parsed?.status !== \"active\" || !parsed?.metadata) {\n return null;\n }\n\n const schema = parsed.metadata.schema;\n if (!schema) {\n return null;\n }\n\n return readEntitySchema(schema);\n}\n\ninterface ValidationResult {\n errors: string[];\n valid: boolean;\n}\n\n// =============================================================================\n// SCHEMA LOOKUP\n// =============================================================================\n\n/**\n * Fetch the registered metadata schema for an entity type.\n * Returns null if no schema is registered.\n */\nexport async function getEntityTypeSchema(\n ctx: QueryCtx | MutationCtx,\n nodeType: string,\n tenantId?: string\n): Promise<EntitySchema | null> {\n // Try tenant-specific first, then platform default\n if (tenantId) {\n const tenantEntries = await ctx.db\n .query(\"schemaEnumConfig\")\n .withIndex(\"by_tenant_category\", (q) =>\n q.eq(\"tenantId\", tenantId).eq(\"category\", \"entity_type\")\n )\n .collect();\n\n const tenantMatch = tenantEntries.find((entry) => {\n const parsed = readSchemaEnumConfigRow(entry);\n return (\n parsed !== null &&\n parsed.value === nodeType &&\n parsed.status === \"active\"\n );\n });\n const tenantSchema = readEntitySchemaFromConfig(tenantMatch);\n if (tenantSchema !== null) {\n return tenantSchema;\n }\n }\n\n // Fall back to platform default\n const platformEntry = await ctx.db\n .query(\"schemaEnumConfig\")\n .withIndex(\"by_category_value\", (q) =>\n q.eq(\"category\", \"entity_type\").eq(\"value\", nodeType)\n )\n .first();\n\n const platformSchema = readEntitySchemaFromConfig(platformEntry);\n if (platformSchema !== null) {\n return platformSchema;\n }\n\n return null;\n}\n\n// =============================================================================\n// VALIDATION\n// =============================================================================\n\n/**\n * Validate entity metadata against the registered schema.\n *\n * Policy: strict on create (unregistered types fail), lenient on read.\n *\n * @param ctx - Convex query/mutation context\n * @param nodeType - The entity nodeType (e.g., \"company\", \"person\")\n * @param metadata - The metadata object to validate\n * @param tenantId - Optional tenant ID for tenant-specific schemas\n * @returns ValidationResult with errors if invalid\n */\nexport async function validateEntityMetadata(\n ctx: QueryCtx | MutationCtx,\n nodeType: string,\n metadata: Record<string, unknown> | undefined | null,\n tenantId?: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const schema = await getEntityTypeSchema(ctx, nodeType, tenantId);\n\n if (!schema) {\n return {\n valid: false,\n errors: [\n `No registered schema for entity type \"${nodeType}\". Register it in schemaEnumConfig (category=\"entity_type\") before creating entities of this type.`,\n ],\n };\n }\n\n const meta = metadata || {};\n\n // Check required fields\n for (const [fieldName, fieldDef] of Object.entries(schema)) {\n if (fieldDef.required) {\n const value = meta[fieldName];\n if (value === undefined || value === null || value === \"\") {\n errors.push(`Required field \"${fieldName}\" is missing or empty`);\n }\n }\n }\n\n // Check field types for provided fields\n for (const [fieldName, value] of Object.entries(meta)) {\n const fieldDef = schema[fieldName];\n if (!fieldDef) {\n // Extra fields are allowed (loose metadata tolerance)\n continue;\n }\n\n if (value === undefined || value === null) {\n // null/undefined are allowed for optional fields (already caught above for required)\n continue;\n }\n\n const actualType = typeof value;\n if (actualType !== fieldDef.type) {\n errors.push(\n `Field \"${fieldName}\" expected type \"${fieldDef.type}\" but got \"${actualType}\"`\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/**\n * Check if a nodeType is a registered entity type (platform or tenant).\n */\nexport async function isRegisteredEntityType(\n ctx: QueryCtx | MutationCtx,\n nodeType: string,\n tenantId?: string\n): Promise<boolean> {\n const schema = await getEntityTypeSchema(ctx, nodeType, tenantId);\n return schema !== null;\n}\n"]}
|
|
@@ -25,25 +25,25 @@
|
|
|
25
25
|
* 8. Updates question's answerQuality field
|
|
26
26
|
* 9. Logs to epistemicAudit
|
|
27
27
|
*/
|
|
28
|
-
declare const create:
|
|
28
|
+
declare const create: unknown;
|
|
29
29
|
/**
|
|
30
30
|
* Internal mutation for creating answer nodes.
|
|
31
31
|
* Called from epistemicQuestions.updateStatus when status === "answered".
|
|
32
32
|
*/
|
|
33
|
-
declare const createInternal:
|
|
33
|
+
declare const createInternal: unknown;
|
|
34
34
|
/**
|
|
35
35
|
* Get all answers for a question, optionally including superseded.
|
|
36
36
|
*/
|
|
37
|
-
declare const getByQuestion:
|
|
37
|
+
declare const getByQuestion: unknown;
|
|
38
38
|
/**
|
|
39
39
|
* Get the single active (latest) answer for a question.
|
|
40
40
|
*/
|
|
41
|
-
declare const getLatestForQuestion:
|
|
41
|
+
declare const getLatestForQuestion: unknown;
|
|
42
42
|
/**
|
|
43
43
|
* Get full version history for answers to a question.
|
|
44
44
|
* Returns answers ordered by version number (newest first).
|
|
45
45
|
*/
|
|
46
|
-
declare const getVersionHistory:
|
|
46
|
+
declare const getVersionHistory: unknown;
|
|
47
47
|
/**
|
|
48
48
|
* Backfill answer nodes for questions that have answer text in metadata
|
|
49
49
|
* but never had an answer node created (due to the QuestionAnswerEditor bug
|
|
@@ -52,7 +52,7 @@ declare const getVersionHistory: any;
|
|
|
52
52
|
* Run once via Convex dashboard:
|
|
53
53
|
* internal.epistemicAnswers.backfillAnswerNodes({ projectId, userId })
|
|
54
54
|
*/
|
|
55
|
-
declare const backfillAnswerNodes:
|
|
55
|
+
declare const backfillAnswerNodes: unknown;
|
|
56
56
|
|
|
57
57
|
declare const epistemicAnswers_backfillAnswerNodes: typeof backfillAnswerNodes;
|
|
58
58
|
declare const epistemicAnswers_create: typeof create;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { b as backfillAnswerNodes, c as create, a as createInternal, g as getByQuestion, d as getLatestForQuestion, f as getVersionHistory } from './epistemicAnswers-
|
|
1
|
+
export { b as backfillAnswerNodes, c as create, a as createInternal, g as getByQuestion, d as getLatestForQuestion, f as getVersionHistory } from './epistemicAnswers-f47YMu9U.js';
|