@dialecte/scl 0.3.16 → 0.3.17

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.
@@ -1,8 +1,10 @@
1
+ import { AssertValidSclTestCasesParams, AssertValidSclXmlOptions } from './assert-valid-scl-xml.types';
1
2
  /**
2
3
  * Assert a test XML string is valid SCL, structurally: every element's namespace matches its parent
3
4
  * context, every element is an allowed child of its parent, and every attribute is a known attribute of
4
- * its element. Elements/parents unknown to the schema are skipped (bespoke content under a transparent
5
- * `Private`, or dev-namespace scaffolding).
5
+ * its element. Elements unknown to the schema are skipped (bespoke content under a transparent
6
+ * `Private`), and so is any element in a namespace the SCL config does not declare — even when its
7
+ * local name collides with a schema element.
6
8
  *
7
9
  * `requireComplete` (default `true`) additionally requires every schema-required attribute to be
8
10
  * present. Minimal test fixtures legitimately omit these (e.g. a bare `<SCL>` without
@@ -12,7 +14,11 @@
12
14
  * NOT yet enforced (planned with the validation feature): attribute VALUE facets (uuid pattern, enums,
13
15
  * datatypes) and cross-element constraints (unique keys, keyref resolution).
14
16
  */
15
- export declare function assertValidSclXml(xml: string, label?: string, options?: {
16
- requireComplete?: boolean;
17
- }): void;
17
+ export declare function assertValidSclXml(xml: string, label?: string, options?: AssertValidSclXmlOptions): void;
18
+ /**
19
+ * Validate every case's `sourceXml`/`targetXml` and throw ONCE with the violations of all invalid
20
+ * cases, each attributed to its case name — so a suite's fixtures are fixed in one round instead of
21
+ * one failure at a time.
22
+ */
23
+ export declare function assertValidSclTestCases(params: AssertValidSclTestCasesParams): void;
18
24
  //# sourceMappingURL=assert-valid-scl-xml.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assert-valid-scl-xml.d.ts","sourceRoot":"","sources":["../../../src/v2019C1/test/assert-valid-scl-xml.ts"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,MAAM,EACX,KAAK,SAAa,EAClB,OAAO,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAO,GACzC,IAAI,CAqDN"}
1
+ {"version":3,"file":"assert-valid-scl-xml.d.ts","sourceRoot":"","sources":["../../../src/v2019C1/test/assert-valid-scl-xml.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,6BAA6B,EAC7B,wBAAwB,EAKxB,MAAM,8BAA8B,CAAA;AAsJrC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,MAAM,EACX,KAAK,SAAa,EAClB,OAAO,GAAE,wBAA6B,GACpC,IAAI,CAIN;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,6BAA6B,GAAG,IAAI,CAkBnF"}
@@ -0,0 +1,45 @@
1
+ export type SchemaNamespace = {
2
+ uri: string;
3
+ };
4
+ /** The slice of a generated element definition the fixture validator reads. */
5
+ export type SchemaElementDefinition = {
6
+ namespace?: SchemaNamespace;
7
+ attributes?: {
8
+ sequence?: readonly string[];
9
+ details?: Record<string, {
10
+ required?: boolean;
11
+ } | undefined>;
12
+ };
13
+ children?: {
14
+ sequence?: readonly string[];
15
+ any?: boolean;
16
+ details?: Record<string, {
17
+ namespace?: SchemaNamespace;
18
+ } | undefined>;
19
+ };
20
+ };
21
+ export type AssertValidSclXmlOptions = {
22
+ requireComplete?: boolean;
23
+ };
24
+ export type DescribeInvalidSclXmlParams = {
25
+ xml: string;
26
+ label: string;
27
+ requireComplete: boolean;
28
+ };
29
+ export type CollectElementViolationsParams = {
30
+ element: Element;
31
+ parentLocalName: string | undefined;
32
+ requireComplete: boolean;
33
+ };
34
+ export type CollectAttributeViolationsParams = {
35
+ element: Element;
36
+ definition: SchemaElementDefinition;
37
+ requireComplete: boolean;
38
+ };
39
+ export type AssertValidSclTestCasesParams = {
40
+ testCases: Record<string, {
41
+ sourceXml: string;
42
+ targetXml?: string;
43
+ }>;
44
+ };
45
+ //# sourceMappingURL=assert-valid-scl-xml.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assert-valid-scl-xml.types.d.ts","sourceRoot":"","sources":["../../../src/v2019C1/test/assert-valid-scl-xml.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7C,+EAA+E;AAC/E,MAAM,MAAM,uBAAuB,GAAG;IACrC,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,UAAU,CAAC,EAAE;QACZ,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,GAAG,SAAS,CAAC,CAAA;KAC5D,CAAA;IACD,QAAQ,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC5B,GAAG,CAAC,EAAE,OAAO,CAAA;QACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,SAAS,CAAC,EAAE,eAAe,CAAA;SAAE,GAAG,SAAS,CAAC,CAAA;KACrE,CAAA;CACD,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEpE,MAAM,MAAM,2BAA2B,GAAG;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC5C,OAAO,EAAE,OAAO,CAAA;IAChB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,eAAe,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,gCAAgC,GAAG;IAC9C,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,uBAAuB,CAAA;IACnC,eAAe,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC3C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACpE,CAAA"}
@@ -48,8 +48,8 @@ declare const rawRunSclTestCases: import('@dialecte/core/test').TestRunner<Confi
48
48
  };
