@agentshouse/mdmodel 0.1.0-c83456e1cebfb → 0.1.0-cf72583e19192

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,6 +46,7 @@ if (parsed.ok) {
46
46
  | `apply` | Apply one field, section, preamble, or link change |
47
47
  | `links`, `target`, `retarget` | Inventory and rewrite link destinations |
48
48
  | `project`, `divide` | Embedding projection input and its division into Spans |
49
+ | `facts`, `holds`, `fires` | A condition over a Document and over one of its changes |
49
50
  | `MARKDOWN_SYNTAX_PROFILE`, `VERSION` | The pinned Markdown profile (GFM 0.29) and MD model version |
50
51
  | `MEMBER_FIELD`, `SITE_FIELD`, `RECEIVED_FIELD` | The field names validation counts as declared beyond a type's own |
51
52
 
@@ -0,0 +1,93 @@
1
+ import type { Document, VerifiedModel } from './types.js';
2
+ export type ConditionValue = string | number | boolean | {
3
+ readonly owner: true;
4
+ };
5
+ export type ConditionTest = {
6
+ readonly all: readonly ConditionTest[];
7
+ } | {
8
+ readonly any: readonly ConditionTest[];
9
+ } | {
10
+ readonly not: ConditionTest;
11
+ } | ({
12
+ readonly path: string;
13
+ } & ({
14
+ readonly eq: ConditionValue;
15
+ } | {
16
+ readonly in: readonly ConditionValue[];
17
+ } | {
18
+ readonly exists: boolean;
19
+ } | {
20
+ readonly contains: ConditionValue;
21
+ } | {
22
+ readonly gt: number | string;
23
+ } | {
24
+ readonly gte: number | string;
25
+ } | {
26
+ readonly lt: number | string;
27
+ } | {
28
+ readonly lte: number | string;
29
+ } | {
30
+ readonly prefix: string;
31
+ }));
32
+ export type ConditionScope = {
33
+ readonly type: string;
34
+ } | {
35
+ readonly folder: string;
36
+ } | {
37
+ readonly document: string;
38
+ };
39
+ type DocumentsCondition = {
40
+ readonly on: 'documents';
41
+ readonly scope: ConditionScope;
42
+ readonly by?: ConditionTest;
43
+ };
44
+ export type Condition = (DocumentsCondition & {
45
+ readonly mode: 'starts_matching';
46
+ readonly new_documents: boolean;
47
+ readonly match: ConditionTest;
48
+ }) | (DocumentsCondition & {
49
+ readonly mode: 'field_changes';
50
+ readonly field: string;
51
+ readonly from?: readonly ConditionValue[] | 'new';
52
+ readonly to?: readonly ConditionValue[] | 'deleted';
53
+ readonly match?: ConditionTest;
54
+ });
55
+ export type Fact = {
56
+ readonly kind: 'string' | 'number' | 'date' | 'enum' | 'reference';
57
+ readonly value: string | number | readonly (string | number)[];
58
+ };
59
+ export type DocumentFacts = {
60
+ readonly id: string;
61
+ readonly path: string;
62
+ readonly type: string | null;
63
+ readonly fields: Readonly<Record<string, Fact>>;
64
+ readonly members: Readonly<Record<string, string | readonly string[]>>;
65
+ readonly prose: readonly string[];
66
+ readonly unreadable: readonly string[];
67
+ };
68
+ export declare const WRITE_DOORS: readonly ['browser', 'agent', 'client'];
69
+ export type WriteDoor = (typeof WRITE_DOORS)[number];
70
+ export type Actor = {
71
+ readonly user?: string;
72
+ readonly site?: string;
73
+ readonly door?: WriteDoor;
74
+ };
75
+ export type DocumentEvent = {
76
+ readonly before: DocumentFacts | null;
77
+ readonly after: DocumentFacts | null;
78
+ readonly changed: readonly string[];
79
+ readonly by: Actor;
80
+ };
81
+ export type Resolved = {
82
+ readonly id: string;
83
+ readonly member?: string;
84
+ };
85
+ type Truth = boolean | undefined;
86
+ export declare function facts(document: Document, at: {
87
+ readonly id: string;
88
+ readonly path: string;
89
+ }, model: VerifiedModel, resolve: (target: string) => Resolved | undefined): DocumentFacts;
90
+ export declare function holds(test: ConditionTest, document: DocumentFacts, owner: string): Truth;
91
+ export declare function fires(condition: Condition, event: DocumentEvent, owner: string): boolean;
92
+ export {};
93
+ //# sourceMappingURL=condition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../src/condition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ import { target } from './paths.js';
2
+ import { fitsValue } from './schema.js';
3
+ import { declaredFields } from './validate.js';
4
+ export const WRITE_DOORS = ['browser', 'agent', 'client'];
5
+ const DATE = /^\d{4}-\d{2}-\d{2}$/u;
6
+ function record(value) {
7
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
8
+ }
9
+ function referenced(model, spec) {
10
+ const to = spec.kind === 'reference'
11
+ ? spec.to
12
+ : spec.kind === 'list' && spec.of.kind === 'reference'
13
+ ? spec.of.to
14
+ : null;
15
+ return to !== null && Object.hasOwn(model.types, to) && model.types[to].memberDocument;
16
+ }
17
+ function fitted(spec, value, path, resolve) {
18
+ if (!fitsValue(spec, value))
19
+ return undefined;
20
+ if (spec.kind !== 'reference')
21
+ return { value: value };
22
+ const reached = target(path, value);
23
+ return reached === null ? undefined : resolve(reached);
24
+ }
25
+ export function facts(document, at, model, resolve) {
26
+ const type = document.type ?? null;
27
+ const definition = type !== null && Object.hasOwn(model.types, type) ? model.types[type] : null;
28
+ const fields = {};
29
+ const members = {};
30
+ const prose = Object.keys(document.sections).map((heading) => `/sections/${heading}`);
31
+ const unreadable = [];
32
+ for (const [name, spec] of Object.entries(definition === null ? {} : declaredFields(definition))) {
33
+ const value = document.fields[name];
34
+ if (value === undefined || value === null)
35
+ continue;
36
+ const scalar = spec.kind === 'list' ? spec.of : spec;
37
+ const items = spec.kind === 'list' ? value : [value];
38
+ const held = Array.isArray(items)
39
+ ? items.map((item) => fitted(scalar, item, at.path, resolve))
40
+ : [undefined];
41
+ if (held.some((item) => item === undefined)) {
42
+ unreadable.push(`/fields/${name}`);
43
+ if (referenced(model, spec))
44
+ unreadable.push(`/members/${name}`);
45
+ continue;
46
+ }
47
+ if (scalar.kind === 'text') {
48
+ prose.push(`/fields/${name}`);
49
+ continue;
50
+ }
51
+ const values = held.map((item) => ('id' in item ? item.id : item.value));
52
+ fields[name] = { kind: scalar.kind, value: spec.kind === 'list' ? values : values[0] };
53
+ if (!referenced(model, spec))
54
+ continue;
55
+ const bound = held.flatMap((item) => 'member' in item && item.member !== undefined ? [item.member] : []);
56
+ if (spec.kind === 'list')
57
+ members[name] = bound;
58
+ else if (bound[0] !== undefined)
59
+ members[name] = bound[0];
60
+ }
61
+ return {
62
+ id: at.id,
63
+ path: `/${at.path}`,
64
+ type,
65
+ fields,
66
+ members,
67
+ prose: prose.sort(),
68
+ unreadable: unreadable.sort(),
69
+ };
70
+ }
71
+ function readDocument(facts, path) {
72
+ if (path === '/path')
73
+ return { kind: 'path', value: facts.path };
74
+ if (path === '/type')
75
+ return facts.type === null ? undefined : { kind: 'string', value: facts.type };
76
+ if (facts.unreadable.includes(path))
77
+ return { kind: 'unreadable' };
78
+ if (facts.prose.includes(path))
79
+ return { kind: 'present' };
80
+ if (path.startsWith('/fields/')) {
81
+ const name = path.slice('/fields/'.length);
82
+ return Object.hasOwn(facts.fields, name) ? facts.fields[name] : undefined;
83
+ }
84
+ if (path.startsWith('/members/')) {
85
+ const name = path.slice('/members/'.length);
86
+ return Object.hasOwn(facts.members, name)
87
+ ? { kind: 'member', value: facts.members[name] }
88
+ : undefined;
89
+ }
90
+ return undefined;
91
+ }
92
+ function readActor(actor, path) {
93
+ const value = path === '/user'
94
+ ? actor.user
95
+ : path === '/site'
96
+ ? actor.site
97
+ : path === '/door'
98
+ ? actor.door
99
+ : undefined;
100
+ return value === undefined ? undefined : { kind: 'actor', value };
101
+ }
102
+ function wanted(value, owner) {
103
+ return record(value) && value.owner === true ? owner : value;
104
+ }
105
+ function equal(held, value, owner) {
106
+ if (held.kind === 'present' || Array.isArray(held.value))
107
+ return undefined;
108
+ const expected = wanted(value, owner);
109
+ if (typeof expected !== typeof held.value)
110
+ return undefined;
111
+ return expected === held.value;
112
+ }
113
+ function ordered(held, value, compare) {
114
+ if (held.kind !== 'number' && held.kind !== 'date')
115
+ return undefined;
116
+ if (Array.isArray(held.value))
117
+ return undefined;
118
+ if (held.kind === 'number') {
119
+ if (typeof value !== 'number' || typeof held.value !== 'number')
120
+ return undefined;
121
+ return compare(Math.sign(held.value - value));
122
+ }
123
+ if (typeof value !== 'string' || !DATE.test(value) || typeof held.value !== 'string')
124
+ return undefined;
125
+ return compare(held.value < value ? -1 : held.value > value ? 1 : 0);
126
+ }
127
+ function anyOf(truths) {
128
+ if (truths.some((truth) => truth === true))
129
+ return true;
130
+ return truths.some((truth) => truth === undefined) ? undefined : false;
131
+ }
132
+ function allOf(truths) {
133
+ if (truths.some((truth) => truth === false))
134
+ return false;
135
+ return truths.some((truth) => truth === undefined) ? undefined : true;
136
+ }
137
+ function leaf(test, held, owner) {
138
+ if (held?.kind === 'unreadable')
139
+ return undefined;
140
+ if ('exists' in test)
141
+ return (held !== undefined) === test.exists;
142
+ if (held === undefined)
143
+ return undefined;
144
+ if ('eq' in test)
145
+ return equal(held, test.eq, owner);
146
+ if ('in' in test)
147
+ return anyOf(test.in.map((value) => equal(held, value, owner)));
148
+ if ('contains' in test) {
149
+ if (held.kind === 'present' || !Array.isArray(held.value))
150
+ return undefined;
151
+ const expected = wanted(test.contains, owner);
152
+ if (held.value.some((item) => item === expected))
153
+ return true;
154
+ return held.value.every((item) => typeof item === typeof expected) ? false : undefined;
155
+ }
156
+ if ('prefix' in test) {
157
+ if (held.kind === 'present' || typeof held.value !== 'string')
158
+ return undefined;
159
+ if (held.kind === 'number' || held.kind === 'reference' || held.kind === 'member')
160
+ return undefined;
161
+ return held.value.startsWith(test.prefix);
162
+ }
163
+ if ('gt' in test)
164
+ return ordered(held, test.gt, (sign) => sign > 0);
165
+ if ('gte' in test)
166
+ return ordered(held, test.gte, (sign) => sign >= 0);
167
+ if ('lt' in test)
168
+ return ordered(held, test.lt, (sign) => sign < 0);
169
+ return ordered(held, test.lte, (sign) => sign <= 0);
170
+ }
171
+ function evaluated(test, read, owner) {
172
+ if ('all' in test)
173
+ return allOf(test.all.map((part) => evaluated(part, read, owner)));
174
+ if ('any' in test)
175
+ return anyOf(test.any.map((part) => evaluated(part, read, owner)));
176
+ if ('not' in test) {
177
+ const truth = evaluated(test.not, read, owner);
178
+ return truth === undefined ? undefined : !truth;
179
+ }
180
+ return leaf(test, read(test.path), owner);
181
+ }
182
+ export function holds(test, document, owner) {
183
+ return evaluated(test, (path) => readDocument(document, path), owner);
184
+ }
185
+ function inScope(scope, document) {
186
+ if (document === null)
187
+ return false;
188
+ if ('type' in scope)
189
+ return document.type === scope.type;
190
+ if ('document' in scope)
191
+ return document.id === scope.document;
192
+ return scope.folder === '/' || document.path.startsWith(`${scope.folder}/`);
193
+ }
194
+ function matched(condition, test, document, owner) {
195
+ if (!inScope(condition.scope, document))
196
+ return false;
197
+ return test === undefined || holds(test, document, owner) === true;
198
+ }
199
+ function sameFact(left, right) {
200
+ return JSON.stringify(left) === JSON.stringify(right);
201
+ }
202
+ function among(values, document, field, owner) {
203
+ return holds({ path: field, in: values }, document, owner) === true;
204
+ }
205
+ function fieldChanged(condition, event, owner) {
206
+ const { field, from, to } = condition;
207
+ if (from === undefined && to === undefined && event.changed.includes(field))
208
+ return true;
209
+ if (!field.startsWith('/fields/'))
210
+ return false;
211
+ const name = field.slice('/fields/'.length);
212
+ const before = event.before?.fields[name];
213
+ const after = event.after?.fields[name];
214
+ if (before === undefined && after === undefined)
215
+ return false;
216
+ if (event.before !== null && event.after !== null && sameFact(before, after))
217
+ return false;
218
+ if (from === 'new'
219
+ ? event.before !== null
220
+ : from !== undefined && (event.before === null || !among(from, event.before, field, owner)))
221
+ return false;
222
+ if (to === 'deleted'
223
+ ? event.after !== null
224
+ : to !== undefined && (event.after === null || !among(to, event.after, field, owner)))
225
+ return false;
226
+ return true;
227
+ }
228
+ export function fires(condition, event, owner) {
229
+ if (condition.by !== undefined &&
230
+ evaluated(condition.by, (path) => readActor(event.by, path), owner) !== true)
231
+ return false;
232
+ if (condition.mode === 'starts_matching') {
233
+ if (event.before === null && !condition.new_documents)
234
+ return false;
235
+ return (matched(condition, condition.match, event.after, owner) &&
236
+ !matched(condition, condition.match, event.before, owner));
237
+ }
238
+ const side = event.after ?? event.before;
239
+ return matched(condition, condition.match, side, owner) && fieldChanged(condition, event, owner);
240
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { facts, fires, holds, WRITE_DOORS } from './condition.js';
2
+ export type { Actor, Condition, ConditionScope, ConditionTest, ConditionValue, DocumentEvent, DocumentFacts, Fact, Resolved, WriteDoor, } from './condition.js';
1
3
  export { divide } from './divide.js';
2
4
  export { apply, links, parse, serialize } from './document.js';
3
5
  export { MEMBER_FIELD, RECEIVED_FIELD, SITE_FIELD } from './fields.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1E,YAAY,EACV,WAAW,EACX,MAAM,EACN,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,IAAI,EACJ,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,OAAO,EACP,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EACV,KAAK,EACL,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1E,YAAY,EACV,WAAW,EACX,MAAM,EACN,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,IAAI,EACJ,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,OAAO,EACP,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export { facts, fires, holds, WRITE_DOORS } from './condition.js';
1
2
  export { divide } from './divide.js';
2
3
  export { apply, links, parse, serialize } from './document.js';
3
4
  export { MEMBER_FIELD, RECEIVED_FIELD, SITE_FIELD } from './fields.js';
package/dist/schema.d.ts CHANGED
@@ -3,5 +3,6 @@ export declare function validateFields(fields: Readonly<Record<string, FieldSpec
3
3
  field: string;
4
4
  rule: 'required-field' | 'field-enum' | 'field-kind';
5
5
  } | undefined;
6
+ export declare function fitsValue(spec: ScalarSpec, value: unknown): boolean;
6
7
  export declare function fitsKind(spec: ScalarSpec, text: string): boolean;
7
8
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAoB7D,wBAAgB,cAAc,CAC5B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAC3C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,GAAG,YAAY,CAAA;CAAE,GAAG,SAAS,CAUrF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGhE"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAoB7D,wBAAgB,cAAc,CAC5B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAC3C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,GAAG,YAAY,CAAA;CAAE,GAAG,SAAS,CAUrF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAEnE;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE"}
package/dist/schema.js CHANGED
@@ -31,7 +31,9 @@ export function validateFields(fields, values) {
31
31
  }
32
32
  return undefined;
33
33
  }
