@cosmicdrift/kumiko-framework 0.2.2 → 0.3.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/CHANGELOG.md +54 -0
- package/package.json +124 -38
- package/src/__tests__/full-stack.integration.ts +2 -2
- package/src/api/auth-routes.ts +5 -5
- package/src/api/jwt.ts +2 -2
- package/src/api/route-registrars.ts +1 -1
- package/src/api/routes.ts +3 -3
- package/src/api/server.ts +6 -7
- package/src/auth/__tests__/roles.test.ts +24 -0
- package/src/auth/index.ts +7 -0
- package/src/auth/roles.ts +42 -0
- package/src/compliance/__tests__/duration-spec.test.ts +72 -0
- package/src/compliance/__tests__/profiles.test.ts +308 -0
- package/src/compliance/__tests__/sub-processors.test.ts +139 -0
- package/src/compliance/duration-spec.ts +44 -0
- package/src/compliance/index.ts +31 -0
- package/src/compliance/override-schema.ts +136 -0
- package/src/compliance/profiles.ts +427 -0
- package/src/compliance/sub-processors.ts +152 -0
- package/src/db/__tests__/big-int-field.test.ts +131 -0
- package/src/db/assert-exists-in.ts +2 -2
- package/src/db/cursor.ts +3 -3
- package/src/db/event-store-executor.ts +19 -13
- package/src/db/located-timestamp.ts +1 -1
- package/src/db/money.ts +12 -2
- package/src/db/pg-error.ts +1 -1
- package/src/db/row-helpers.ts +1 -1
- package/src/db/table-builder.ts +20 -5
- package/src/db/tenant-db.ts +9 -9
- package/src/engine/__tests__/_pipeline-test-utils.ts +23 -0
- package/src/engine/__tests__/boot-validator-api-exposure.test.ts +142 -0
- package/src/engine/__tests__/boot-validator-pii-retention.test.ts +570 -0
- package/src/engine/__tests__/boot-validator-s0-integration.test.ts +160 -0
- package/src/engine/__tests__/build-target.test.ts +135 -0
- package/src/engine/__tests__/codemod-pipeline.test.ts +551 -0
- package/src/engine/__tests__/entity-handlers.test.ts +3 -3
- package/src/engine/__tests__/event-helpers.test.ts +4 -4
- package/src/engine/__tests__/pipeline-engine.test.ts +215 -0
- package/src/engine/__tests__/pipeline-handler.integration.ts +894 -0
- package/src/engine/__tests__/pipeline-observability.integration.ts +142 -0
- package/src/engine/__tests__/pipeline-performance.integration.ts +152 -0
- package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +288 -0
- package/src/engine/__tests__/raw-table.test.ts +2 -2
- package/src/engine/__tests__/steps-aggregate-append-event.test.ts +115 -0
- package/src/engine/__tests__/steps-aggregate-create.test.ts +92 -0
- package/src/engine/__tests__/steps-aggregate-update.test.ts +127 -0
- package/src/engine/__tests__/steps-call-feature.test.ts +123 -0
- package/src/engine/__tests__/steps-mail-send.test.ts +136 -0
- package/src/engine/__tests__/steps-read.test.ts +142 -0
- package/src/engine/__tests__/steps-resolver-utils.test.ts +50 -0
- package/src/engine/__tests__/steps-unsafe-projection-delete.test.ts +69 -0
- package/src/engine/__tests__/steps-unsafe-projection-upsert.test.ts +117 -0
- package/src/engine/__tests__/steps-webhook-send.test.ts +135 -0
- package/src/engine/__tests__/steps-workflow.test.ts +198 -0
- package/src/engine/__tests__/validate-projection-allowlist.test.ts +491 -0
- package/src/engine/__tests__/visual-tree-patterns.test.ts +251 -0
- package/src/engine/boot-validator/api-ext.ts +77 -0
- package/src/engine/boot-validator/config-deps.ts +163 -0
- package/src/engine/boot-validator/entity-handler.ts +466 -0
- package/src/engine/boot-validator/index.ts +159 -0
- package/src/engine/boot-validator/ownership.ts +198 -0
- package/src/engine/boot-validator/pii-retention.ts +155 -0
- package/src/engine/boot-validator/screens-nav.ts +624 -0
- package/src/engine/boot-validator.ts +1 -1528
- package/src/engine/build-app-schema.ts +1 -1
- package/src/engine/build-target.ts +99 -0
- package/src/engine/codemod/index.ts +15 -0
- package/src/engine/codemod/pipeline-codemod.ts +641 -0
- package/src/engine/config-helpers.ts +9 -19
- package/src/engine/constants.ts +1 -1
- package/src/engine/define-feature.ts +127 -9
- package/src/engine/define-handler.ts +89 -3
- package/src/engine/define-roles.ts +2 -2
- package/src/engine/define-step.ts +28 -0
- package/src/engine/define-workflow.ts +110 -0
- package/src/engine/entity-handlers.ts +10 -9
- package/src/engine/event-helpers.ts +4 -4
- package/src/engine/extension-names.ts +105 -0
- package/src/engine/extensions/user-data.ts +106 -0
- package/src/engine/factories.ts +26 -16
- package/src/engine/feature-ast/__tests__/visual-tree-parse.test.ts +184 -0
- package/src/engine/feature-ast/extractors/index.ts +74 -0
- package/src/engine/feature-ast/extractors/round1.ts +110 -0
- package/src/engine/feature-ast/extractors/round2.ts +253 -0
- package/src/engine/feature-ast/extractors/round3.ts +471 -0
- package/src/engine/feature-ast/extractors/round4.ts +1365 -0
- package/src/engine/feature-ast/extractors/round5.ts +72 -0
- package/src/engine/feature-ast/extractors/round6.ts +66 -0
- package/src/engine/feature-ast/extractors/shared.ts +177 -0
- package/src/engine/feature-ast/parse.ts +13 -0
- package/src/engine/feature-ast/patch.ts +9 -1
- package/src/engine/feature-ast/patcher.ts +10 -3
- package/src/engine/feature-ast/patterns.ts +71 -1
- package/src/engine/feature-ast/render.ts +31 -1
- package/src/engine/index.ts +66 -2
- package/src/engine/pattern-library/__tests__/library.test.ts +11 -0
- package/src/engine/pattern-library/library.ts +78 -2
- package/src/engine/pipeline.ts +88 -0
- package/src/engine/projection-helpers.ts +1 -1
- package/src/engine/read-claim.ts +1 -1
- package/src/engine/registry.ts +30 -2
- package/src/engine/resolve-config-or-param.ts +4 -0
- package/src/engine/run-pipeline.ts +162 -0
- package/src/engine/schema-builder.ts +10 -4
- package/src/engine/state-machine.ts +1 -1
- package/src/engine/steps/_drizzle-boundary.ts +19 -0
- package/src/engine/steps/_duration-utils.ts +33 -0
- package/src/engine/steps/_no-return-guard.ts +21 -0
- package/src/engine/steps/_resolver-utils.ts +42 -0
- package/src/engine/steps/_step-dispatch-constants.ts +38 -0
- package/src/engine/steps/aggregate-append-event.ts +56 -0
- package/src/engine/steps/aggregate-create.ts +56 -0
- package/src/engine/steps/aggregate-update.ts +68 -0
- package/src/engine/steps/branch.ts +84 -0
- package/src/engine/steps/call-feature.ts +49 -0
- package/src/engine/steps/compute.ts +41 -0
- package/src/engine/steps/for-each.ts +111 -0
- package/src/engine/steps/mail-send.ts +44 -0
- package/src/engine/steps/read-find-many.ts +51 -0
- package/src/engine/steps/read-find-one.ts +58 -0
- package/src/engine/steps/retry.ts +87 -0
- package/src/engine/steps/return.ts +34 -0
- package/src/engine/steps/unsafe-projection-delete.ts +46 -0
- package/src/engine/steps/unsafe-projection-upsert.ts +69 -0
- package/src/engine/steps/wait-for-event.ts +71 -0
- package/src/engine/steps/wait.ts +69 -0
- package/src/engine/steps/webhook-send.ts +71 -0
- package/src/engine/system-user.ts +1 -1
- package/src/engine/types/feature.ts +143 -1
- package/src/engine/types/fields.ts +134 -10
- package/src/engine/types/handlers.ts +18 -10
- package/src/engine/types/identifiers.ts +1 -0
- package/src/engine/types/index.ts +15 -1
- package/src/engine/types/step.ts +334 -0
- package/src/engine/types/target-ref.ts +21 -0
- package/src/engine/types/tree-node.ts +130 -0
- package/src/engine/types/workspace.ts +7 -0
- package/src/engine/validate-projection-allowlist.ts +161 -0
- package/src/event-store/snapshot.ts +1 -1
- package/src/event-store/upcaster-dead-letter.ts +1 -1
- package/src/event-store/upcaster.ts +1 -1
- package/src/files/__tests__/read-stream.test.ts +105 -0
- package/src/files/__tests__/write-stream.test.ts +233 -0
- package/src/files/__tests__/zip-stream.test.ts +357 -0
- package/src/files/file-routes.ts +1 -1
- package/src/files/in-memory-provider.ts +38 -0
- package/src/files/index.ts +3 -0
- package/src/files/local-provider.ts +58 -1
- package/src/files/types.ts +36 -8
- package/src/files/zip-stream.ts +251 -0
- package/src/jobs/job-runner.ts +10 -10
- package/src/lifecycle/lifecycle.ts +0 -3
- package/src/logging/index.ts +1 -0
- package/src/logging/pino-logger.ts +11 -7
- package/src/logging/utils.ts +24 -0
- package/src/observability/prometheus-meter.ts +7 -5
- package/src/pipeline/__tests__/archive-stream.integration.ts +1 -1
- package/src/pipeline/__tests__/causation-chain.integration.ts +1 -1
- package/src/pipeline/__tests__/domain-events-projections.integration.ts +3 -3
- package/src/pipeline/__tests__/event-define-event-strict.integration.ts +4 -4
- package/src/pipeline/__tests__/load-aggregate-query.integration.ts +1 -1
- package/src/pipeline/__tests__/msp-multi-hop.integration.ts +3 -3
- package/src/pipeline/__tests__/msp-rebuild.integration.ts +3 -3
- package/src/pipeline/__tests__/multi-stream-projection.integration.ts +2 -2
- package/src/pipeline/__tests__/query-projection.integration.ts +5 -5
- package/src/pipeline/append-event-core.ts +22 -6
- package/src/pipeline/dispatcher-utils.ts +188 -0
- package/src/pipeline/dispatcher.ts +63 -283
- package/src/pipeline/distributed-lock.ts +1 -1
- package/src/pipeline/entity-cache.ts +2 -2
- package/src/pipeline/event-consumer-state.ts +0 -13
- package/src/pipeline/event-dispatcher.ts +4 -4
- package/src/pipeline/index.ts +0 -2
- package/src/pipeline/lifecycle-pipeline.ts +6 -12
- package/src/pipeline/msp-rebuild.ts +5 -5
- package/src/pipeline/multi-stream-apply-context.ts +6 -7
- package/src/pipeline/projection-rebuild.ts +2 -2
- package/src/pipeline/projection-state.ts +0 -12
- package/src/rate-limit/__tests__/resolver.integration.ts +8 -4
- package/src/rate-limit/resolver.ts +1 -1
- package/src/search/in-memory-adapter.ts +1 -1
- package/src/search/meilisearch-adapter.ts +3 -3
- package/src/search/types.ts +1 -1
- package/src/secrets/leak-guard.ts +2 -2
- package/src/stack/request-helper.ts +9 -5
- package/src/stack/test-stack.ts +1 -1
- package/src/testing/handler-context.ts +4 -4
- package/src/testing/http-cookies.ts +1 -1
- package/src/time/tz-context.ts +1 -2
- package/src/ui-types/index.ts +4 -0
- package/src/engine/feature-ast/extractors.ts +0 -2562
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { CallExpression, SourceFile } from "ts-morph";
|
|
2
|
+
import type {
|
|
3
|
+
OptionalRequiresPattern,
|
|
4
|
+
ReadsConfigPattern,
|
|
5
|
+
RequiresPattern,
|
|
6
|
+
SystemScopePattern,
|
|
7
|
+
ToggleablePattern,
|
|
8
|
+
} from "../patterns";
|
|
9
|
+
import { sourceLocationFromNode } from "../source-location";
|
|
10
|
+
import {
|
|
11
|
+
type ExtractOutput,
|
|
12
|
+
fail,
|
|
13
|
+
ok,
|
|
14
|
+
readBooleanProperty,
|
|
15
|
+
readVarargsOrArrayProp,
|
|
16
|
+
} from "./shared";
|
|
17
|
+
|
|
18
|
+
export function extractRequires(
|
|
19
|
+
call: CallExpression,
|
|
20
|
+
sourceFile: SourceFile,
|
|
21
|
+
): ExtractOutput<RequiresPattern> {
|
|
22
|
+
const names = readVarargsOrArrayProp(call, "features");
|
|
23
|
+
if (!names) {
|
|
24
|
+
return fail(
|
|
25
|
+
"requires",
|
|
26
|
+
sourceLocationFromNode(call, sourceFile),
|
|
27
|
+
"expected positional string literals or { features: string[] }",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return ok({
|
|
31
|
+
kind: "requires",
|
|
32
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
33
|
+
featureNames: names,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function extractOptionalRequires(
|
|
38
|
+
call: CallExpression,
|
|
39
|
+
sourceFile: SourceFile,
|
|
40
|
+
): ExtractOutput<OptionalRequiresPattern> {
|
|
41
|
+
const names = readVarargsOrArrayProp(call, "features");
|
|
42
|
+
if (!names) {
|
|
43
|
+
return fail(
|
|
44
|
+
"optionalRequires",
|
|
45
|
+
sourceLocationFromNode(call, sourceFile),
|
|
46
|
+
"expected positional string literals or { features: string[] }",
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return ok({
|
|
50
|
+
kind: "optionalRequires",
|
|
51
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
52
|
+
featureNames: names,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function extractReadsConfig(
|
|
57
|
+
call: CallExpression,
|
|
58
|
+
sourceFile: SourceFile,
|
|
59
|
+
): ExtractOutput<ReadsConfigPattern> {
|
|
60
|
+
const keys = readVarargsOrArrayProp(call, "keys");
|
|
61
|
+
if (!keys) {
|
|
62
|
+
return fail(
|
|
63
|
+
"readsConfig",
|
|
64
|
+
sourceLocationFromNode(call, sourceFile),
|
|
65
|
+
"expected positional string literals or { keys: string[] }",
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return ok({
|
|
69
|
+
kind: "readsConfig",
|
|
70
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
71
|
+
qualifiedKeys: keys,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function extractSystemScope(
|
|
76
|
+
call: CallExpression,
|
|
77
|
+
sourceFile: SourceFile,
|
|
78
|
+
): ExtractOutput<SystemScopePattern> {
|
|
79
|
+
return ok({
|
|
80
|
+
kind: "systemScope",
|
|
81
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function extractToggleable(
|
|
86
|
+
call: CallExpression,
|
|
87
|
+
sourceFile: SourceFile,
|
|
88
|
+
): ExtractOutput<ToggleablePattern> {
|
|
89
|
+
const arg = call.getArguments()[0];
|
|
90
|
+
if (!arg) {
|
|
91
|
+
return fail(
|
|
92
|
+
"toggleable",
|
|
93
|
+
sourceLocationFromNode(call, sourceFile),
|
|
94
|
+
"expected an object argument with a `default` boolean",
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const defaultValue = readBooleanProperty(arg, "default");
|
|
98
|
+
if (defaultValue === undefined) {
|
|
99
|
+
return fail(
|
|
100
|
+
"toggleable",
|
|
101
|
+
sourceLocationFromNode(call, sourceFile),
|
|
102
|
+
"argument must be `{ default: true | false }`",
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return ok({
|
|
106
|
+
kind: "toggleable",
|
|
107
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
108
|
+
default: defaultValue,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import type { CallExpression, SourceFile } from "ts-morph";
|
|
2
|
+
import { SyntaxKind } from "ts-morph";
|
|
3
|
+
import type { EntityDefinition } from "../../types/fields";
|
|
4
|
+
import type { NavDefinition } from "../../types/nav";
|
|
5
|
+
import type { RelationDefinition } from "../../types/relations";
|
|
6
|
+
import type { WorkspaceDefinition } from "../../types/workspace";
|
|
7
|
+
import type { EntityPattern, NavPattern, RelationPattern, WorkspacePattern } from "../patterns";
|
|
8
|
+
import { sourceLocationFromNode } from "../source-location";
|
|
9
|
+
import {
|
|
10
|
+
type ExtractOutput,
|
|
11
|
+
fail,
|
|
12
|
+
isPlainObject,
|
|
13
|
+
ok,
|
|
14
|
+
readDataLiteralNode,
|
|
15
|
+
readNameOrRef,
|
|
16
|
+
} from "./shared";
|
|
17
|
+
|
|
18
|
+
export function extractEntity(
|
|
19
|
+
call: CallExpression,
|
|
20
|
+
sourceFile: SourceFile,
|
|
21
|
+
): ExtractOutput<EntityPattern> {
|
|
22
|
+
const args = call.getArguments();
|
|
23
|
+
const first = args[0];
|
|
24
|
+
if (!first) {
|
|
25
|
+
return fail(
|
|
26
|
+
"entity",
|
|
27
|
+
sourceLocationFromNode(call, sourceFile),
|
|
28
|
+
"expected at least one argument",
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const obj = first.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
33
|
+
if (obj && args.length === 1) {
|
|
34
|
+
const nameInit = obj
|
|
35
|
+
.getProperty("name")
|
|
36
|
+
?.asKind(SyntaxKind.PropertyAssignment)
|
|
37
|
+
?.getInitializer()
|
|
38
|
+
?.asKind(SyntaxKind.StringLiteral);
|
|
39
|
+
if (!nameInit) {
|
|
40
|
+
return fail(
|
|
41
|
+
"entity",
|
|
42
|
+
sourceLocationFromNode(call, sourceFile),
|
|
43
|
+
"object form requires a string-literal `name` property",
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const definition = readDataLiteralNode(obj);
|
|
47
|
+
if (!isPlainObject(definition)) {
|
|
48
|
+
return fail(
|
|
49
|
+
"entity",
|
|
50
|
+
sourceLocationFromNode(call, sourceFile),
|
|
51
|
+
"definition could not be read as a plain object (contains functions or identifiers)",
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const { name: _name, ...defWithoutName } = definition;
|
|
55
|
+
return ok({
|
|
56
|
+
kind: "entity",
|
|
57
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
58
|
+
entityName: nameInit.getLiteralValue(),
|
|
59
|
+
definition: defWithoutName as EntityDefinition,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const nameArg = first.asKind(SyntaxKind.StringLiteral);
|
|
64
|
+
if (!nameArg) {
|
|
65
|
+
return fail(
|
|
66
|
+
"entity",
|
|
67
|
+
sourceLocationFromNode(call, sourceFile),
|
|
68
|
+
"first argument must be a string literal name (or use the object form)",
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const defArg = args[1];
|
|
72
|
+
if (!defArg) {
|
|
73
|
+
return fail(
|
|
74
|
+
"entity",
|
|
75
|
+
sourceLocationFromNode(call, sourceFile),
|
|
76
|
+
"expected a definition object as second argument",
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
const definition = readDataLiteralNode(defArg);
|
|
80
|
+
if (!isPlainObject(definition)) {
|
|
81
|
+
return fail(
|
|
82
|
+
"entity",
|
|
83
|
+
sourceLocationFromNode(call, sourceFile),
|
|
84
|
+
"definition could not be read as a plain object (contains functions or identifiers)",
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return ok({
|
|
88
|
+
kind: "entity",
|
|
89
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
90
|
+
entityName: nameArg.getLiteralValue(),
|
|
91
|
+
definition: definition as EntityDefinition,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function extractRelation(
|
|
96
|
+
call: CallExpression,
|
|
97
|
+
sourceFile: SourceFile,
|
|
98
|
+
): ExtractOutput<RelationPattern> {
|
|
99
|
+
const args = call.getArguments();
|
|
100
|
+
const first = args[0];
|
|
101
|
+
if (!first) {
|
|
102
|
+
return fail(
|
|
103
|
+
"relation",
|
|
104
|
+
sourceLocationFromNode(call, sourceFile),
|
|
105
|
+
"expected at least one argument",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const obj = first.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
110
|
+
if (obj && args.length === 1) {
|
|
111
|
+
const entityInit = obj
|
|
112
|
+
.getProperty("entity")
|
|
113
|
+
?.asKind(SyntaxKind.PropertyAssignment)
|
|
114
|
+
?.getInitializer();
|
|
115
|
+
if (!entityInit) {
|
|
116
|
+
return fail(
|
|
117
|
+
"relation",
|
|
118
|
+
sourceLocationFromNode(call, sourceFile),
|
|
119
|
+
"object form requires an `entity` property",
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const entityName = readNameOrRef(entityInit);
|
|
123
|
+
if (!entityName) {
|
|
124
|
+
return fail(
|
|
125
|
+
"relation",
|
|
126
|
+
sourceLocationFromNode(call, sourceFile),
|
|
127
|
+
'`entity` must be a string literal or `{ name: "..." }` ref',
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
const nameInit = obj
|
|
131
|
+
.getProperty("name")
|
|
132
|
+
?.asKind(SyntaxKind.PropertyAssignment)
|
|
133
|
+
?.getInitializer()
|
|
134
|
+
?.asKind(SyntaxKind.StringLiteral);
|
|
135
|
+
if (!nameInit) {
|
|
136
|
+
return fail(
|
|
137
|
+
"relation",
|
|
138
|
+
sourceLocationFromNode(call, sourceFile),
|
|
139
|
+
"object form requires a string-literal `name` property",
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
const definition = readDataLiteralNode(obj);
|
|
143
|
+
if (!isPlainObject(definition)) {
|
|
144
|
+
return fail(
|
|
145
|
+
"relation",
|
|
146
|
+
sourceLocationFromNode(call, sourceFile),
|
|
147
|
+
"definition could not be read as a plain object",
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
const { entity: _e, name: _n, ...defWithoutCarriers } = definition;
|
|
151
|
+
return ok({
|
|
152
|
+
kind: "relation",
|
|
153
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
154
|
+
entityName,
|
|
155
|
+
relationName: nameInit.getLiteralValue(),
|
|
156
|
+
definition: defWithoutCarriers as RelationDefinition,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const entityName = readNameOrRef(first);
|
|
161
|
+
if (!entityName) {
|
|
162
|
+
return fail(
|
|
163
|
+
"relation",
|
|
164
|
+
sourceLocationFromNode(call, sourceFile),
|
|
165
|
+
'first argument must be a string literal or an inline { name: "..." } object (or use the object form)',
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const nameArg = args[1]?.asKind(SyntaxKind.StringLiteral);
|
|
169
|
+
if (!nameArg) {
|
|
170
|
+
return fail(
|
|
171
|
+
"relation",
|
|
172
|
+
sourceLocationFromNode(call, sourceFile),
|
|
173
|
+
"second argument must be a string literal relation name",
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
const defArg = args[2];
|
|
177
|
+
if (!defArg) {
|
|
178
|
+
return fail(
|
|
179
|
+
"relation",
|
|
180
|
+
sourceLocationFromNode(call, sourceFile),
|
|
181
|
+
"expected a definition object as third argument",
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
const definition = readDataLiteralNode(defArg);
|
|
185
|
+
if (!isPlainObject(definition)) {
|
|
186
|
+
return fail(
|
|
187
|
+
"relation",
|
|
188
|
+
sourceLocationFromNode(call, sourceFile),
|
|
189
|
+
"definition could not be read as a plain object",
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
return ok({
|
|
193
|
+
kind: "relation",
|
|
194
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
195
|
+
entityName,
|
|
196
|
+
relationName: nameArg.getLiteralValue(),
|
|
197
|
+
definition: definition as RelationDefinition,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function extractNav(
|
|
202
|
+
call: CallExpression,
|
|
203
|
+
sourceFile: SourceFile,
|
|
204
|
+
): ExtractOutput<NavPattern> {
|
|
205
|
+
const arg = call.getArguments()[0];
|
|
206
|
+
if (!arg) {
|
|
207
|
+
return fail(
|
|
208
|
+
"nav",
|
|
209
|
+
sourceLocationFromNode(call, sourceFile),
|
|
210
|
+
"expected a NavDefinition object as first argument",
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
const definition = readDataLiteralNode(arg);
|
|
214
|
+
if (!isPlainObject(definition)) {
|
|
215
|
+
return fail(
|
|
216
|
+
"nav",
|
|
217
|
+
sourceLocationFromNode(call, sourceFile),
|
|
218
|
+
"definition could not be read as a plain object",
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return ok({
|
|
222
|
+
kind: "nav",
|
|
223
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
224
|
+
definition: definition as NavDefinition,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function extractWorkspace(
|
|
229
|
+
call: CallExpression,
|
|
230
|
+
sourceFile: SourceFile,
|
|
231
|
+
): ExtractOutput<WorkspacePattern> {
|
|
232
|
+
const arg = call.getArguments()[0];
|
|
233
|
+
if (!arg) {
|
|
234
|
+
return fail(
|
|
235
|
+
"workspace",
|
|
236
|
+
sourceLocationFromNode(call, sourceFile),
|
|
237
|
+
"expected a WorkspaceDefinition object as first argument",
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
const definition = readDataLiteralNode(arg);
|
|
241
|
+
if (!isPlainObject(definition)) {
|
|
242
|
+
return fail(
|
|
243
|
+
"workspace",
|
|
244
|
+
sourceLocationFromNode(call, sourceFile),
|
|
245
|
+
"definition could not be read as a plain object",
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
return ok({
|
|
249
|
+
kind: "workspace",
|
|
250
|
+
source: sourceLocationFromNode(call, sourceFile),
|
|
251
|
+
definition: definition as WorkspaceDefinition,
|
|
252
|
+
});
|
|
253
|
+
}
|