49
49
  }>;
50
50
  /**
51
- * `createTestRunner`, wrapped so every registered case's XML is checked against the SCL schema's
52
- * per-element namespaces before the suite runs (see {@link assertValidSclXml}).
51
+ * `createTestRunner`, wrapped so every registered case's XML is checked against the SCL schema
52
+ * before the suite runs — all invalid cases reported at once (see {@link assertValidSclTestCases}).
53
53
  */
54
54
  export declare const runSclTestCases: typeof rawRunSclTestCases;
55
55
  export declare function createSclTestProject(params: {
@@ -1 +1 @@
1
- {"version":3,"file":"hydrated-test.d.ts","sourceRoot":"","sources":["../../../src/v2019C1/test/hydrated-test.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,0BAA0B,EAC1B,+BAA+B,EAE/B,MAAM,wBAAwB,CAAA;AAa/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AAO9D,eAAO,MAAM,mBAAmB,QAA0D,CAAA;AAC1F,eAAO,MAAM,yBAAyB,QAA2G,CAAA;AACjJ,eAAO,MAAM,oBAAoB,QAAsG,CAAA;AACvI,OAAO,EAAE,0BAA0B,EAAE,+BAA+B,EAAE,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAI1D,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAItB,CAAA;AAaF;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,kBAUpC,CAAA;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IAClD,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;CAAuD,CAAA;AACvF,eAAO,MAAQ,4BAA4B;;;YAAE,8BAA8B;;;UAI1E,CAAA"}
1
+ {"version":3,"file":"hydrated-test.d.ts","sourceRoot":"","sources":["../../../src/v2019C1/test/hydrated-test.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,0BAA0B,EAC1B,+BAA+B,EAE/B,MAAM,wBAAwB,CAAA;AAa/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAA;AAO9D,eAAO,MAAM,mBAAmB,QAA0D,CAAA;AAC1F,eAAO,MAAM,yBAAyB,QAA2G,CAAA;AACjJ,eAAO,MAAM,oBAAoB,QAAsG,CAAA;AACvI,OAAO,EAAE,0BAA0B,EAAE,+BAA+B,EAAE,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAI1D,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAItB,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,kBAUpC,CAAA;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IAClD,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;CAAuD,CAAA;AACvF,eAAO,MAAQ,4BAA4B;;;YAAE,8BAA8B;;;UAI1E,CAAA"}
@@ -1,70 +1,120 @@
1
- import { F as e, M as t, n, r, t as i } from "../hooks-BBGXNK0x.js";
2
- import { CUSTOM_RECORD_ID_ATTRIBUTE as a, CUSTOM_RECORD_ID_ATTRIBUTE_NAME as o, XMLNS_XSI_NAMESPACE as s } from "@dialecte/core/helpers";
3
- import { XMLNS_DEV_NAMESPACE as c, createTestProject as l, createTestRecordFactory as u, createTestRunner as d, createXmlAssertions as f } from "@dialecte/core/test";
1
+ import { F as e, M as t, P as n, n as r, r as i, t as a } from "../hooks-BBGXNK0x.js";
2
+ import { CUSTOM_RECORD_ID_ATTRIBUTE as o, CUSTOM_RECORD_ID_ATTRIBUTE_NAME as s, XMLNS_XSI_NAMESPACE as c } from "@dialecte/core/helpers";
3
+ import { XMLNS_DEV_NAMESPACE as l, createTestProject as u, createTestRecordFactory as d, createTestRunner as f, createXmlAssertions as p } from "@dialecte/core/test";
4
4
  //#region src/v2019C1/test/assert-valid-scl-xml.ts
5
- var p = e;
6
- function m(e, t) {
7
- return ((e ? p[e]?.children?.details?.[t]?.namespace : void 0) ?? p[t]?.namespace)?.uri;
5
+ var m = e, h = Object.values(n).map((e) => e.uri);
6
+ function g(e) {
7
+ return e.namespaceURI !== null && !h.includes(e.namespaceURI);
8
+ }
9
+ function _(e, t) {
10
+ return ((e ? m[e]?.children?.details?.[t]?.namespace : void 0) ?? m[t]?.namespace)?.uri;
8
11
  }
9
- function h(e, t) {
12
+ function v(e, t) {
10
13
  let n = e.children;
11
14
  return n ? n.any === !0 || n.sequence?.includes(t) ? !0 : n.details ? t in n.details : !1 : !1;
12
15
  }
13
- function g(e) {
16
+ function y(e) {
14
17
  return new Set([...e.attributes?.sequence ?? [], ...Object.keys(e.attributes?.details ?? {})]);
15
18
  }
16
- function _(e, t = "test XML", n = {}) {
17
- let r = n.requireComplete ?? !0, i = new DOMParser().parseFromString(e, "application/xml"), a = i.querySelector("parsererror");
18
- if (a) throw Error(`${t}: malformed XML — ${a.textContent?.trim()}`);
19
- let o = [], s = (e, t) => {
20
- let n = e.localName, i = p[n], a = m(t, n);
21
- if (a !== void 0 && e.namespaceURI !== a) {
22
- let n = t ? ` under <${t}>` : "";
23
- o.push(`[namespace] <${e.tagName}>${n}: is in ${e.namespaceURI ?? "(no namespace)"}, schema declares ${a}`);
24
- }
25
- let c = t ? p[t] : void 0;
26
- if (c && !h(c, n) && o.push(`[containment] <${n}> is not a valid child of <${t}>`), i?.attributes) {
27
- let t = g(i);
28
- for (let r of Array.from(e.attributes)) r.namespaceURI === null && (t.has(r.localName) || o.push(`[attribute] <${n}> has unknown attribute '${r.localName}'`));
29
- if (r) for (let [t, r] of Object.entries(i.attributes.details ?? {})) r?.required && !e.hasAttribute(t) && o.push(`[required] <${n}> is missing required attribute '${t}'`);
30
- }
31
- for (let t of Array.from(e.children)) s(t, n);
32
- };
33
- if (i.documentElement && s(i.documentElement, void 0), o.length > 0) throw Error(`${t}: not valid SCL:\n ${o.join("\n ")}`);
19
+ function b(e) {
20
+ let { element: t, definition: n, requireComplete: r } = e;
21
+ if (!n.attributes) return [];
22
+ let i = y(n), a = Array.from(t.attributes).filter((e) => e.namespaceURI === null && !i.has(e.localName)).map((e) => `[attribute] <${t.localName}> has unknown attribute '${e.localName}'`);
23
+ if (!r) return a;
24
+ let o = Object.entries(n.attributes.details ?? {}).filter(([e, n]) => n?.required && !t.hasAttribute(e)).map(([e]) => `[required] <${t.localName}> is missing required attribute '${e}'`);
25
+ return [...a, ...o];
26
+ }
27
+ function x(e) {
28
+ let { element: t, parentLocalName: n, requireComplete: r } = e, i = Array.from(t.children);
29
+ if (g(t)) return i.flatMap((e) => x({
30
+ element: e,
31
+ parentLocalName: void 0,
32
+ requireComplete: r
33
+ }));
34
+ let a = t.localName, o = [], s = _(n, a);
35
+ if (s !== void 0 && t.namespaceURI !== s) {
36
+ let e = n ? ` under <${n}>` : "";
37
+ o.push(`[namespace] <${t.tagName}>${e}: is in ${t.namespaceURI ?? "(no namespace)"}, schema declares ${s}`);
38
+ }
39
+ let c = n ? m[n] : void 0;
40
+ c && !v(c, a) && o.push(`[containment] <${a}> is not a valid child of <${n}>`);
41
+ let l = m[a], u = l ? b({
42
+ element: t,
43
+ definition: l,
44
+ requireComplete: r
45
+ }) : [], d = i.flatMap((e) => x({
46
+ element: e,
47
+ parentLocalName: a,
48
+ requireComplete: r
49
+ }));
50
+ return [
51
+ ...o,
52
+ ...u,
53
+ ...d
54
+ ];
55
+ }
56
+ function S(e) {
57
+ let { xml: t, label: n, requireComplete: r } = e;
58
+ if (!t.startsWith("<?xml") && t.trimStart().startsWith("<?xml")) return `${n}: malformed XML — the XML declaration must be the very first characters of the string: remove the declaration (a snippet does not need one) or the whitespace before it`;
59
+ let i = new DOMParser().parseFromString(t, "application/xml"), a = i.querySelector("parsererror");
60
+ if (a) return `${n}: malformed XML — ${a.textContent?.trim()}`;
61
+ if (!i.documentElement) return;
62
+ let o = x({
63
+ element: i.documentElement,
64
+ parentLocalName: void 0,
65
+ requireComplete: r
66
+ });
67
+ return o.length > 0 ? `${n}: not valid SCL:\n ${o.join("\n ")}` : void 0;
68
+ }
69
+ function C(e, t = "test XML", n = {}) {
70
+ let r = S({
71
+ xml: e,
72
+ label: t,
73
+ requireComplete: n.requireComplete ?? !0
74
+ });
75
+ if (r) throw Error(r);
34
76
  }
35
- //#endregion
36
- //#region src/v2019C1/test/hydrated-test.ts
37
- var v = {
38
- ...n(),
39
- ...i
40
- }, y = `xmlns="${t.namespaces.default.uri}"`, b = `xmlns:${t.namespaces.v2019C1.prefix}="${t.namespaces.v2019C1.uri}"`, x = `${y} ${b} ${c} ${s}`, S = { base: r }, C = d({
41
- dialecteConfig: t,
42
- extensions: S,
43
- hooks: v
44
- });
45
77
  function w(e) {
46
- for (let [t, n] of Object.entries(e)) _(n.sourceXml, `${t} › sourceXml`, { requireComplete: !1 }), n.targetXml && _(n.targetXml, `${t} › targetXml`, { requireComplete: !1 });
78
+ let { testCases: t } = e, n = Object.entries(t).flatMap(([e, t]) => [S({
79
+ xml: t.sourceXml,
80
+ label: `${e} › sourceXml`,
81
+ requireComplete: !1
82
+ }), t.targetXml ? S({
83
+ xml: t.targetXml,
84
+ label: `${e} › targetXml`,
85
+ requireComplete: !1
86
+ }) : void 0].filter((e) => e !== void 0));
87
+ if (n.length > 0) throw Error(n.join("\n"));
47
88
  }
89
+ //#endregion
90
+ //#region src/v2019C1/test/hydrated-test.ts
48
91
  var T = {
49
- ...C,
92
+ ...r(),
93
+ ...a
94
+ }, E = `xmlns="${t.namespaces.default.uri}"`, D = `xmlns:${t.namespaces.v2019C1.prefix}="${t.namespaces.v2019C1.uri}"`, O = `${E} ${D} ${l} ${c}`, k = { base: i }, A = f({
95
+ dialecteConfig: t,
96
+ extensions: k,
97
+ hooks: T
98
+ }), j = {
99
+ ...A,
50
100
  withExport(e) {
51
- w(e.testCases), C.withExport(e);
101
+ w({ testCases: e.testCases }), A.withExport(e);
52
102
  },
53
103
  withoutExport(e) {
54
- w(e.testCases), C.withoutExport(e);
104
+ w({ testCases: e.testCases }), A.withoutExport(e);
55
105
  }
56
106
  };
57
- async function E(e) {
107
+ async function M(e) {
58
108
  let { sourceXml: n, targetXml: r, dev: i } = e;
59
- return _(n, "sourceXml", { requireComplete: !1 }), r && _(r, "targetXml", { requireComplete: !1 }), l({
109
+ return C(n, "sourceXml", { requireComplete: !1 }), r && C(r, "targetXml", { requireComplete: !1 }), u({
60
110
  sourceXml: n,
61
111
  targetXml: r,
62
112
  dialecteConfig: t,
63
- extensions: S,
64
- hooks: v,
113
+ extensions: k,
114
+ hooks: T,
65
115
  dev: i
66
116
  });
67
117
  }
68
- var D = u(t), { assertExpectedElementQueries: O, assertUnexpectedElementQueries: k } = f({ namespaces: t.namespaces });
118
+ var N = d(t), { assertExpectedElementQueries: P, assertUnexpectedElementQueries: F } = p({ namespaces: t.namespaces });
69
119
  //#endregion
70
- export { x as ALL_XMLNS_NAMESPACES, a as CUSTOM_RECORD_ID_ATTRIBUTE, o as CUSTOM_RECORD_ID_ATTRIBUTE_NAME, b as XMLNS_SCL_6_100_NAMESPACE, y as XMLNS_SCL_NAMESPACE, O as assertExpectedElementQueries, k as assertUnexpectedElementQueries, _ as assertValidSclXml, E as createSclTestProject, D as createSclTestRecord, T as runSclTestCases };
120
+ export { O as ALL_XMLNS_NAMESPACES, o as CUSTOM_RECORD_ID_ATTRIBUTE, s as CUSTOM_RECORD_ID_ATTRIBUTE_NAME, D as XMLNS_SCL_6_100_NAMESPACE, E as XMLNS_SCL_NAMESPACE, P as assertExpectedElementQueries, F as assertUnexpectedElementQueries, C as assertValidSclXml, M as createSclTestProject, N as createSclTestRecord, j as runSclTestCases };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dialecte/scl",
3
- "version": "0.3.16",
3
+ "version": "0.3.17",
4
4
  "description": "Dialecte - SCL (Substation Configuration Language) sdk",
5
5
  "license": "MIT",
6
6
  "repository": {