34
- export function fitsKind(spec, text) {
35
- const value = spec.kind === 'number' ? interpretPlain(text) : text;
34
+ export function fitsValue(spec, value) {
36
35
  return new Validator(scalarSchema(spec), '2020-12', false).validate(value).valid;
37
36
  }
37
+ export function fitsKind(spec, text) {
38
+ return fitsValue(spec, spec.kind === 'number' ? interpretPlain(text) : text);
39
+ }
@@ -1,4 +1,6 @@
1
+ import { type Definition, type FieldSpec } from './definition.js';
1
2
  import type { Library, ModelVerification, Validation, ValidationContext, VerifiedModel } from './types.js';
2
3
  export declare function verify(schema: string): ModelVerification;
4
+ export declare function declaredFields(definition: Definition): Readonly<Record<string, FieldSpec>>;
3
5
  export declare function validate(library: Library, context?: ValidationContext, model?: VerifiedModel): Validation;
4
6
  //# sourceMappingURL=validate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,OAAO,EACP,iBAAiB,EAEjB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,YAAY,CAAC;AAsEpB,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAQxD;AAQD,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,EAClD,KAAK,GAAE,aAA6B,GACnC,UAAU,CAuHZ"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQ9E,OAAO,KAAK,EAGV,OAAO,EACP,iBAAiB,EAEjB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,YAAY,CAAC;AAsEpB,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAQxD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAI1F;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,EAClD,KAAK,GAAE,aAA6B,GACnC,UAAU,CAuHZ"}
package/dist/validate.js CHANGED
@@ -65,7 +65,7 @@ export function verify(schema) {
65
65
  ...(read.location === undefined ? {} : { location: read.location }),
66
66
  };
67
67
  }
68
- function declaredFields(definition) {
68
+ export function declaredFields(definition) {
69
69
  if (!definition.memberDocument || Object.hasOwn(definition.fields, MEMBER_FIELD))
70
70
  return definition.fields;
71
71
  return { ...definition.fields, [MEMBER_FIELD]: MEMBER_SPEC };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/mdmodel",
3
- "version": "0.1.0-c83456e1cebfb",
3
+ "version": "0.1.0-cf72583e19192",
4
4
  "description": "MD Type language, parser, validator, structured change application, Markdown syntax profile, and conformance fixtures",
5
5
  "license": "MIT",
6
6
  "type": "module",