@astrale-os/kernel-dsl 0.2.0 → 1.0.0-beta.10
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/v1/builder/callable/authoring.d.ts +10 -4
- package/dist/v1/builder/callable/authoring.js +2 -0
- package/dist/v1/builder/class/authoring.d.ts +36 -1
- package/dist/v1/builder/class/authoring.js +25 -5
- package/dist/v1/builder/index.d.ts +1 -1
- package/dist/v1/builder/lowering/callable.js +1 -0
- package/dist/v1/builder/lowering/class.js +18 -1
- package/dist/v1/builder/lowering/property-keys.d.ts +27 -0
- package/dist/v1/builder/lowering/property-keys.js +108 -0
- package/dist/v1/builder/lowering/schema/compile.js +8 -3
- package/dist/v1/builder/lowering/schema/context.d.ts +2 -0
- package/dist/v1/builder/lowering/schema/context.js +12 -0
- package/dist/v1/builder/lowering/schema/lifetime.d.ts +11 -0
- package/dist/v1/builder/lowering/schema/lifetime.js +55 -0
- package/dist/v1/builder/schema/diagnostic.d.ts +1 -1
- package/dist/v1/builder/schema/projection/callable.d.ts +7 -5
- package/dist/v1/builder/schema/projection/model.d.ts +4 -2
- package/dist/v1/builder/schema/projection/resolved-class.d.ts +2 -1
- package/dist/v1/compiled/admission/semantics/cardinality.d.ts +1 -1
- package/dist/v1/compiled/admission/semantics/cardinality.js +16 -1
- package/dist/v1/compiled/admission/semantics/class.js +31 -1
- package/dist/v1/compiled/admission/semantics/core.js +16 -0
- package/dist/v1/compiled/admission/wire/callable.js +11 -1
- package/dist/v1/compiled/admission/wire/class.js +50 -3
- package/dist/v1/compiled/compiler/compile.js +2 -0
- package/dist/v1/domain/create.js +1 -0
- package/dist/v1/domain/projection/classes.js +3 -0
- package/dist/v1/index.d.ts +2 -1
- package/dist/v1/language/callable/admission.d.ts +15 -0
- package/dist/v1/language/callable/admission.js +43 -0
- package/dist/v1/language/callable/model/callable.d.ts +10 -0
- package/dist/v1/language/callable/resolved.d.ts +5 -1
- package/dist/v1/language/class/inheritance.d.ts +18 -5
- package/dist/v1/language/class/inheritance.js +14 -1
- package/dist/v1/language/class/lifetime.d.ts +50 -11
- package/dist/v1/language/class/lifetime.js +89 -20
- package/dist/v1/language/class/model/class.d.ts +25 -1
- package/dist/v1/language/class/model/edge.d.ts +30 -1
- package/dist/v1/language/class/unique.d.ts +143 -0
- package/dist/v1/language/class/unique.js +264 -0
- package/dist/v1/language/index.d.ts +6 -2
- package/dist/v1/language/index.js +4 -1
- package/dist/v1/language/value/evaluate/validate.js +4 -0
- package/dist/v1/language/value/evaluate/validity.optimization.d.ts +14 -0
- package/dist/v1/language/value/evaluate/validity.optimization.js +342 -0
- package/dist/v1/language/value/profile/canonicalize.js +6 -5
- package/dist/v1/schema/compatibility/api.d.ts +1 -0
- package/dist/v1/schema/compatibility/api.js +1 -0
- package/dist/v1/schema/compatibility/comparators/classes.d.ts +9 -4
- package/dist/v1/schema/compatibility/comparators/classes.js +25 -4
- package/dist/v1/schema/compatibility/comparators/index.d.ts +1 -1
- package/dist/v1/schema/compatibility/extension.d.ts +11 -0
- package/dist/v1/schema/compatibility/extension.js +22 -0
- package/dist/v1/schema/compatibility/fields.d.ts +20 -4
- package/dist/v1/schema/compatibility/fields.js +13 -3
- package/dist/v1/schema/compatibility/model.d.ts +11 -3
- package/dist/v1/schema/compatibility/scope.d.ts +2 -0
- package/dist/v1/schema/compatibility/scope.js +4 -1
- package/dist/v1/schema/compatibility/structure/index.js +6 -4
- package/dist/v1/schema/compatibility/structure/requirements.js +32 -1
- package/dist/v1/schema/compatibility/versioning/surface.d.ts +1 -1
- package/dist/v1/schema/compatibility/versioning/surface.js +30 -2
- package/dist/v1/schema/diagnostic.d.ts +1 -1
- package/dist/v1/schema/normalization/domain.js +18 -0
- package/dist/v1/schema/validation/callable.d.ts +1 -1
- package/dist/v1/schema/validation/callable.js +17 -2
- package/dist/v1/schema/validation/class.js +80 -2
- package/dist/v1/schema/validation/core.js +50 -0
- package/dist/v1/schema/validation/domain.structure.js +45 -10
- package/dist/value/canonical.d.ts +5 -0
- package/dist/value/canonical.js +12 -0
- package/dist/value/json.d.ts +1 -1
- package/dist/value/json.js +1 -1
- package/package.json +1 -1
- package/dist/v1/builder/lowering/core-properties.d.ts +0 -10
- package/dist/v1/builder/lowering/core-properties.js +0 -76
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DiagnosticCode as LanguageDiagnosticCode } from '../../language/validation/diagnostic.js';
|
|
2
|
-
export type BuilderDiagnosticCode = LanguageDiagnosticCode | 'BUILDER_ABSTRACT_POLICY' | 'BUILDER_AMBIGUOUS_OWNERSHIP' | 'BUILDER_AUTO_EVENT_INVALID' | 'BUILDER_AUTO_IMMUTABLE' | 'BUILDER_AUTO_NESTED' | 'BUILDER_AUTO_SET_INVALID' | 'BUILDER_CALLABLE_AUTH' | 'BUILDER_CALLABLE_PLACEMENT' | 'BUILDER_CALLABLE_POLICY_AUTH' | 'BUILDER_CORE_CLASS' | 'BUILDER_CORE_EDGE' | 'BUILDER_CORE_NODE' | 'BUILDER_CORE_PROPERTY' | 'BUILDER_CORE_REF' | 'BUILDER_DEFINITION' | 'BUILDER_DEPENDENCY_CONFLICT' | 'BUILDER_DEPENDENCY_ALIAS' | 'BUILDER_DEPENDENCY_DIRECT' | 'BUILDER_DUPLICATE_MEMBER' | 'BUILDER_FOREIGN_POLICY' | 'BUILDER_FULL_MATCH_INVALID' | 'BUILDER_FUNCTION' | 'BUILDER_METHOD' | 'BUILDER_PATH_DUPLICATE' | 'BUILDER_PATH_EMPTY' | 'BUILDER_POLICY' | 'BUILDER_POLICY_COMPOSITION' | 'BUILDER_POLICY_CYCLE' | 'BUILDER_POLICY_EMPTY_COMPOSITION' | 'BUILDER_POLICY_EMPTY_EXISTS' | 'BUILDER_POLICY_INPUT' | 'BUILDER_POLICY_REF' | 'BUILDER_POLICY_SELF' | 'BUILDER_PROPERTY_IMMUTABLE_INVALID' | 'BUILDER_REFERENCE_CYCLE' | 'BUILDER_REFERENCE_KIND' | 'BUILDER_REFERENCE_MISSING' | 'BUILDER_UNKNOWN_FIELD' | 'BUILDER_UNOWNED_REFERENCE' | 'BUILDER_VIEW' | 'ZOD_SCHEMA_NOT_LOSSLESS';
|
|
2
|
+
export type BuilderDiagnosticCode = LanguageDiagnosticCode | 'BUILDER_ABSTRACT_POLICY' | 'BUILDER_AMBIGUOUS_OWNERSHIP' | 'BUILDER_AUTO_EVENT_INVALID' | 'BUILDER_AUTO_IMMUTABLE' | 'BUILDER_AUTO_NESTED' | 'BUILDER_AUTO_SET_INVALID' | 'BUILDER_CALLABLE_AUTH' | 'BUILDER_CALLABLE_PLACEMENT' | 'BUILDER_CALLABLE_POLICY_AUTH' | 'BUILDER_CLASS_INHERITANCE' | 'BUILDER_CORE_CLASS' | 'BUILDER_CORE_EDGE' | 'BUILDER_CORE_NODE' | 'BUILDER_CORE_PROPERTY' | 'BUILDER_CORE_REF' | 'BUILDER_DEFINITION' | 'BUILDER_DEPENDENCY_CONFLICT' | 'BUILDER_DEPENDENCY_ALIAS' | 'BUILDER_DEPENDENCY_DIRECT' | 'BUILDER_DUPLICATE_MEMBER' | 'BUILDER_EDGE_LIFETIME' | 'BUILDER_FOREIGN_POLICY' | 'BUILDER_FULL_MATCH_INVALID' | 'BUILDER_FUNCTION' | 'BUILDER_METHOD' | 'BUILDER_PATH_DUPLICATE' | 'BUILDER_PATH_EMPTY' | 'BUILDER_POLICY' | 'BUILDER_POLICY_COMPOSITION' | 'BUILDER_POLICY_CYCLE' | 'BUILDER_POLICY_EMPTY_COMPOSITION' | 'BUILDER_POLICY_EMPTY_EXISTS' | 'BUILDER_POLICY_INPUT' | 'BUILDER_POLICY_REF' | 'BUILDER_POLICY_SELF' | 'BUILDER_PROPERTY_IMMUTABLE_INVALID' | 'BUILDER_REFERENCE_CYCLE' | 'BUILDER_REFERENCE_KIND' | 'BUILDER_REFERENCE_MISSING' | 'BUILDER_UNIQUE_PROPERTY' | 'BUILDER_UNKNOWN_FIELD' | 'BUILDER_UNOWNED_REFERENCE' | 'BUILDER_VIEW' | 'ZOD_SCHEMA_NOT_LOSSLESS';
|
|
3
3
|
export interface BuilderDiagnostic<out Code extends BuilderDiagnosticCode = BuilderDiagnosticCode> {
|
|
4
4
|
readonly code: Code;
|
|
5
5
|
readonly pointer: string;
|
|
@@ -18,6 +18,7 @@ type CallableConfig<Value> = Value extends Method<infer Config> ? Config extends
|
|
|
18
18
|
type CallableInputValue<Value extends Method | Function> = CallableConfig<Value>['input'];
|
|
19
19
|
type CallableOutputValue<Value extends Method | Function> = CallableConfig<Value>['output'];
|
|
20
20
|
type CallableExecutionOf<Value extends Method | Function> = CallableConfig<Value>['execution'];
|
|
21
|
+
type CallableAdmissionOf<Value extends Method | Function> = CallableConfig<Value>['admission'];
|
|
21
22
|
type CallableStaticOf<Value extends Method> = CallableConfig<Value> extends {
|
|
22
23
|
readonly static: true;
|
|
23
24
|
} ? true : false;
|
|
@@ -25,11 +26,11 @@ type CallableAbstractOf<Value extends Method> = CallableConfig<Value> extends {
|
|
|
25
26
|
readonly abstract: infer Abstract extends boolean;
|
|
26
27
|
} ? Abstract : false;
|
|
27
28
|
type CallableAuthOf<Value extends Method | Function> = CallableConfig<Value>['auth'];
|
|
28
|
-
type MethodProjectionOfEntry<Origin extends string, OwnerName extends string, Entry> = Entry extends language.ResolvedMethod ? MethodProjectionOfResolved<Entry> : Entry extends AuthoredMethodEntry<infer Owner, infer Name, infer Value> ? MethodProjection<CallableInputValue<Value>, CallableOutputValue<Value>, CallableStaticOf<Value>, CallableAbstractOf<Value>, CallableAuthOf<Value>, Name, language.MethodKey<Origin, OwnerName, Name>, MethodExecutableOf<AbstractOf<ClassInputOf<Owner>>, CallableAbstractOf<Value>>, CallableExecutionOf<Value>> : never;
|
|
29
|
+
type MethodProjectionOfEntry<Origin extends string, OwnerName extends string, Entry> = Entry extends language.ResolvedMethod ? MethodProjectionOfResolved<Entry> : Entry extends AuthoredMethodEntry<infer Owner, infer Name, infer Value> ? MethodProjection<CallableInputValue<Value>, CallableOutputValue<Value>, CallableStaticOf<Value>, CallableAbstractOf<Value>, CallableAuthOf<Value>, Name, language.MethodKey<Origin, OwnerName, Name>, MethodExecutableOf<AbstractOf<ClassInputOf<Owner>>, CallableAbstractOf<Value>>, CallableExecutionOf<Value>, CallableAdmissionOf<Value>> : never;
|
|
29
30
|
type MethodProjectionOfEntries<Origin extends string, OwnerName extends string, Entries> = Entries extends unknown ? MethodProjectionOfEntry<Origin, OwnerName, Entries> : never;
|
|
30
31
|
type MethodProjectionOfResolved<Value> = Value extends language.ResolvedMethod<infer Input, infer Output, infer Static, infer Abstract, infer Auth, infer _Policy, infer Key> & {
|
|
31
32
|
readonly name: infer Name extends string;
|
|
32
|
-
} ? MethodProjection<Input, Output, Static, Abstract, Auth, Name, Key, Value['executable'], Value['execution']> : never;
|
|
33
|
+
} ? MethodProjection<Input, Output, Static, Abstract, Auth, Name, Key, Value['executable'], Value['execution'], Value['admission']> : never;
|
|
33
34
|
/** Capture each Method through its qualified lookup key. */
|
|
34
35
|
export type MethodsOfCollection<Value> = Value extends {
|
|
35
36
|
readonly byKey: infer ByKey extends Readonly<Record<language.MethodKey, language.ResolvedMethod>>;
|
|
@@ -41,11 +42,12 @@ export type OwnStaticMethodProjectionsOf<Origin extends string, Name extends str
|
|
|
41
42
|
/** Bind an authored Function to its exact Domain coordinates. */
|
|
42
43
|
export type FunctionProjectionOfAuthoring<Origin extends string, Name extends string, Value> = Value extends Function ? FunctionProjection<CallableInputValue<Value>, CallableOutputValue<Value>, CallableAuthOf<Value>, language.FunctionRef<Name> & {
|
|
43
44
|
readonly origin: Origin;
|
|
44
|
-
}, language.DefinitionKey<Origin, 'function', Name>, CallableExecutionOf<Value>> : never;
|
|
45
|
-
/** Restore a resolved Function while preserving its execution modifier. */
|
|
46
|
-
export type ResolvedFunctionOfProjection<Value extends FunctionProjection> = Value extends FunctionProjection<infer Input, infer Output, infer Auth, infer Ref, infer Key, infer Execution> ? language.ResolvedFunction<Input, Output, Auth, language.CallablePolicy> & {
|
|
45
|
+
}, language.DefinitionKey<Origin, 'function', Name>, CallableExecutionOf<Value>, CallableAdmissionOf<Value>> : never;
|
|
46
|
+
/** Restore a resolved Function while preserving its execution modifier and admission age. */
|
|
47
|
+
export type ResolvedFunctionOfProjection<Value extends FunctionProjection> = Value extends FunctionProjection<infer Input, infer Output, infer Auth, infer Ref, infer Key, infer Execution, infer Admission> ? language.ResolvedFunction<Input, Output, Auth, language.CallablePolicy> & {
|
|
47
48
|
readonly ref: Ref;
|
|
48
49
|
readonly key: Key;
|
|
49
50
|
readonly execution: Execution;
|
|
51
|
+
readonly admission: Admission;
|
|
50
52
|
} : never;
|
|
51
53
|
export {};
|
|
@@ -10,7 +10,7 @@ export interface PropertyProjection<Value = unknown, Required extends boolean =
|
|
|
10
10
|
readonly input: Input;
|
|
11
11
|
}
|
|
12
12
|
/** A Method’s exact callable, ownership and executable contracts. */
|
|
13
|
-
export interface MethodProjection<Input = unknown, Output = unknown, Static extends boolean = boolean, Abstract extends boolean = boolean, Auth extends language.FunctionAuth = language.FunctionAuth, Name extends string = string, Key extends language.MethodKey = language.MethodKey, Executable extends boolean = boolean, Execution extends language.CallableExecution | undefined = language.CallableExecution | undefined> {
|
|
13
|
+
export interface MethodProjection<Input = unknown, Output = unknown, Static extends boolean = boolean, Abstract extends boolean = boolean, Auth extends language.FunctionAuth = language.FunctionAuth, Name extends string = string, Key extends language.MethodKey = language.MethodKey, Executable extends boolean = boolean, Execution extends language.CallableExecution | undefined = language.CallableExecution | undefined, Admission extends language.CallableAdmission | undefined = language.CallableAdmission | undefined> {
|
|
14
14
|
readonly input: Input;
|
|
15
15
|
readonly output: Output;
|
|
16
16
|
readonly static: Static;
|
|
@@ -20,15 +20,17 @@ export interface MethodProjection<Input = unknown, Output = unknown, Static exte
|
|
|
20
20
|
readonly name: Name;
|
|
21
21
|
readonly key: Key;
|
|
22
22
|
readonly execution: Execution;
|
|
23
|
+
readonly admission: Admission;
|
|
23
24
|
}
|
|
24
25
|
/** A Function’s exact callable and declaration contracts. */
|
|
25
|
-
export interface FunctionProjection<Input = unknown, Output = unknown, Auth extends language.FunctionAuth = language.FunctionAuth, Ref extends language.FunctionRef = language.FunctionRef, Key extends language.DefinitionKey<string, 'function'> = language.DefinitionKey<string, 'function'>, Execution extends language.CallableExecution | undefined = language.CallableExecution | undefined> {
|
|
26
|
+
export interface FunctionProjection<Input = unknown, Output = unknown, Auth extends language.FunctionAuth = language.FunctionAuth, Ref extends language.FunctionRef = language.FunctionRef, Key extends language.DefinitionKey<string, 'function'> = language.DefinitionKey<string, 'function'>, Execution extends language.CallableExecution | undefined = language.CallableExecution | undefined, Admission extends language.CallableAdmission | undefined = language.CallableAdmission | undefined> {
|
|
26
27
|
readonly input: Input;
|
|
27
28
|
readonly output: Output;
|
|
28
29
|
readonly auth: Auth;
|
|
29
30
|
readonly ref: Ref;
|
|
30
31
|
readonly key: Key;
|
|
31
32
|
readonly execution: Execution;
|
|
33
|
+
readonly admission: Admission;
|
|
32
34
|
}
|
|
33
35
|
/** A compact Class witness with effective members and exact self facets. */
|
|
34
36
|
export interface ClassProjection<Kind extends language.ClassKind = language.ClassKind, Definition extends Extract<language.ClassDefinition, {
|
|
@@ -56,10 +56,11 @@ type ProjectionPropertyByName<Entries extends PropertyProjection> = Readonly<{
|
|
|
56
56
|
/** Restore qualified lookup and unambiguous named Property access. */
|
|
57
57
|
type PropertyCollectionOfProjection<Entries extends PropertyProjection> = language.ResolvedPropertyCollection<ProjectionPropertyByKey<Entries>, ProjectionPropertyByName<Entries>>;
|
|
58
58
|
type MethodCollectionOperation = 'byKey' | 'get';
|
|
59
|
-
type ResolvedMethodOfProjection<Value> = Value extends MethodProjection<infer Input, infer Output, infer Static, infer Abstract, infer Auth, infer Name, infer Key, infer Executable, infer Execution> ? language.ResolvedMethod<Input, Output, Static, Abstract, Auth, language.CallablePolicy, Key> & {
|
|
59
|
+
type ResolvedMethodOfProjection<Value> = Value extends MethodProjection<infer Input, infer Output, infer Static, infer Abstract, infer Auth, infer Name, infer Key, infer Executable, infer Execution, infer Admission> ? language.ResolvedMethod<Input, Output, Static, Abstract, Auth, language.CallablePolicy, Key> & {
|
|
60
60
|
readonly name: Name;
|
|
61
61
|
readonly executable: Executable;
|
|
62
62
|
readonly execution: Execution;
|
|
63
|
+
readonly admission: Admission;
|
|
63
64
|
} : never;
|
|
64
65
|
type ProjectionMethodByKey<Entries extends MethodProjection> = Readonly<{
|
|
65
66
|
[Key in Entries['key']]: ResolvedMethodOfProjection<Extract<Entries, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CompiledSchemaEntry } from '../../model/schema.js';
|
|
2
2
|
import { type SemanticIndex } from './context.js';
|
|
3
3
|
import { type CoreNode, type CoreEdgeValue } from './core.js';
|
|
4
|
-
/** Check normalized Edge
|
|
4
|
+
/** Check normalized Edge identity, keys, noSelf, cycles and complete Core degrees. */
|
|
5
5
|
export declare function validateCoreEdgeSet(context: SemanticIndex, entry: CompiledSchemaEntry, entryIndex: number, nodes: ReadonlyMap<string, CoreNode>, edges: readonly CoreEdgeValue[]): void;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Key } from '../../../addressing/index.js';
|
|
2
2
|
import { compareUnicode } from '../../../addressing/ordering.js';
|
|
3
3
|
import {} from '../../../language/class/model/edge.js';
|
|
4
|
+
import { coveringEdgeUniqueTuples, edgeUniqueKeys } from '../../../language/class/unique.js';
|
|
4
5
|
import {} from '../../model/schema.js';
|
|
5
6
|
import { fail } from '../diagnostic.js';
|
|
6
7
|
import { isCompiledEdge, classSatisfiesAny, } from './context.js';
|
|
7
8
|
import {} from './core.js';
|
|
8
9
|
import { sameIncidentEndpoint, countBounds } from './edge.js';
|
|
9
|
-
/** Check normalized Edge
|
|
10
|
+
/** Check normalized Edge identity, keys, noSelf, cycles and complete Core degrees. */
|
|
10
11
|
export function validateCoreEdgeSet(context, entry, entryIndex, nodes, edges) {
|
|
11
12
|
const seen = new Set();
|
|
12
13
|
const slices = new Map();
|
|
@@ -26,6 +27,20 @@ export function validateCoreEdgeSet(context, entry, entryIndex, nodes, edges) {
|
|
|
26
27
|
if (edge.class.value.constraints.noSelf === true && edge.source.key === edge.target.key)
|
|
27
28
|
fail(edge.pointer, 'Core Edge violates noSelf.');
|
|
28
29
|
}
|
|
30
|
+
// No two Core Edges hold one key under a tuple covering their Classes (DV-EDGE-UNIQUE).
|
|
31
|
+
const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
|
|
32
|
+
const holders = new Set();
|
|
33
|
+
for (const edge of edges) {
|
|
34
|
+
const keys = edgeUniqueKeys(coveringEdgeUniqueTuples(edge.class.value, resolve), {
|
|
35
|
+
source: edge.source.key,
|
|
36
|
+
target: edge.target.key,
|
|
37
|
+
props: edge.value.properties,
|
|
38
|
+
});
|
|
39
|
+
if (keys.some((key) => holders.has(key)))
|
|
40
|
+
fail(edge.pointer, 'Core Edge holds a key another Core Edge holds.');
|
|
41
|
+
for (const key of keys)
|
|
42
|
+
holders.add(key);
|
|
43
|
+
}
|
|
29
44
|
for (const edgeClass of entry.definitions.classes) {
|
|
30
45
|
if (!isCompiledEdge(edgeClass))
|
|
31
46
|
continue;
|
|
@@ -2,6 +2,7 @@ import { json } from '@astrale-os/kernel-dsl/value';
|
|
|
2
2
|
import { Key, PropertyKey as PropertyKeyValue, } from '../../../addressing/index.js';
|
|
3
3
|
import { composeMethods } from '../../../language/callable/composition.js';
|
|
4
4
|
import { isMethodExecutable } from '../../../language/callable/executable.js';
|
|
5
|
+
import { keyableProperty } from '../../../language/class/unique.js';
|
|
5
6
|
import { bindValueProgram } from '../../../language/value/compile/load.js';
|
|
6
7
|
import {} from '../../model/schema.js';
|
|
7
8
|
import { fail } from '../diagnostic.js';
|
|
@@ -22,6 +23,8 @@ export function analyzeClasses(classes) {
|
|
|
22
23
|
const parent = classes.get(Key.of(ref));
|
|
23
24
|
if (parent === undefined)
|
|
24
25
|
fail(`${located.pointer}/extends/${index}`, 'Parent Class is absent.');
|
|
26
|
+
if (parent.value.inheritance === 'final')
|
|
27
|
+
fail(`${located.pointer}/extends/${index}`, 'A final Class has no subclass.');
|
|
25
28
|
return analyze(parent);
|
|
26
29
|
});
|
|
27
30
|
const properties = new Map();
|
|
@@ -114,11 +117,38 @@ export function validateClassFacets(context) {
|
|
|
114
117
|
}
|
|
115
118
|
}
|
|
116
119
|
}
|
|
120
|
+
if (located.value.unique !== undefined) {
|
|
121
|
+
const properties = context.analyses.get(Key.of(located.value.ref))?.properties;
|
|
122
|
+
const keyable = (key, at) => {
|
|
123
|
+
const property = properties?.get(key)?.declaration;
|
|
124
|
+
if (property === undefined || !keyableProperty(property.ordering, property.auto)) {
|
|
125
|
+
fail(at, 'A key Property is a keyable Property of the Class.');
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
// A Node tuple names Properties only; an Edge tuple names them as `{ property }`.
|
|
129
|
+
const value = located.value;
|
|
130
|
+
if (value.kind === 'node') {
|
|
131
|
+
for (const [t, tuple] of (value.unique ?? []).entries())
|
|
132
|
+
for (const [f, key] of tuple.entries())
|
|
133
|
+
keyable(key, `${located.pointer}/unique/${t}/${f}`);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
for (const [t, tuple] of (value.unique ?? []).entries())
|
|
137
|
+
for (const [f, field] of tuple.entries())
|
|
138
|
+
if (typeof field !== 'string')
|
|
139
|
+
keyable(field.property, `${located.pointer}/unique/${t}/${f}/property`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
117
142
|
if (located.value.kind === 'node') {
|
|
118
143
|
for (const [index, method] of located.value.methods.entries()) {
|
|
119
|
-
if (
|
|
144
|
+
if (isMethodExecutable(located.value, method))
|
|
145
|
+
continue;
|
|
146
|
+
if (method.policy !== undefined) {
|
|
120
147
|
fail(`${located.pointer}/methods/${index}/policy`, 'An abstract Method cannot have a Policy.');
|
|
121
148
|
}
|
|
149
|
+
if (method.admission !== undefined) {
|
|
150
|
+
fail(`${located.pointer}/methods/${index}/admission`, 'An abstract Method cannot have an admission age.');
|
|
151
|
+
}
|
|
122
152
|
}
|
|
123
153
|
}
|
|
124
154
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Key } from '../../../addressing/index.js';
|
|
2
2
|
import { isMethodExecutable } from '../../../language/callable/executable.js';
|
|
3
|
+
import { coveringNodeUniqueTuples, nodeUniqueKeys } from '../../../language/class/unique.js';
|
|
3
4
|
import {} from '../../../language/core/model/core.js';
|
|
4
5
|
import { policyObjectOrigin, policyObjectKey, projectedMemberClass, } from '../../../language/index.js';
|
|
5
6
|
import { bindValueProgram } from '../../../language/value/compile/load.js';
|
|
@@ -31,6 +32,7 @@ export function validateCore(candidate, context) {
|
|
|
31
32
|
pointer: path,
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
validateCoreNodeKeys(context, nodes);
|
|
34
36
|
const edges = [];
|
|
35
37
|
for (const [index, value] of entry.facts.core.entries()) {
|
|
36
38
|
const path = `/closure/${entryIndex}/facts/core/${index}`;
|
|
@@ -67,6 +69,20 @@ export function validateCore(candidate, context) {
|
|
|
67
69
|
validateCoreEdgeSet(context, entry, entryIndex, nodes, edges);
|
|
68
70
|
}
|
|
69
71
|
}
|
|
72
|
+
/** No two Core Nodes hold one key under a tuple covering their Classes (DV-NODE-UNIQUE). */
|
|
73
|
+
function validateCoreNodeKeys(context, nodes) {
|
|
74
|
+
const resolve = (ref) => context.classes.get(Key.of(ref))?.value;
|
|
75
|
+
const holders = new Set();
|
|
76
|
+
for (const node of nodes.values()) {
|
|
77
|
+
const keys = nodeUniqueKeys(coveringNodeUniqueTuples(node.class.value, resolve), {
|
|
78
|
+
props: node.value.properties,
|
|
79
|
+
});
|
|
80
|
+
if (keys.some((key) => holders.has(key)))
|
|
81
|
+
fail(node.pointer, 'Core Node holds a key another Core Node holds.');
|
|
82
|
+
for (const key of keys)
|
|
83
|
+
holders.add(key);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
70
86
|
function validateCoreProperties(values, analysis, path) {
|
|
71
87
|
for (const key of Object.keys(values))
|
|
72
88
|
if (!analysis.properties.has(key))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {} from '@astrale-os/kernel-dsl/value';
|
|
2
|
+
import { isAdmissionMaxAge } from '../../../language/callable/admission.js';
|
|
2
3
|
import {} from '../../model/schema.js';
|
|
3
4
|
import { invalid, pointer } from '../diagnostic.js';
|
|
4
5
|
import { callablePolicy } from './policy.js';
|
|
@@ -16,7 +17,7 @@ export function compiledCallable(input, values, method, path) {
|
|
|
16
17
|
const value = object(input, 'Compiled Callable', path);
|
|
17
18
|
exact(value, method
|
|
18
19
|
? ['name', 'auth', 'static', 'abstract', 'input', 'output']
|
|
19
|
-
: ['ref', 'auth', 'input', 'output'], 'Compiled Callable', path, ['policy', 'description', 'execution', 'fields']);
|
|
20
|
+
: ['ref', 'auth', 'input', 'output'], 'Compiled Callable', path, ['policy', 'description', 'execution', 'admission', 'fields']);
|
|
20
21
|
if (method) {
|
|
21
22
|
memberName(value.name, 'Method name', `${path}/name`);
|
|
22
23
|
boolean(value.static, 'Method static', `${path}/static`);
|
|
@@ -87,4 +88,13 @@ export function compiledCallable(input, values, method, path) {
|
|
|
87
88
|
invalid('durable Callable output', 'COMPILED_SOURCE_INVALID', `${outputPath}/mode`);
|
|
88
89
|
}
|
|
89
90
|
}
|
|
91
|
+
if (value.admission !== undefined) {
|
|
92
|
+
const admissionPath = `${path}/admission`;
|
|
93
|
+
const admission = object(value.admission, 'Callable admission', admissionPath);
|
|
94
|
+
exact(admission, ['maxAge'], 'Callable admission', admissionPath);
|
|
95
|
+
// An absent admission age is the only spelling of a call admitted afresh.
|
|
96
|
+
if (!isAdmissionMaxAge(admission.maxAge)) {
|
|
97
|
+
invalid('Callable admission age', 'COMPILED_SOURCE_INVALID', `${admissionPath}/maxAge`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
90
100
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {} from '@astrale-os/kernel-dsl/value';
|
|
2
2
|
import { Key } from '../../../addressing/index.js';
|
|
3
3
|
import { MEDIA_TYPE_PATTERN } from '../../../language/class/model/data.js';
|
|
4
|
+
import { compareEdgeUniqueTuples, compareNodeUniqueTuples, edgeUniqueTuple, nodeUniqueTuple, } from '../../../language/class/unique.js';
|
|
4
5
|
import {} from '../../model/schema.js';
|
|
5
6
|
import { invalid } from '../diagnostic.js';
|
|
6
7
|
import { compiledCallable } from './callable.js';
|
|
@@ -25,9 +26,15 @@ export function compiledClass(input, values, path) {
|
|
|
25
26
|
'constraints',
|
|
26
27
|
'properties',
|
|
27
28
|
'policies',
|
|
28
|
-
], 'Compiled Class', path, value.kind === 'node'
|
|
29
|
+
], 'Compiled Class', path, value.kind === 'node'
|
|
30
|
+
? ['data', 'description', 'icon', 'inheritance', 'unique']
|
|
31
|
+
: ['description', 'inheritance', 'unique']);
|
|
29
32
|
definitionRef(value.ref, 'class', 'Class ref', `${path}/ref`);
|
|
30
33
|
boolean(value.abstract, 'Class abstract', `${path}/abstract`);
|
|
34
|
+
if (value.inheritance !== undefined &&
|
|
35
|
+
value.inheritance !== 'open' &&
|
|
36
|
+
value.inheritance !== 'final')
|
|
37
|
+
invalid('Class inheritance', undefined, `${path}/inheritance`);
|
|
31
38
|
description(value.description, 'Class description', `${path}/description`);
|
|
32
39
|
const extendsPath = `${path}/extends`;
|
|
33
40
|
const parents = array(value.extends, 'Class extends', extendsPath).map((parent, index) => definitionRef(parent, 'class', 'Class parent', `${extendsPath}/${index}`));
|
|
@@ -40,6 +47,8 @@ export function compiledClass(input, values, path) {
|
|
|
40
47
|
dataDefinition(value.data, `${path}/data`);
|
|
41
48
|
boundedString(value.icon, 1, 8000, 'Class icon', `${path}/icon`);
|
|
42
49
|
classPolicies(value.policies, 'node', `${path}/policies`);
|
|
50
|
+
if (value.unique !== undefined)
|
|
51
|
+
nodeUniqueTuples(value.unique, `${path}/unique`);
|
|
43
52
|
const methodsPath = `${path}/methods`;
|
|
44
53
|
const methods = array(value.methods, 'Class methods', methodsPath);
|
|
45
54
|
for (const [index, method] of methods.entries())
|
|
@@ -93,9 +102,13 @@ function edgeContract(value, path) {
|
|
|
93
102
|
object(endpoints.target, 'directed Edge target', `${endpointsPath}/target`).role) {
|
|
94
103
|
invalid('Edge endpoint roles', undefined, endpointsPath);
|
|
95
104
|
}
|
|
105
|
+
if (value.unique !== undefined)
|
|
106
|
+
uniqueTuples(value.unique, `${path}/unique`);
|
|
96
107
|
return;
|
|
97
108
|
}
|
|
98
|
-
if (value.orientation !== 'undirected' ||
|
|
109
|
+
if (value.orientation !== 'undirected' ||
|
|
110
|
+
constraints.acyclic !== undefined ||
|
|
111
|
+
value.unique !== undefined) {
|
|
99
112
|
invalid('Edge orientation', undefined, `${path}/orientation`);
|
|
100
113
|
}
|
|
101
114
|
const endpointsPath = `${path}/endpoints`;
|
|
@@ -109,9 +122,41 @@ function edgeContract(value, path) {
|
|
|
109
122
|
invalid('Edge endpoint roles', undefined, endpointsPath);
|
|
110
123
|
}
|
|
111
124
|
}
|
|
125
|
+
/** A nonempty list of canonical tuples (`edgeUniqueTuple`), distinct and in canonical order. */
|
|
126
|
+
function uniqueTuples(input, path) {
|
|
127
|
+
const tuples = array(input, 'Edge unique tuples', path);
|
|
128
|
+
if (tuples.length === 0)
|
|
129
|
+
invalid('Edge unique tuples', undefined, path);
|
|
130
|
+
const known = tuples.map((tuple, index) => {
|
|
131
|
+
const fields = edgeUniqueTuple(array(tuple, 'Edge unique tuple', `${path}/${index}`));
|
|
132
|
+
if (fields === undefined)
|
|
133
|
+
invalid('Edge unique tuple', undefined, `${path}/${index}`);
|
|
134
|
+
return fields;
|
|
135
|
+
});
|
|
136
|
+
for (const [index, tuple] of known.entries()) {
|
|
137
|
+
if (index > 0 && compareEdgeUniqueTuples(known[index - 1], tuple) >= 0)
|
|
138
|
+
invalid('Edge unique tuples', undefined, `${path}/${index}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** A nonempty list of canonical Node tuples (`nodeUniqueTuple`), distinct and in canonical order. */
|
|
142
|
+
function nodeUniqueTuples(input, path) {
|
|
143
|
+
const tuples = array(input, 'Node unique tuples', path);
|
|
144
|
+
if (tuples.length === 0)
|
|
145
|
+
invalid('Node unique tuples', undefined, path);
|
|
146
|
+
const known = tuples.map((tuple, index) => {
|
|
147
|
+
const keys = nodeUniqueTuple(array(tuple, 'Node unique tuple', `${path}/${index}`));
|
|
148
|
+
if (keys === undefined)
|
|
149
|
+
invalid('Node unique tuple', undefined, `${path}/${index}`);
|
|
150
|
+
return keys;
|
|
151
|
+
});
|
|
152
|
+
for (const [index, tuple] of known.entries()) {
|
|
153
|
+
if (index > 0 && compareNodeUniqueTuples(known[index - 1], tuple) >= 0)
|
|
154
|
+
invalid('Node unique tuples', undefined, `${path}/${index}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
112
157
|
function edgeEndpoint(input, count, label, path) {
|
|
113
158
|
const value = object(input, label, path);
|
|
114
|
-
exact(value, ['role', 'accepts', count], label, path);
|
|
159
|
+
exact(value, ['role', 'accepts', count], label, path, ['onDelete']);
|
|
115
160
|
memberName(value.role, `${label} role`, `${path}/role`);
|
|
116
161
|
const acceptsPath = `${path}/accepts`;
|
|
117
162
|
const accepts = array(value.accepts, `${label} accepts`, acceptsPath).map((item, index) => definitionRef(item, 'class', `${label} accepted Class`, `${acceptsPath}/${index}`));
|
|
@@ -124,6 +169,8 @@ function edgeEndpoint(input, count, label, path) {
|
|
|
124
169
|
value[count] !== '1') {
|
|
125
170
|
invalid(`${label} ${count}`, undefined, `${path}/${count}`);
|
|
126
171
|
}
|
|
172
|
+
if (value.onDelete !== undefined && value.onDelete !== 'restrict' && value.onDelete !== 'detach')
|
|
173
|
+
invalid(`${label} onDelete`, undefined, `${path}/onDelete`);
|
|
127
174
|
}
|
|
128
175
|
function dataDefinition(input, path) {
|
|
129
176
|
const value = object(input, 'Class data', path);
|
|
@@ -89,6 +89,7 @@ function compileEntry(schema, lookup) {
|
|
|
89
89
|
static: method.static,
|
|
90
90
|
abstract: method.abstract,
|
|
91
91
|
...(method.execution === undefined ? {} : { execution: method.execution }),
|
|
92
|
+
...(method.admission === undefined ? {} : { admission: method.admission }),
|
|
92
93
|
input,
|
|
93
94
|
...(fields === undefined ? {} : { fields }),
|
|
94
95
|
output: output(method.output, `${pointer}/methods/${name}/output`),
|
|
@@ -117,6 +118,7 @@ function compileEntry(schema, lookup) {
|
|
|
117
118
|
...(definition.policy === undefined ? {} : { policy: definition.policy }),
|
|
118
119
|
...(definition.description === undefined ? {} : { description: definition.description }),
|
|
119
120
|
...(definition.execution === undefined ? {} : { execution: definition.execution }),
|
|
121
|
+
...(definition.admission === undefined ? {} : { admission: definition.admission }),
|
|
120
122
|
input,
|
|
121
123
|
...(fields === undefined ? {} : { fields }),
|
|
122
124
|
output: output(definition.output, `/functions/${definition.ref.name}/output`),
|
package/dist/v1/domain/create.js
CHANGED
|
@@ -130,6 +130,7 @@ function createDefinitions(declarations, classesByKey, input) {
|
|
|
130
130
|
input: definition.input,
|
|
131
131
|
output: definition.output,
|
|
132
132
|
...(definition.execution === undefined ? {} : { execution: definition.execution }),
|
|
133
|
+
...(definition.admission === undefined ? {} : { admission: definition.admission }),
|
|
133
134
|
auth: definition.auth,
|
|
134
135
|
policy: definition.policy,
|
|
135
136
|
...(inputFields === undefined ? {} : { inputFields }),
|
|
@@ -70,6 +70,9 @@ export function createClasses(definitions, validation) {
|
|
|
70
70
|
...(methodDefinition.execution === undefined
|
|
71
71
|
? {}
|
|
72
72
|
: { execution: methodDefinition.execution }),
|
|
73
|
+
...(methodDefinition.admission === undefined
|
|
74
|
+
? {}
|
|
75
|
+
: { admission: methodDefinition.admission }),
|
|
73
76
|
auth: methodDefinition.auth,
|
|
74
77
|
policy: methodDefinition.policy,
|
|
75
78
|
static: methodDefinition.static,
|
package/dist/v1/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { isBinaryInput } from './language/callable/model/callable.js';
|
|
|
5
5
|
export type { EventOf, StateMachine, StateOf } from './language/state/index.js';
|
|
6
6
|
export { PropertyValues } from './language/index.js';
|
|
7
7
|
export * as metadata from './language/definition/metadata.js';
|
|
8
|
-
export type { AnyResolvedClass, BoundMethodOf, BoundMethodShortcutsOf, CallableResultOf, CallableInputOf, CallableInputModeOf, CallableOutputOf, ClassSatisfactionKeysOf, ClassDefinition, CoreDefinition, CoreEdge, FunctionAuth, FunctionDefinition, BinaryInput, BinaryInputProjection, CallableInputContract, MethodDefinition, MethodOwnerKeyOf, CallablePolicy, ClassPolicy, ClassRuleChecks, ClassRuleObject, NodeClassPolicy, PolicyCheckExpression, PolicyDefinition, PropertyImmutability, PropertyInputOf, PropertyAccessOf, PropertyOutputOf, PropertyShortcutsOf, PropertyValuesOf, ResolvedClass, ResolvedCoreDefinition, ResolvedCoreEndpoint, ResolvedData, ResolvedFunction, ExecutableMethod, ResolvedMethod, ResolvedMethodCollection, ResolvedPolicy, ResolvedProperty, ResolvedView, MethodAccessOf, SelfMethodsOf, SelfPropertiesOf, SelfStaticMethodsOf, StaticMethodsOf, ViewDefinition, } from './language/index.js';
|
|
8
|
+
export type { AnyResolvedClass, BoundMethodOf, BoundMethodShortcutsOf, CallableResultOf, CallableInputOf, CallableInputModeOf, CallableOutputOf, ClassSatisfactionKeysOf, ClassDefinition, CoreDefinition, CoreEdge, FunctionAuth, FunctionDefinition, Inheritance, BinaryInput, BinaryInputProjection, CallableInputContract, MethodDefinition, MethodOwnerKeyOf, CallablePolicy, ClassPolicy, ClassRuleChecks, ClassRuleObject, NodeClassPolicy, PolicyCheckExpression, PolicyDefinition, PropertyImmutability, PropertyInputOf, PropertyAccessOf, PropertyOutputOf, PropertyShortcutsOf, PropertyValuesOf, ResolvedClass, ResolvedCoreDefinition, ResolvedCoreEndpoint, ResolvedData, ResolvedFunction, ExecutableMethod, ResolvedMethod, ResolvedMethodCollection, ResolvedPolicy, ResolvedProperty, ResolvedView, MethodAccessOf, SelfMethodsOf, SelfPropertiesOf, SelfStaticMethodsOf, StaticMethodsOf, ViewDefinition, } from './language/index.js';
|
|
9
9
|
export { acceptDefinitionRef, callableAddress, ClassKey, equalDefinitionRefs, isDefinitionRef, Key, MethodKey, PropertyKey, } from './addressing/index.js';
|
|
10
10
|
export type { ClassRef, CoreRef, DefinitionBase, DefinitionKey, DefinitionRef, FunctionRef, MethodAddress, PolicyRef, Revision, ViewRef, } from './addressing/index.js';
|
|
11
11
|
export type { Definition } from './language/index.js';
|
|
@@ -14,6 +14,7 @@ export { isDomain } from './domain/index.js';
|
|
|
14
14
|
export type * as builder from './builder/index.js';
|
|
15
15
|
export type { PathAuthoring, TypedValueSchema } from './builder/index.js';
|
|
16
16
|
export type { PropertyValues as PropertyValuesValue } from './language/index.js';
|
|
17
|
+
export type { BlobReceipt, BlobRef } from './language/value/model/blob.js';
|
|
17
18
|
export type { CompiledSchema } from './compiled/index.js';
|
|
18
19
|
export * as schema from './schema/index.js';
|
|
19
20
|
export * as bundle from './bundle/index.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CallablePolicy } from '../policy/model/policy.js';
|
|
2
|
+
/**
|
|
3
|
+
* The language ceiling of a declared admission age, in seconds. Raising it later widens the
|
|
4
|
+
* language; lowering it would refuse accepted Schemas.
|
|
5
|
+
*/
|
|
6
|
+
export declare const MAXIMUM_ADMISSION_AGE_SECONDS = 300;
|
|
7
|
+
/** Whether `value` is a declarable admission age: an integer from 1 to the language ceiling. */
|
|
8
|
+
export declare function isAdmissionMaxAge(value: unknown): value is number;
|
|
9
|
+
/**
|
|
10
|
+
* The input fields an admission of this callable reads: the `field` of every `input` check object
|
|
11
|
+
* of its Policy, unique and in Unicode code-point order. A callable without Policy checks reads no
|
|
12
|
+
* input field. Two calls that agree on these fields, and on everything else the admission reads,
|
|
13
|
+
* receive the same admission.
|
|
14
|
+
*/
|
|
15
|
+
export declare function admissionInputFields(policy: CallablePolicy | undefined): readonly string[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { compareUnicode } from '../../addressing/ordering.js';
|
|
2
|
+
/**
|
|
3
|
+
* The language ceiling of a declared admission age, in seconds. Raising it later widens the
|
|
4
|
+
* language; lowering it would refuse accepted Schemas.
|
|
5
|
+
*/
|
|
6
|
+
export const MAXIMUM_ADMISSION_AGE_SECONDS = 300;
|
|
7
|
+
/** Whether `value` is a declarable admission age: an integer from 1 to the language ceiling. */
|
|
8
|
+
export function isAdmissionMaxAge(value) {
|
|
9
|
+
return (typeof value === 'number' &&
|
|
10
|
+
Number.isInteger(value) &&
|
|
11
|
+
value >= 1 &&
|
|
12
|
+
value <= MAXIMUM_ADMISSION_AGE_SECONDS);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The input fields an admission of this callable reads: the `field` of every `input` check object
|
|
16
|
+
* of its Policy, unique and in Unicode code-point order. A callable without Policy checks reads no
|
|
17
|
+
* input field. Two calls that agree on these fields, and on everything else the admission reads,
|
|
18
|
+
* receive the same admission.
|
|
19
|
+
*/
|
|
20
|
+
export function admissionInputFields(policy) {
|
|
21
|
+
if (policy === undefined || policy === true)
|
|
22
|
+
return Object.freeze([]);
|
|
23
|
+
const fields = new Set();
|
|
24
|
+
collectInputFields(policy, fields);
|
|
25
|
+
return Object.freeze([...fields].sort(compareUnicode));
|
|
26
|
+
}
|
|
27
|
+
function collectInputFields(expression, fields) {
|
|
28
|
+
if ('check' in expression) {
|
|
29
|
+
if (expression.object.kind === 'input')
|
|
30
|
+
fields.add(expression.object.field);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if ('sameNode' in expression) {
|
|
34
|
+
for (const object of [expression.sameNode.left, expression.sameNode.right]) {
|
|
35
|
+
if (object.kind === 'input')
|
|
36
|
+
fields.add(object.field);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
for (const child of 'allOf' in expression ? expression.allOf : expression.anyOf) {
|
|
41
|
+
collectInputFields(child, fields);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -21,6 +21,15 @@ export type OutputMode = CallableOutput['mode'];
|
|
|
21
21
|
export interface CallableExecution {
|
|
22
22
|
readonly durable: boolean;
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Admission age of a callable: how old, in whole seconds, the admission decision used for one of its
|
|
26
|
+
* calls may be. A destination may reuse an admission it received within that age; a Runtime that
|
|
27
|
+
* never reuses one conforms. Absent means every call is admitted afresh, and `maxAge` is an integer
|
|
28
|
+
* from 1 to `MAXIMUM_ADMISSION_AGE_SECONDS`.
|
|
29
|
+
*/
|
|
30
|
+
export interface CallableAdmission {
|
|
31
|
+
readonly maxAge: number;
|
|
32
|
+
}
|
|
24
33
|
/** A binary Function receives portable metadata and one required byte stream. */
|
|
25
34
|
export interface BinaryInput {
|
|
26
35
|
readonly mode: 'binary';
|
|
@@ -39,6 +48,7 @@ export interface CallableDefinitionBase<Input extends CallableInputContract = Ca
|
|
|
39
48
|
readonly input: Input;
|
|
40
49
|
readonly output: CallableOutput;
|
|
41
50
|
readonly execution?: CallableExecution;
|
|
51
|
+
readonly admission?: CallableAdmission;
|
|
42
52
|
}
|
|
43
53
|
export type CallableDefinition<Input extends CallableInputContract = CallableInputContract> = CallableDefinitionBase<Input> & ({
|
|
44
54
|
readonly auth: 'anonymous' | 'authenticated';
|
|
@@ -2,7 +2,7 @@ import type { DefinitionKey, FunctionRef, Key, MethodKey } from '../../addressin
|
|
|
2
2
|
import type { ResolvedClass } from '../class/resolved.js';
|
|
3
3
|
import type { CallablePolicy } from '../policy/model/policy.js';
|
|
4
4
|
import type { Diagnostic } from '../validation/diagnostic.js';
|
|
5
|
-
import type { BinaryInputProjection, CallableExecution, FunctionDefinition, MethodDefinition } from './model/callable.js';
|
|
5
|
+
import type { BinaryInputProjection, CallableAdmission, CallableExecution, FunctionDefinition, MethodDefinition } from './model/callable.js';
|
|
6
6
|
import type { FunctionAuth } from './model/callable.js';
|
|
7
7
|
type CallableDefinitionOf<Definition extends FunctionDefinition | MethodDefinition, Auth extends FunctionAuth, Policy extends CallablePolicy> = Omit<Definition, 'auth' | 'policy'> & (Auth extends FunctionAuth ? {
|
|
8
8
|
readonly auth: Auth;
|
|
@@ -22,6 +22,8 @@ export interface ResolvedMethod<out Input = unknown, out Output = unknown, out S
|
|
|
22
22
|
readonly output: MethodDefinition['output'];
|
|
23
23
|
/** Present only for a durable Method. */
|
|
24
24
|
readonly execution?: CallableExecution;
|
|
25
|
+
/** Present only when the Method declares an admission age. */
|
|
26
|
+
readonly admission?: CallableAdmission;
|
|
25
27
|
readonly auth: Auth;
|
|
26
28
|
readonly policy?: Auth extends 'authorized' ? Policy : never;
|
|
27
29
|
readonly static: Static;
|
|
@@ -53,6 +55,8 @@ export interface ResolvedFunction<out Input = unknown, out Output = unknown, out
|
|
|
53
55
|
readonly output: FunctionDefinition['output'];
|
|
54
56
|
/** Present only for a durable Function. */
|
|
55
57
|
readonly execution?: CallableExecution;
|
|
58
|
+
/** Present only when the Function declares an admission age. */
|
|
59
|
+
readonly admission?: CallableAdmission;
|
|
56
60
|
readonly auth: Auth;
|
|
57
61
|
readonly policy?: Auth extends 'authorized' ? Policy : never;
|
|
58
62
|
/** Present only when the callable input is a safely enumerable closed object. */
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
import type { ClassRef } from '../../addressing/index.js';
|
|
2
|
-
import type { ClassKind } from './model/class.js';
|
|
3
|
-
/**
|
|
4
|
-
export interface
|
|
2
|
+
import type { ClassKind, Inheritance } from './model/class.js';
|
|
3
|
+
/** A Class as satisfaction reads it, shared by source, compiled and resolved Class admission. */
|
|
4
|
+
export interface ClassAncestry {
|
|
5
5
|
readonly ref: ClassRef;
|
|
6
6
|
readonly kind: ClassKind;
|
|
7
7
|
readonly extends: readonly ClassRef[];
|
|
8
8
|
}
|
|
9
|
+
/** The origin of the Kernel, whose Schema every Domain depends on. */
|
|
10
|
+
export declare const KERNEL_ORIGIN = "kernel.astrale.ai";
|
|
9
11
|
/** Kernel graph roots are intrinsic supertypes, not authored structural Edge contracts. */
|
|
10
|
-
export declare function isGraphRoot(value: Pick<
|
|
12
|
+
export declare function isGraphRoot(value: Pick<ClassAncestry, 'ref' | 'kind'>): boolean;
|
|
11
13
|
/** Same-kind satisfaction includes the intrinsic root and the declared parent closure. */
|
|
12
|
-
export declare function classSatisfies(candidate:
|
|
14
|
+
export declare function classSatisfies(candidate: ClassAncestry, required: ClassAncestry, resolve: (ref: ClassRef) => ClassAncestry | undefined): boolean;
|
|
15
|
+
/** The inheritance a Class declares, `'internal'` when it declares none. */
|
|
16
|
+
export declare function inheritanceOf(declaration: {
|
|
17
|
+
readonly inheritance?: Inheritance;
|
|
18
|
+
}): Inheritance;
|
|
19
|
+
/**
|
|
20
|
+
* Whether a Class of another Domain may extend this Class: only an `'open'` one admits it. Its own
|
|
21
|
+
* Domain may extend any Class that is not `'final'`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function admitsForeignSubclass(declaration: {
|
|
24
|
+
readonly inheritance?: Inheritance;
|
|
25
|
+
}): boolean;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
/** The origin of the Kernel, whose Schema every Domain depends on. */
|
|
2
|
+
export const KERNEL_ORIGIN = 'kernel.astrale.ai';
|
|
1
3
|
/** Kernel graph roots are intrinsic supertypes, not authored structural Edge contracts. */
|
|
2
4
|
export function isGraphRoot(value) {
|
|
3
|
-
return (value.ref.origin ===
|
|
5
|
+
return (value.ref.origin === KERNEL_ORIGIN &&
|
|
4
6
|
value.ref.name === (value.kind === 'node' ? 'Node' : 'Edge'));
|
|
5
7
|
}
|
|
6
8
|
/** Same-kind satisfaction includes the intrinsic root and the declared parent closure. */
|
|
@@ -23,3 +25,14 @@ export function classSatisfies(candidate, required, resolve) {
|
|
|
23
25
|
};
|
|
24
26
|
return visit(candidate);
|
|
25
27
|
}
|
|
28
|
+
/** The inheritance a Class declares, `'internal'` when it declares none. */
|
|
29
|
+
export function inheritanceOf(declaration) {
|
|
30
|
+
return declaration.inheritance ?? 'internal';
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Whether a Class of another Domain may extend this Class: only an `'open'` one admits it. Its own
|
|
34
|
+
* Domain may extend any Class that is not `'final'`.
|
|
35
|
+
*/
|
|
36
|
+
export function admitsForeignSubclass(declaration) {
|
|
37
|
+
return inheritanceOf(declaration) === 'open';
|
|
38
|
+
}
|