@mica-js/document 0.0.0-stage → 0.1.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.
@@ -0,0 +1,154 @@
1
+ //#region src/topic/delivery.ts
2
+ /**
3
+ * Delivery semantics of one topic port (RFC 0017).
4
+ *
5
+ * `level` treats the payload as the current value of the port, so only the last delivery of a step
6
+ * takes effect; `message` treats every publish as one record that must all arrive in order.
7
+ */
8
+ var DELIVERY_KINDS = ["level", "message"];
9
+ /** Pending `message` records a port accepts before it starts rejecting with backpressure. */
10
+ var DEFAULT_TOPIC_CAPACITY = 64;
11
+ /** Resolves a written `delivery` value, or `undefined` when it is not one of the two kinds. */
12
+ function parseDeliveryKind(value) {
13
+ return DELIVERY_KINDS.includes(value) ? value : void 0;
14
+ }
15
+ var DEFAULT_DELIVERY = {
16
+ boolean: "level",
17
+ number: "level",
18
+ vec2d: "level",
19
+ vec3d: "level",
20
+ string: "message",
21
+ bytes: "message",
22
+ "bytes<rgb565>": "message",
23
+ "bytes<segments>": "message"
24
+ };
25
+ /** Delivery a port gets when it omits the optional `delivery` field (RFC 0017 default table). */
26
+ function defaultDelivery(type) {
27
+ return DEFAULT_DELIVERY[type];
28
+ }
29
+ /**
30
+ * Declared delivery wins; the payload type decides when the port leaves it out.
31
+ *
32
+ * `declared` is `unknown` on purpose: the value arrives from a written descriptor, so an
33
+ * unparsable value falls back to the default instead of failing here. Validating the written value
34
+ * belongs to the loader that reads the descriptor.
35
+ */
36
+ function resolveDelivery(declared, type) {
37
+ return parseDeliveryKind(declared) ?? defaultDelivery(type);
38
+ }
39
+ /**
40
+ * Per-port delivery queue of RFC 0017.
41
+ *
42
+ * A step posts what the previous step published; the receiver reads it once, then `endStep()`
43
+ * drops the step's records. `level` keeps only the newest record and remembers the effective value
44
+ * across steps, `message` keeps every record in publish order and reports backpressure instead of
45
+ * growing past `capacity`.
46
+ */
47
+ var TopicInbox = class {
48
+ #delivery;
49
+ #capacity;
50
+ #port;
51
+ #onDiagnostic;
52
+ #pending = [];
53
+ #current;
54
+ #read;
55
+ #mixedReported = false;
56
+ constructor(options) {
57
+ this.#delivery = options.delivery;
58
+ this.#capacity = options.capacity ?? 64;
59
+ this.#port = options.port;
60
+ this.#onDiagnostic = options.onDiagnostic;
61
+ }
62
+ get delivery() {
63
+ return this.#delivery;
64
+ }
65
+ get capacity() {
66
+ return this.#capacity;
67
+ }
68
+ /** Records waiting for the current step. */
69
+ get pending() {
70
+ return this.#pending.length;
71
+ }
72
+ /** Effective value of a `level` port, including steps that received nothing. */
73
+ get current() {
74
+ return this.#current?.payload;
75
+ }
76
+ /**
77
+ * Accepts one record.
78
+ *
79
+ * Returns `false` when a `message` port is at capacity: the record is rejected and reported, the
80
+ * records already accepted stay untouched.
81
+ */
82
+ post(envelope) {
83
+ if (this.#delivery === "level") this.#pending.length = 0;
84
+ else if (this.#pending.length >= this.#capacity) {
85
+ this.#report("topic/backpressure", `Port ${JSON.stringify(this.#port ?? "")} is at its ${this.#capacity}-record capacity; a payload was rejected.`);
86
+ return false;
87
+ }
88
+ this.#pending.push(envelope);
89
+ if (this.#delivery === "level") this.#current = envelope;
90
+ return true;
91
+ }
92
+ /** Payload the port received in this step, or `undefined` when the step was silent. */
93
+ takeInput() {
94
+ this.#markRead("input");
95
+ return this.#pending[this.#pending.length - 1]?.payload;
96
+ }
97
+ /** Every record the port received in this step, in publish order. */
98
+ takeInputs() {
99
+ this.#markRead("inputs");
100
+ return this.#pending.slice();
101
+ }
102
+ /**
103
+ * Ends the step: drops the records it carried and forgets which read method it used.
104
+ *
105
+ * A `level` value stays available through {@link current}, because the effective value outlives
106
+ * the step that set it.
107
+ */
108
+ endStep() {
109
+ this.#pending.length = 0;
110
+ this.#read = void 0;
111
+ }
112
+ /** RFC 0017 asks for a diagnostic when one port reads with both methods. */
113
+ #markRead(read) {
114
+ if (this.#read !== void 0 && this.#read !== read && !this.#mixedReported) {
115
+ this.#mixedReported = true;
116
+ this.#report("topic/mixed-read", `Port ${JSON.stringify(this.#port ?? "")} mixes takeInput and takeInputs; a port must use one of them.`);
117
+ }
118
+ this.#read = read;
119
+ }
120
+ #report(code, message) {
121
+ try {
122
+ this.#onDiagnostic?.({
123
+ code,
124
+ message,
125
+ ...this.#port === void 0 ? {} : { port: this.#port }
126
+ });
127
+ } catch {}
128
+ }
129
+ };
130
+ //#endregion
131
+ //#region src/format/type-name.ts
132
+ /** Payload type names of the Mica value model (see #10). */
133
+ var PAYLOAD_TYPES = [
134
+ "boolean",
135
+ "number",
136
+ "string",
137
+ "vec2d",
138
+ "vec3d",
139
+ "bytes",
140
+ "bytes<rgb565>",
141
+ "bytes<segments>"
142
+ ];
143
+ /** Resolves a written payload type name, or `undefined` when it names no known type. */
144
+ function parsePayloadType(value) {
145
+ return PAYLOAD_TYPES.includes(value) ? value : void 0;
146
+ }
147
+ /** Payload types are nominal for now: only an exact match is assignable. */
148
+ function isAssignable(from, to) {
149
+ return from === to;
150
+ }
151
+ //#endregion
152
+ export { DELIVERY_KINDS as a, parseDeliveryKind as c, DEFAULT_TOPIC_CAPACITY as i, resolveDelivery as l, isAssignable as n, TopicInbox as o, parsePayloadType as r, defaultDelivery as s, PAYLOAD_TYPES as t };
153
+
154
+ //# sourceMappingURL=type-name-B6Vkwj77.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-name-B6Vkwj77.js","names":[],"sources":["../src/topic/delivery.ts","../src/format/type-name.ts"],"sourcesContent":["import type { TimePs } from '@mica-js/core';\nimport type { PayloadType } from '../format/type-name';\n\n/**\n * Delivery semantics of one topic port (RFC 0017).\n *\n * `level` treats the payload as the current value of the port, so only the last delivery of a step\n * takes effect; `message` treats every publish as one record that must all arrive in order.\n */\nexport const DELIVERY_KINDS = ['level', 'message'] as const;\n\nexport type DeliveryKind = (typeof DELIVERY_KINDS)[number];\n\n/** Pending `message` records a port accepts before it starts rejecting with backpressure. */\nexport const DEFAULT_TOPIC_CAPACITY = 64;\n\n/** Resolves a written `delivery` value, or `undefined` when it is not one of the two kinds. */\nexport function parseDeliveryKind(value: unknown): DeliveryKind | undefined {\n return (DELIVERY_KINDS as readonly unknown[]).includes(value)\n ? (value as DeliveryKind)\n : undefined;\n}\n\nconst DEFAULT_DELIVERY: Readonly<Record<PayloadType, DeliveryKind>> = {\n boolean: 'level',\n number: 'level',\n vec2d: 'level',\n vec3d: 'level',\n string: 'message',\n bytes: 'message',\n 'bytes<rgb565>': 'message',\n 'bytes<segments>': 'message',\n};\n\n/** Delivery a port gets when it omits the optional `delivery` field (RFC 0017 default table). */\nexport function defaultDelivery(type: PayloadType): DeliveryKind {\n return DEFAULT_DELIVERY[type];\n}\n\n/**\n * Declared delivery wins; the payload type decides when the port leaves it out.\n *\n * `declared` is `unknown` on purpose: the value arrives from a written descriptor, so an\n * unparsable value falls back to the default instead of failing here. Validating the written value\n * belongs to the loader that reads the descriptor.\n */\nexport function resolveDelivery(declared: unknown, type: PayloadType): DeliveryKind {\n return parseDeliveryKind(declared) ?? defaultDelivery(type);\n}\n\n/** One payload on its way to a port, with the virtual time it was published at (RFC 0017). */\nexport interface TopicEnvelope<T = unknown> {\n readonly payload: T;\n /** Publication time; `flushOutputs` publishes use the end of the step they ran in. */\n readonly simTime: TimePs;\n}\n\nexport type TopicDeliveryDiagnosticCode = 'topic/backpressure' | 'topic/mixed-read';\n\n/** A violation RFC 0017 reports instead of aborting the simulation. */\nexport interface TopicDeliveryDiagnostic {\n readonly code: TopicDeliveryDiagnosticCode;\n readonly message: string;\n readonly port?: string;\n}\n\nexport interface TopicInboxOptions {\n readonly delivery: DeliveryKind;\n /** Deepest pending queue a `message` port accepts; `level` ports always hold one value. */\n readonly capacity?: number;\n /** Port name, echoed in diagnostics so a receiver can attribute them. */\n readonly port?: string;\n readonly onDiagnostic?: (diagnostic: TopicDeliveryDiagnostic) => void;\n}\n\n/**\n * Per-port delivery queue of RFC 0017.\n *\n * A step posts what the previous step published; the receiver reads it once, then `endStep()`\n * drops the step's records. `level` keeps only the newest record and remembers the effective value\n * across steps, `message` keeps every record in publish order and reports backpressure instead of\n * growing past `capacity`.\n */\nexport class TopicInbox<T = unknown> {\n readonly #delivery: DeliveryKind;\n readonly #capacity: number;\n readonly #port: string | undefined;\n readonly #onDiagnostic: ((diagnostic: TopicDeliveryDiagnostic) => void) | undefined;\n readonly #pending: TopicEnvelope<T>[] = [];\n #current: TopicEnvelope<T> | undefined;\n #read: 'input' | 'inputs' | undefined;\n #mixedReported = false;\n\n constructor(options: TopicInboxOptions) {\n this.#delivery = options.delivery;\n this.#capacity = options.capacity ?? DEFAULT_TOPIC_CAPACITY;\n this.#port = options.port;\n this.#onDiagnostic = options.onDiagnostic;\n }\n\n get delivery(): DeliveryKind {\n return this.#delivery;\n }\n\n get capacity(): number {\n return this.#capacity;\n }\n\n /** Records waiting for the current step. */\n get pending(): number {\n return this.#pending.length;\n }\n\n /** Effective value of a `level` port, including steps that received nothing. */\n get current(): T | undefined {\n return this.#current?.payload;\n }\n\n /**\n * Accepts one record.\n *\n * Returns `false` when a `message` port is at capacity: the record is rejected and reported, the\n * records already accepted stay untouched.\n */\n post(envelope: TopicEnvelope<T>): boolean {\n if (this.#delivery === 'level') {\n this.#pending.length = 0;\n } else if (this.#pending.length >= this.#capacity) {\n this.#report(\n 'topic/backpressure',\n `Port ${JSON.stringify(this.#port ?? '')} is at its ${this.#capacity}-record capacity; a payload was rejected.`,\n );\n return false;\n }\n this.#pending.push(envelope);\n if (this.#delivery === 'level') {\n this.#current = envelope;\n }\n return true;\n }\n\n /** Payload the port received in this step, or `undefined` when the step was silent. */\n takeInput(): T | undefined {\n this.#markRead('input');\n return this.#pending[this.#pending.length - 1]?.payload;\n }\n\n /** Every record the port received in this step, in publish order. */\n takeInputs(): readonly TopicEnvelope<T>[] {\n this.#markRead('inputs');\n return this.#pending.slice();\n }\n\n /**\n * Ends the step: drops the records it carried and forgets which read method it used.\n *\n * A `level` value stays available through {@link current}, because the effective value outlives\n * the step that set it.\n */\n endStep(): void {\n this.#pending.length = 0;\n this.#read = undefined;\n }\n\n /** RFC 0017 asks for a diagnostic when one port reads with both methods. */\n #markRead(read: 'input' | 'inputs'): void {\n if (this.#read !== undefined && this.#read !== read && !this.#mixedReported) {\n this.#mixedReported = true;\n this.#report(\n 'topic/mixed-read',\n `Port ${JSON.stringify(this.#port ?? '')} mixes takeInput and takeInputs; a port must use one of them.`,\n );\n }\n this.#read = read;\n }\n\n #report(code: TopicDeliveryDiagnosticCode, message: string): void {\n try {\n this.#onDiagnostic?.({\n code,\n message,\n ...(this.#port === undefined ? {} : { port: this.#port }),\n });\n } catch {\n // A throwing diagnostic sink must not break the delivery contract.\n }\n }\n}\n","/** Payload type names of the Mica value model (see #10). */\nexport const PAYLOAD_TYPES = [\n 'boolean',\n 'number',\n 'string',\n 'vec2d',\n 'vec3d',\n 'bytes',\n 'bytes<rgb565>',\n 'bytes<segments>',\n] as const;\n\nexport type PayloadType = (typeof PAYLOAD_TYPES)[number];\n\n/** Resolves a written payload type name, or `undefined` when it names no known type. */\nexport function parsePayloadType(value: string): PayloadType | undefined {\n return (PAYLOAD_TYPES as readonly string[]).includes(value) ? (value as PayloadType) : undefined;\n}\n\n/** Payload types are nominal for now: only an exact match is assignable. */\nexport function isAssignable(from: PayloadType, to: PayloadType): boolean {\n return from === to;\n}\n"],"mappings":";;;;;;;AASA,IAAa,iBAAiB,CAAC,SAAS,SAAS;;AAKjD,IAAa,yBAAyB;;AAGtC,SAAgB,kBAAkB,OAA0C;CAC1E,OAAQ,eAAsC,SAAS,KAAK,IACvD,QACD,KAAA;AACN;AAEA,IAAM,mBAAgE;CACpE,SAAS;CACT,QAAQ;CACR,OAAO;CACP,OAAO;CACP,QAAQ;CACR,OAAO;CACP,iBAAiB;CACjB,mBAAmB;AACrB;;AAGA,SAAgB,gBAAgB,MAAiC;CAC/D,OAAO,iBAAiB;AAC1B;;;;;;;;AASA,SAAgB,gBAAgB,UAAmB,MAAiC;CAClF,OAAO,kBAAkB,QAAQ,KAAK,gBAAgB,IAAI;AAC5D;;;;;;;;;AAmCA,IAAa,aAAb,MAAqC;CACnC;CACA;CACA;CACA;CACA,WAAwC,CAAC;CACzC;CACA;CACA,iBAAiB;CAEjB,YAAY,SAA4B;EACtC,KAAK,YAAY,QAAQ;EACzB,KAAK,YAAY,QAAQ,YAAA;EACzB,KAAK,QAAQ,QAAQ;EACrB,KAAK,gBAAgB,QAAQ;CAC/B;CAEA,IAAI,WAAyB;EAC3B,OAAO,KAAK;CACd;CAEA,IAAI,WAAmB;EACrB,OAAO,KAAK;CACd;;CAGA,IAAI,UAAkB;EACpB,OAAO,KAAK,SAAS;CACvB;;CAGA,IAAI,UAAyB;EAC3B,OAAO,KAAK,UAAU;CACxB;;;;;;;CAQA,KAAK,UAAqC;EACxC,IAAI,KAAK,cAAc,SACrB,KAAK,SAAS,SAAS;OAClB,IAAI,KAAK,SAAS,UAAU,KAAK,WAAW;GACjD,KAAK,QACH,sBACA,QAAQ,KAAK,UAAU,KAAK,SAAS,EAAE,EAAE,aAAa,KAAK,UAAU,0CACvE;GACA,OAAO;EACT;EACA,KAAK,SAAS,KAAK,QAAQ;EAC3B,IAAI,KAAK,cAAc,SACrB,KAAK,WAAW;EAElB,OAAO;CACT;;CAGA,YAA2B;EACzB,KAAK,UAAU,OAAO;EACtB,OAAO,KAAK,SAAS,KAAK,SAAS,SAAS,EAAE,EAAE;CAClD;;CAGA,aAA0C;EACxC,KAAK,UAAU,QAAQ;EACvB,OAAO,KAAK,SAAS,MAAM;CAC7B;;;;;;;CAQA,UAAgB;EACd,KAAK,SAAS,SAAS;EACvB,KAAK,QAAQ,KAAA;CACf;;CAGA,UAAU,MAAgC;EACxC,IAAI,KAAK,UAAU,KAAA,KAAa,KAAK,UAAU,QAAQ,CAAC,KAAK,gBAAgB;GAC3E,KAAK,iBAAiB;GACtB,KAAK,QACH,oBACA,QAAQ,KAAK,UAAU,KAAK,SAAS,EAAE,EAAE,8DAC3C;EACF;EACA,KAAK,QAAQ;CACf;CAEA,QAAQ,MAAmC,SAAuB;EAChE,IAAI;GACF,KAAK,gBAAgB;IACnB;IACA;IACA,GAAI,KAAK,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;GACzD,CAAC;EACH,QAAQ,CAER;CACF;AACF;;;;AC1LA,IAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAKA,SAAgB,iBAAiB,OAAwC;CACvE,OAAQ,cAAoC,SAAS,KAAK,IAAK,QAAwB,KAAA;AACzF;;AAGA,SAAgB,aAAa,MAAmB,IAA0B;CACxE,OAAO,SAAS;AAClB"}
@@ -0,0 +1,232 @@
1
+ import { a as assetSrcError, s as isAssetMode } from "./errors-7cnIjhnV.js";
2
+ //#region src/format/input.ts
3
+ /** Strings are parsed as JSON text; any other value is validated as-is. */
4
+ function parseInput(input, diagnostics) {
5
+ if (typeof input !== "string") return {
6
+ ok: true,
7
+ value: input
8
+ };
9
+ try {
10
+ return {
11
+ ok: true,
12
+ value: JSON.parse(input)
13
+ };
14
+ } catch (error) {
15
+ const detail = error instanceof Error ? error.message : String(error);
16
+ diagnostics.push({
17
+ severity: "error",
18
+ code: "json/invalid",
19
+ message: `Invalid JSON: ${detail}`
20
+ });
21
+ return {
22
+ ok: false,
23
+ value: void 0
24
+ };
25
+ }
26
+ }
27
+ //#endregion
28
+ //#region src/format/uuid.ts
29
+ var UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
30
+ /** Strict UUID v4 check: 8-4-4-4-12 hex with the version and variant bits fixed. */
31
+ function isUuidV4(value) {
32
+ return UUID_V4.test(value);
33
+ }
34
+ //#endregion
35
+ //#region src/format/validate.ts
36
+ function toPointer(path) {
37
+ if (path.length === 0) return "";
38
+ return `/${path.map((segment) => segment.replace(/~/g, "~0").replace(/\//g, "~1")).join("/")}`;
39
+ }
40
+ function isRecord(value) {
41
+ return typeof value === "object" && value !== null && !Array.isArray(value);
42
+ }
43
+ function hasErrors(diagnostics) {
44
+ return diagnostics.some((diagnostic) => diagnostic.severity === "error");
45
+ }
46
+ function report(diagnostics, code, message, path, entity) {
47
+ const diagnostic = {
48
+ severity: "error",
49
+ code,
50
+ message,
51
+ pointer: toPointer(path)
52
+ };
53
+ diagnostics.push(entity === void 0 ? diagnostic : {
54
+ ...diagnostic,
55
+ entity
56
+ });
57
+ }
58
+ function forbidUnknownFields(value, allowed, path, diagnostics) {
59
+ for (const key of Object.keys(value)) if (!allowed.includes(key)) report(diagnostics, "schema/unknown-field", `Unknown field "${key}".`, [...path, key]);
60
+ }
61
+ function readStringField(value, key, path, diagnostics, options = {}) {
62
+ const fieldPath = [...path, key];
63
+ if (!Object.prototype.hasOwnProperty.call(value, key)) {
64
+ report(diagnostics, "schema/missing-field", `Missing required field "${key}".`, fieldPath);
65
+ return;
66
+ }
67
+ const field = value[key];
68
+ if (typeof field !== "string") {
69
+ report(diagnostics, "schema/invalid-type", `Field "${key}" must be a string.`, fieldPath);
70
+ return;
71
+ }
72
+ if (options.nonEmpty === true && field.length === 0) {
73
+ report(diagnostics, "schema/invalid-value", `Field "${key}" must not be empty.`, fieldPath);
74
+ return;
75
+ }
76
+ return field;
77
+ }
78
+ function readNumberField(value, key, path, diagnostics) {
79
+ const fieldPath = [...path, key];
80
+ if (!Object.prototype.hasOwnProperty.call(value, key)) {
81
+ report(diagnostics, "schema/missing-field", `Missing required field "${key}".`, fieldPath);
82
+ return;
83
+ }
84
+ const field = value[key];
85
+ if (typeof field !== "number") {
86
+ report(diagnostics, "schema/invalid-type", `Field "${key}" must be a number.`, fieldPath);
87
+ return;
88
+ }
89
+ if (!Number.isFinite(field)) {
90
+ report(diagnostics, "schema/invalid-value", `Field "${key}" must be a finite number.`, fieldPath);
91
+ return;
92
+ }
93
+ return field;
94
+ }
95
+ function readIntegerField(value, key, path, diagnostics) {
96
+ const field = readNumberField(value, key, path, diagnostics);
97
+ if (field === void 0) return;
98
+ if (!Number.isInteger(field)) {
99
+ report(diagnostics, "schema/invalid-value", `Field "${key}" must be an integer.`, [...path, key]);
100
+ return;
101
+ }
102
+ return field;
103
+ }
104
+ function readArrayField(value, key, path, diagnostics) {
105
+ const fieldPath = [...path, key];
106
+ if (!Object.prototype.hasOwnProperty.call(value, key)) {
107
+ report(diagnostics, "schema/missing-field", `Missing required field "${key}".`, fieldPath);
108
+ return;
109
+ }
110
+ const field = value[key];
111
+ if (!Array.isArray(field)) {
112
+ report(diagnostics, "schema/invalid-type", `Field "${key}" must be an array.`, fieldPath);
113
+ return;
114
+ }
115
+ return field;
116
+ }
117
+ function readObjectField(value, key, path, diagnostics) {
118
+ const fieldPath = [...path, key];
119
+ if (!Object.prototype.hasOwnProperty.call(value, key)) {
120
+ report(diagnostics, "schema/missing-field", `Missing required field "${key}".`, fieldPath);
121
+ return;
122
+ }
123
+ const field = value[key];
124
+ if (!isRecord(field)) {
125
+ report(diagnostics, "schema/invalid-type", `Field "${key}" must be an object.`, fieldPath);
126
+ return;
127
+ }
128
+ return field;
129
+ }
130
+ function readPoint(value, path, diagnostics) {
131
+ if (!isRecord(value)) {
132
+ report(diagnostics, "schema/invalid-type", "Point must be an object.", path);
133
+ return;
134
+ }
135
+ forbidUnknownFields(value, ["x", "y"], path, diagnostics);
136
+ const x = readNumberField(value, "x", path, diagnostics);
137
+ const y = readNumberField(value, "y", path, diagnostics);
138
+ if (x === void 0 || y === void 0) return;
139
+ return {
140
+ x,
141
+ y
142
+ };
143
+ }
144
+ /**
145
+ * Reads an `image` / `binary` property value: a resource reference `{ "src", "mode" }` (#7).
146
+ * `src` is checked against the rules of its mode; content itself lives outside the document.
147
+ */
148
+ function readAssetReference(value, path, diagnostics) {
149
+ if (!isRecord(value)) {
150
+ report(diagnostics, "schema/invalid-type", "Resource reference must be an object.", path);
151
+ return;
152
+ }
153
+ forbidUnknownFields(value, ["src", "mode"], path, diagnostics);
154
+ const src = readStringField(value, "src", path, diagnostics, { nonEmpty: true });
155
+ let mode;
156
+ if (!Object.prototype.hasOwnProperty.call(value, "mode")) report(diagnostics, "schema/missing-field", "Missing required field \"mode\".", [...path, "mode"]);
157
+ else if (isAssetMode(value["mode"])) mode = value["mode"];
158
+ else report(diagnostics, "schema/invalid-value", "Field \"mode\" must be \"file\", \"inline\" or \"store\".", [...path, "mode"]);
159
+ if (src === void 0 || mode === void 0) return;
160
+ const srcError = assetSrcError(mode, src);
161
+ if (srcError !== void 0) {
162
+ report(diagnostics, "schema/invalid-value", `Field "src" ${srcError}.`, [...path, "src"]);
163
+ return;
164
+ }
165
+ return {
166
+ src,
167
+ mode
168
+ };
169
+ }
170
+ /** Reads an optional `properties` map of scalars, resource references and explicit nulls (#6). */
171
+ function readProperties(value, path, diagnostics) {
172
+ if (!isRecord(value)) {
173
+ report(diagnostics, "schema/invalid-type", "Field \"properties\" must be an object.", path);
174
+ return;
175
+ }
176
+ const properties = Object.create(null);
177
+ let failed = false;
178
+ for (const [key, entry] of Object.entries(value)) {
179
+ if (key.length === 0) {
180
+ report(diagnostics, "schema/invalid-value", "Property keys must not be empty.", path);
181
+ failed = true;
182
+ continue;
183
+ }
184
+ const entryPath = [...path, key];
185
+ if (typeof entry === "string" || typeof entry === "boolean") {
186
+ properties[key] = entry;
187
+ continue;
188
+ }
189
+ if (entry === null) {
190
+ properties[key] = null;
191
+ continue;
192
+ }
193
+ if (typeof entry === "number") {
194
+ if (!Number.isFinite(entry)) {
195
+ report(diagnostics, "schema/invalid-value", `Property "${key}" must be a finite number.`, entryPath);
196
+ failed = true;
197
+ continue;
198
+ }
199
+ properties[key] = entry;
200
+ continue;
201
+ }
202
+ if (typeof entry === "object" && !Array.isArray(entry)) {
203
+ const reference = readAssetReference(entry, entryPath, diagnostics);
204
+ if (reference === void 0) {
205
+ failed = true;
206
+ continue;
207
+ }
208
+ properties[key] = reference;
209
+ continue;
210
+ }
211
+ report(diagnostics, "schema/invalid-value", `Property "${key}" must be a string, finite number, boolean, resource reference or null.`, entryPath);
212
+ failed = true;
213
+ }
214
+ return failed ? void 0 : properties;
215
+ }
216
+ function checkDuplicateIds(entries, kind, diagnostics) {
217
+ const seen = /* @__PURE__ */ new Set();
218
+ for (const entry of entries) {
219
+ if (seen.has(entry.id)) {
220
+ report(diagnostics, "id/duplicate", `Duplicate ${kind} id "${entry.id}".`, entry.path, {
221
+ kind,
222
+ id: entry.id
223
+ });
224
+ continue;
225
+ }
226
+ seen.add(entry.id);
227
+ }
228
+ }
229
+ //#endregion
230
+ export { readArrayField as a, readObjectField as c, readStringField as d, report as f, parseInput as h, isRecord as i, readPoint as l, isUuidV4 as m, forbidUnknownFields as n, readIntegerField as o, toPointer as p, hasErrors as r, readNumberField as s, checkDuplicateIds as t, readProperties as u };
231
+
232
+ //# sourceMappingURL=validate-Cz-ZbbEr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-Cz-ZbbEr.js","names":[],"sources":["../src/format/input.ts","../src/format/uuid.ts","../src/format/validate.ts"],"sourcesContent":["import type { Diagnostic } from './diagnostics';\n\nexport interface ParsedInput {\n readonly ok: boolean;\n readonly value: unknown;\n}\n\n/** Strings are parsed as JSON text; any other value is validated as-is. */\nexport function parseInput(input: string | unknown, diagnostics: Diagnostic[]): ParsedInput {\n if (typeof input !== 'string') {\n return { ok: true, value: input };\n }\n try {\n return { ok: true, value: JSON.parse(input) as unknown };\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n diagnostics.push({\n severity: 'error',\n code: 'json/invalid',\n message: `Invalid JSON: ${detail}`,\n });\n return { ok: false, value: undefined };\n }\n}\n","const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** Strict UUID v4 check: 8-4-4-4-12 hex with the version and variant bits fixed. */\nexport function isUuidV4(value: string): boolean {\n return UUID_V4.test(value);\n}\n","import type { Diagnostic, DiagnosticCode, DiagnosticEntity } from './diagnostics';\nimport type { AssetMode, AssetReference, Point, PropertyValue } from './value';\nimport { assetSrcError, isAssetMode } from './value';\n\nexport function toPointer(path: readonly string[]): string {\n if (path.length === 0) {\n return '';\n }\n const segments = path.map((segment) => segment.replace(/~/g, '~0').replace(/\\//g, '~1'));\n return `/${segments.join('/')}`;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function hasErrors(diagnostics: readonly Diagnostic[]): boolean {\n return diagnostics.some((diagnostic) => diagnostic.severity === 'error');\n}\n\nexport function report(\n diagnostics: Diagnostic[],\n code: DiagnosticCode,\n message: string,\n path: readonly string[],\n entity?: DiagnosticEntity,\n): void {\n const diagnostic: Diagnostic = {\n severity: 'error',\n code,\n message,\n pointer: toPointer(path),\n };\n diagnostics.push(entity === undefined ? diagnostic : { ...diagnostic, entity });\n}\n\nexport function forbidUnknownFields(\n value: Record<string, unknown>,\n allowed: readonly string[],\n path: readonly string[],\n diagnostics: Diagnostic[],\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.includes(key)) {\n report(diagnostics, 'schema/unknown-field', `Unknown field \"${key}\".`, [...path, key]);\n }\n }\n}\n\nexport interface StringFieldOptions {\n readonly nonEmpty?: boolean;\n}\n\nexport function readStringField(\n value: Record<string, unknown>,\n key: string,\n path: readonly string[],\n diagnostics: Diagnostic[],\n options: StringFieldOptions = {},\n): string | undefined {\n const fieldPath = [...path, key];\n if (!Object.prototype.hasOwnProperty.call(value, key)) {\n report(diagnostics, 'schema/missing-field', `Missing required field \"${key}\".`, fieldPath);\n return undefined;\n }\n const field = value[key];\n if (typeof field !== 'string') {\n report(diagnostics, 'schema/invalid-type', `Field \"${key}\" must be a string.`, fieldPath);\n return undefined;\n }\n if (options.nonEmpty === true && field.length === 0) {\n report(diagnostics, 'schema/invalid-value', `Field \"${key}\" must not be empty.`, fieldPath);\n return undefined;\n }\n return field;\n}\n\nexport function readNumberField(\n value: Record<string, unknown>,\n key: string,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): number | undefined {\n const fieldPath = [...path, key];\n if (!Object.prototype.hasOwnProperty.call(value, key)) {\n report(diagnostics, 'schema/missing-field', `Missing required field \"${key}\".`, fieldPath);\n return undefined;\n }\n const field = value[key];\n if (typeof field !== 'number') {\n report(diagnostics, 'schema/invalid-type', `Field \"${key}\" must be a number.`, fieldPath);\n return undefined;\n }\n if (!Number.isFinite(field)) {\n report(\n diagnostics,\n 'schema/invalid-value',\n `Field \"${key}\" must be a finite number.`,\n fieldPath,\n );\n return undefined;\n }\n return field;\n}\n\nexport function readIntegerField(\n value: Record<string, unknown>,\n key: string,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): number | undefined {\n const field = readNumberField(value, key, path, diagnostics);\n if (field === undefined) {\n return undefined;\n }\n if (!Number.isInteger(field)) {\n report(diagnostics, 'schema/invalid-value', `Field \"${key}\" must be an integer.`, [\n ...path,\n key,\n ]);\n return undefined;\n }\n return field;\n}\n\nexport function readArrayField(\n value: Record<string, unknown>,\n key: string,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): unknown[] | undefined {\n const fieldPath = [...path, key];\n if (!Object.prototype.hasOwnProperty.call(value, key)) {\n report(diagnostics, 'schema/missing-field', `Missing required field \"${key}\".`, fieldPath);\n return undefined;\n }\n const field = value[key];\n if (!Array.isArray(field)) {\n report(diagnostics, 'schema/invalid-type', `Field \"${key}\" must be an array.`, fieldPath);\n return undefined;\n }\n return field;\n}\n\nexport function readObjectField(\n value: Record<string, unknown>,\n key: string,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): Record<string, unknown> | undefined {\n const fieldPath = [...path, key];\n if (!Object.prototype.hasOwnProperty.call(value, key)) {\n report(diagnostics, 'schema/missing-field', `Missing required field \"${key}\".`, fieldPath);\n return undefined;\n }\n const field = value[key];\n if (!isRecord(field)) {\n report(diagnostics, 'schema/invalid-type', `Field \"${key}\" must be an object.`, fieldPath);\n return undefined;\n }\n return field;\n}\n\nexport function readPoint(\n value: unknown,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): Point | undefined {\n if (!isRecord(value)) {\n report(diagnostics, 'schema/invalid-type', 'Point must be an object.', path);\n return undefined;\n }\n forbidUnknownFields(value, ['x', 'y'], path, diagnostics);\n const x = readNumberField(value, 'x', path, diagnostics);\n const y = readNumberField(value, 'y', path, diagnostics);\n if (x === undefined || y === undefined) {\n return undefined;\n }\n return { x, y };\n}\n\nexport interface IdentifiedEntry {\n readonly id: string;\n readonly path: readonly string[];\n}\n\n/**\n * Reads an `image` / `binary` property value: a resource reference `{ \"src\", \"mode\" }` (#7).\n * `src` is checked against the rules of its mode; content itself lives outside the document.\n */\nexport function readAssetReference(\n value: unknown,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): AssetReference | undefined {\n if (!isRecord(value)) {\n report(diagnostics, 'schema/invalid-type', 'Resource reference must be an object.', path);\n return undefined;\n }\n forbidUnknownFields(value, ['src', 'mode'], path, diagnostics);\n const src = readStringField(value, 'src', path, diagnostics, { nonEmpty: true });\n let mode: AssetMode | undefined;\n if (!Object.prototype.hasOwnProperty.call(value, 'mode')) {\n report(diagnostics, 'schema/missing-field', 'Missing required field \"mode\".', [\n ...path,\n 'mode',\n ]);\n } else if (isAssetMode(value['mode'])) {\n mode = value['mode'];\n } else {\n report(\n diagnostics,\n 'schema/invalid-value',\n 'Field \"mode\" must be \"file\", \"inline\" or \"store\".',\n [...path, 'mode'],\n );\n }\n if (src === undefined || mode === undefined) {\n return undefined;\n }\n const srcError = assetSrcError(mode, src);\n if (srcError !== undefined) {\n report(diagnostics, 'schema/invalid-value', `Field \"src\" ${srcError}.`, [...path, 'src']);\n return undefined;\n }\n return { src, mode };\n}\n\n/** Reads an optional `properties` map of scalars, resource references and explicit nulls (#6). */\nexport function readProperties(\n value: unknown,\n path: readonly string[],\n diagnostics: Diagnostic[],\n): Record<string, PropertyValue> | undefined {\n if (!isRecord(value)) {\n report(diagnostics, 'schema/invalid-type', 'Field \"properties\" must be an object.', path);\n return undefined;\n }\n const properties: Record<string, PropertyValue> = Object.create(null);\n let failed = false;\n for (const [key, entry] of Object.entries(value)) {\n if (key.length === 0) {\n report(diagnostics, 'schema/invalid-value', 'Property keys must not be empty.', path);\n failed = true;\n continue;\n }\n const entryPath = [...path, key];\n if (typeof entry === 'string' || typeof entry === 'boolean') {\n properties[key] = entry;\n continue;\n }\n if (entry === null) {\n properties[key] = null;\n continue;\n }\n if (typeof entry === 'number') {\n if (!Number.isFinite(entry)) {\n report(\n diagnostics,\n 'schema/invalid-value',\n `Property \"${key}\" must be a finite number.`,\n entryPath,\n );\n failed = true;\n continue;\n }\n properties[key] = entry;\n continue;\n }\n if (typeof entry === 'object' && !Array.isArray(entry)) {\n const reference = readAssetReference(entry, entryPath, diagnostics);\n if (reference === undefined) {\n failed = true;\n continue;\n }\n properties[key] = reference;\n continue;\n }\n report(\n diagnostics,\n 'schema/invalid-value',\n `Property \"${key}\" must be a string, finite number, boolean, resource reference or null.`,\n entryPath,\n );\n failed = true;\n }\n return failed ? undefined : properties;\n}\n\nexport function checkDuplicateIds(\n entries: readonly IdentifiedEntry[],\n kind: DiagnosticEntity['kind'],\n diagnostics: Diagnostic[],\n): void {\n const seen = new Set<string>();\n for (const entry of entries) {\n if (seen.has(entry.id)) {\n report(diagnostics, 'id/duplicate', `Duplicate ${kind} id \"${entry.id}\".`, entry.path, {\n kind,\n id: entry.id,\n });\n continue;\n }\n seen.add(entry.id);\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,48 @@
1
1
  {
2
2
  "name": "@mica-js/document",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "description": "Mica document contracts: schematic and canvas formats, topic delivery and shared format models",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/x-botlab/mica-js.git",
9
+ "directory": "packages/document"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ },
18
+ "./schematic": {
19
+ "types": "./dist/schematic/index.d.ts",
20
+ "import": "./dist/schematic/index.js"
21
+ },
22
+ "./canvas": {
23
+ "types": "./dist/canvas/index.d.ts",
24
+ "import": "./dist/canvas/index.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "dependencies": {
34
+ "@mica-js/core": "0.6.0"
35
+ },
36
+ "devDependencies": {
37
+ "typescript": "^6.0.3",
38
+ "vite": "^8.3.4",
39
+ "vite-plugin-dts": "^5.1.2",
40
+ "vitest": "^5.0.5"
41
+ },
42
+ "scripts": {
43
+ "build": "vite build",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "typecheck": "tsc --noEmit"
47
+ }
6
48
  }