@usearazzo/runner 0.0.0-stage → 1.0.1-alpha.7

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.
Files changed (151) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +784 -2
  4. package/dist/arazzo-runner.browser.js +111247 -0
  5. package/dist/arazzo-runner.browser.min.js +1 -0
  6. package/package.json +88 -4
  7. package/src/action/ActionResolver.cjs +160 -0
  8. package/src/action/ActionResolver.mjs +150 -0
  9. package/src/assembler/OpenAPI2DocumentAssembler.cjs +111 -0
  10. package/src/assembler/OpenAPI2DocumentAssembler.mjs +104 -0
  11. package/src/assembler/OpenAPI30DocumentAssembler.cjs +110 -0
  12. package/src/assembler/OpenAPI30DocumentAssembler.mjs +103 -0
  13. package/src/assembler/OpenAPI31DocumentAssembler.cjs +111 -0
  14. package/src/assembler/OpenAPI31DocumentAssembler.mjs +104 -0
  15. package/src/assembler/OpenAPIDocumentAssembler.cjs +58 -0
  16. package/src/assembler/OpenAPIDocumentAssembler.mjs +50 -0
  17. package/src/client/HTTPClient.cjs +5 -0
  18. package/src/client/HTTPClient.mjs +1 -0
  19. package/src/client/HTTPClientFetch.cjs +16 -0
  20. package/src/client/HTTPClientFetch.mjs +10 -0
  21. package/src/client/OpenAPIOperationRequest.cjs +5 -0
  22. package/src/client/OpenAPIOperationRequest.mjs +1 -0
  23. package/src/client/OpenAPIOperationResponse.cjs +42 -0
  24. package/src/client/OpenAPIOperationResponse.mjs +36 -0
  25. package/src/client/OpenAPIOperationResponseNormalizer.cjs +48 -0
  26. package/src/client/OpenAPIOperationResponseNormalizer.mjs +40 -0
  27. package/src/client/ParameterDelivery.cjs +119 -0
  28. package/src/client/ParameterDelivery.mjs +113 -0
  29. package/src/constants.cjs +9 -0
  30. package/src/constants.mjs +3 -0
  31. package/src/criterion/CriterionEvaluator.cjs +205 -0
  32. package/src/criterion/CriterionEvaluator.mjs +196 -0
  33. package/src/criterion/JSONPathCriterionEvaluator.cjs +47 -0
  34. package/src/criterion/JSONPathCriterionEvaluator.mjs +40 -0
  35. package/src/criterion/RegexCriterionEvaluator.cjs +67 -0
  36. package/src/criterion/RegexCriterionEvaluator.mjs +60 -0
  37. package/src/criterion/SimpleCriterionEvaluator.cjs +50 -0
  38. package/src/criterion/SimpleCriterionEvaluator.mjs +43 -0
  39. package/src/criterion/XPathCriterionEvaluator.cjs +117 -0
  40. package/src/criterion/XPathCriterionEvaluator.mjs +109 -0
  41. package/src/document/APIDocument.cjs +35 -0
  42. package/src/document/APIDocument.mjs +30 -0
  43. package/src/document/ArazzoDocument.cjs +81 -0
  44. package/src/document/ArazzoDocument.mjs +74 -0
  45. package/src/document/ArazzoSourceDescriptionIndex.cjs +26 -0
  46. package/src/document/ArazzoSourceDescriptionIndex.mjs +20 -0
  47. package/src/document/ArazzoStepIndex.cjs +25 -0
  48. package/src/document/ArazzoStepIndex.mjs +19 -0
  49. package/src/document/ArazzoWorkflowIndex.cjs +17 -0
  50. package/src/document/ArazzoWorkflowIndex.mjs +11 -0
  51. package/src/document/OpenAPIDocument.cjs +28 -0
  52. package/src/document/OpenAPIDocument.mjs +21 -0
  53. package/src/document/OpenAPIOperationIndex.cjs +24 -0
  54. package/src/document/OpenAPIOperationIndex.mjs +18 -0
  55. package/src/document/ParameterIdentity.cjs +93 -0
  56. package/src/document/ParameterIdentity.mjs +88 -0
  57. package/src/document/openapi-types.cjs +5 -0
  58. package/src/document/openapi-types.mjs +1 -0
  59. package/src/errors/ArazzoRunnerError.cjs +10 -0
  60. package/src/errors/ArazzoRunnerError.mjs +5 -0
  61. package/src/errors/AssemblerError.cjs +11 -0
  62. package/src/errors/AssemblerError.mjs +4 -0
  63. package/src/errors/ClientError.cjs +11 -0
  64. package/src/errors/ClientError.mjs +4 -0
  65. package/src/errors/CriterionError.cjs +11 -0
  66. package/src/errors/CriterionError.mjs +4 -0
  67. package/src/errors/ExecutionError.cjs +11 -0
  68. package/src/errors/ExecutionError.mjs +4 -0
  69. package/src/errors/ExtractionError.cjs +11 -0
  70. package/src/errors/ExtractionError.mjs +4 -0
  71. package/src/errors/InvalidEntryDocumentError.cjs +11 -0
  72. package/src/errors/InvalidEntryDocumentError.mjs +4 -0
  73. package/src/errors/NormalizationError.cjs +11 -0
  74. package/src/errors/NormalizationError.mjs +4 -0
  75. package/src/errors/ResolverError.cjs +11 -0
  76. package/src/errors/ResolverError.mjs +4 -0
  77. package/src/errors/RuntimeExpressionError.cjs +11 -0
  78. package/src/errors/RuntimeExpressionError.mjs +4 -0
  79. package/src/errors/UnmatchedProviderError.cjs +11 -0
  80. package/src/errors/UnmatchedProviderError.mjs +4 -0
  81. package/src/executor/ArazzoWorkflowLocatorNormalizer.cjs +147 -0
  82. package/src/executor/ArazzoWorkflowLocatorNormalizer.mjs +137 -0
  83. package/src/executor/OpenAPIOperationExecutor.cjs +457 -0
  84. package/src/executor/OpenAPIOperationExecutor.mjs +446 -0
  85. package/src/executor/OpenAPIOperationLocatorNormalizer.cjs +197 -0
  86. package/src/executor/OpenAPIOperationLocatorNormalizer.mjs +189 -0
  87. package/src/executor/SourceDescriptionsLocatorNormalizer.cjs +44 -0
  88. package/src/executor/SourceDescriptionsLocatorNormalizer.mjs +38 -0
  89. package/src/executor/StepExecutor.cjs +333 -0
  90. package/src/executor/StepExecutor.mjs +326 -0
  91. package/src/executor/StepRetryRunner.cjs +226 -0
  92. package/src/executor/StepRetryRunner.mjs +215 -0
  93. package/src/executor/StepTransitionInterpreter.cjs +159 -0
  94. package/src/executor/StepTransitionInterpreter.mjs +151 -0
  95. package/src/executor/WorkflowCallStack.cjs +116 -0
  96. package/src/executor/WorkflowCallStack.mjs +106 -0
  97. package/src/executor/WorkflowExecutor.cjs +1091 -0
  98. package/src/executor/WorkflowExecutor.mjs +1077 -0
  99. package/src/executor/abort.cjs +70 -0
  100. package/src/executor/abort.mjs +60 -0
  101. package/src/expression/RuntimeExpressionContext.cjs +5 -0
  102. package/src/expression/RuntimeExpressionContext.mjs +1 -0
  103. package/src/expression/RuntimeExpressionEvaluator.cjs +337 -0
  104. package/src/expression/RuntimeExpressionEvaluator.mjs +328 -0
  105. package/src/extractor/ArazzoStepExtractor.cjs +48 -0
  106. package/src/extractor/ArazzoStepExtractor.mjs +41 -0
  107. package/src/extractor/ArazzoWorkflowExtractor.cjs +50 -0
  108. package/src/extractor/ArazzoWorkflowExtractor.mjs +43 -0
  109. package/src/extractor/OpenAPIOperationExtractor.cjs +84 -0
  110. package/src/extractor/OpenAPIOperationExtractor.mjs +77 -0
  111. package/src/index.cjs +419 -0
  112. package/src/index.mjs +73 -0
  113. package/src/normalizer/ArazzoStepNormalizer.cjs +23 -0
  114. package/src/normalizer/ArazzoStepNormalizer.mjs +17 -0
  115. package/src/normalizer/ArazzoWorkflowNormalizer.cjs +214 -0
  116. package/src/normalizer/ArazzoWorkflowNormalizer.mjs +206 -0
  117. package/src/normalizer/OpenAPI2OperationNormalizer.cjs +128 -0
  118. package/src/normalizer/OpenAPI2OperationNormalizer.mjs +120 -0
  119. package/src/normalizer/OpenAPI30OperationNormalizer.cjs +129 -0
  120. package/src/normalizer/OpenAPI30OperationNormalizer.mjs +121 -0
  121. package/src/normalizer/OpenAPI31OperationNormalizer.cjs +131 -0
  122. package/src/normalizer/OpenAPI31OperationNormalizer.mjs +123 -0
  123. package/src/normalizer/OpenAPIOperationNormalizer.cjs +58 -0
  124. package/src/normalizer/OpenAPIOperationNormalizer.mjs +50 -0
  125. package/src/registry/DocumentRegistry.cjs +160 -0
  126. package/src/registry/DocumentRegistry.mjs +151 -0
  127. package/src/registry/providers/ArazzoDocumentRegistryProvider.cjs +154 -0
  128. package/src/registry/providers/ArazzoDocumentRegistryProvider.mjs +146 -0
  129. package/src/registry/providers/DocumentRegistryProvider.cjs +31 -0
  130. package/src/registry/providers/DocumentRegistryProvider.mjs +25 -0
  131. package/src/registry/providers/OpenAPIDocumentRegistryProvider.cjs +122 -0
  132. package/src/registry/providers/OpenAPIDocumentRegistryProvider.mjs +114 -0
  133. package/src/resolver/ArazzoValueResolver.cjs +42 -0
  134. package/src/resolver/ArazzoValueResolver.mjs +37 -0
  135. package/src/resolver/OpenAPIOperationParameterResolver.cjs +117 -0
  136. package/src/resolver/OpenAPIOperationParameterResolver.mjs +110 -0
  137. package/src/resolver/OutputResolver.cjs +71 -0
  138. package/src/resolver/OutputResolver.mjs +64 -0
  139. package/src/resolver/RequestBodyResolver.cjs +227 -0
  140. package/src/resolver/RequestBodyResolver.mjs +220 -0
  141. package/src/resolver/ResolverScope.cjs +5 -0
  142. package/src/resolver/ResolverScope.mjs +1 -0
  143. package/src/resolver/StepParameterResolver.cjs +22 -0
  144. package/src/resolver/StepParameterResolver.mjs +15 -0
  145. package/src/resolver/WorkflowParameterResolver.cjs +73 -0
  146. package/src/resolver/WorkflowParameterResolver.mjs +66 -0
  147. package/src/state/WorkflowExecutionState.cjs +99 -0
  148. package/src/state/WorkflowExecutionState.mjs +93 -0
  149. package/src/vendor/swagger-client.cjs +1 -0
  150. package/src/vendor/swagger-client.mjs +1 -0
  151. package/types/runner.d.ts +2341 -0
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
4
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _empty = require("@speclynx/apidom-reference/configuration/empty");
10
+ var _ArazzoDocument = _interopRequireDefault(require("../document/ArazzoDocument.cjs"));
11
+ var _ArazzoDocumentRegistryProvider = _interopRequireDefault(require("./providers/ArazzoDocumentRegistryProvider.cjs"));
12
+ var _OpenAPIDocumentRegistryProvider = _interopRequireDefault(require("./providers/OpenAPIDocumentRegistryProvider.cjs"));
13
+ var _InvalidEntryDocumentError = _interopRequireDefault(require("../errors/InvalidEntryDocumentError.cjs"));
14
+ var _UnmatchedProviderError = _interopRequireDefault(require("../errors/UnmatchedProviderError.cjs"));
15
+ var constants = _interopRequireWildcard(require("../constants.cjs"));
16
+ /**
17
+ * Options for the DocumentRegistry.
18
+ * @public
19
+ */
20
+
21
+ /**
22
+ * Registry for API documents keyed by canonical URI.
23
+ *
24
+ * Acts as an LRU cache for parsed documents. The entry Arazzo document
25
+ * is pinned and never evicted. Providers are tried in order to detect
26
+ * and load documents.
27
+ * @public
28
+ */
29
+ class DocumentRegistry {
30
+ #documents = new Map();
31
+ #providers;
32
+ constructor(options = {}) {
33
+ this.#providers = options.providers ?? [new _ArazzoDocumentRegistryProvider.default(), new _OpenAPIDocumentRegistryProvider.default()];
34
+ }
35
+
36
+ /**
37
+ * Returns the entry Arazzo document, or undefined if not yet registered.
38
+ */
39
+ get entryDocument() {
40
+ for (const doc of this.#documents.values()) {
41
+ if (_ArazzoDocument.default.is(doc) && doc.isEntry) {
42
+ return doc;
43
+ }
44
+ }
45
+ return undefined;
46
+ }
47
+
48
+ /**
49
+ * Acquires a document by URI. Returns cached document if available,
50
+ * otherwise detects the format, loads via the matching provider,
51
+ * caches, and returns it.
52
+ */
53
+ async acquire(uri) {
54
+ const canonicalURI = this.#canonicalize(uri);
55
+ const cachedDocument = this.#get(canonicalURI);
56
+ if (cachedDocument) return cachedDocument;
57
+ for (const provider of this.#providers) {
58
+ if (await provider.canProvide(canonicalURI)) {
59
+ const document = await provider.provide(canonicalURI);
60
+ this.#set(canonicalURI, document);
61
+ return document;
62
+ }
63
+ }
64
+ throw new _UnmatchedProviderError.default(`No provider can handle the document at "${canonicalURI}"`, {
65
+ uri: canonicalURI
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Returns an already-loaded document by URI, or undefined if not cached.
71
+ *
72
+ * Synchronous counterpart to `acquire`: it never loads a document, only
73
+ * returns one the registry already holds, marking it most recently used like
74
+ * any other access. Consumers that must resolve a reference without awaiting
75
+ * (e.g. runtime expression evaluation) use this; the executor is responsible
76
+ * for having acquired the document beforehand.
77
+ */
78
+ get(uri) {
79
+ return this.#get(this.#canonicalize(uri));
80
+ }
81
+
82
+ /**
83
+ * Canonical form of a URI, used as the cache key and handed to providers.
84
+ *
85
+ * A relative file system path resolves against the current working directory
86
+ * first: the canonical URI doubles as the base URI for source description
87
+ * URLs, where a relative base resolves against the filesystem root instead of
88
+ * the document. A leading slash or backslash (UNC, drive-rooted) is already
89
+ * rooted and passes through untouched. The working directory is encoded so a
90
+ * directory name containing `#`, `?` or `%` survives URL parsing.
91
+ */
92
+ #canonicalize(uri) {
93
+ const absoluteURI = !_empty.url.isHttpUrl(uri) && _empty.url.getProtocol(uri) !== 'file' && !/^[\\/]/.test(uri) ? _empty.url.resolve(_empty.url.fromFileSystemPath(_empty.url.cwd()), uri) : uri;
94
+ return _empty.url.sanitize(_empty.url.stripHash(absoluteURI));
95
+ }
96
+
97
+ /**
98
+ * Acquires the entry Arazzo document and marks it with `isEntry: true`.
99
+ * Validates that the document is an Arazzo specification.
100
+ */
101
+ async acquireEntryDocument(uri) {
102
+ const document = await this.acquire(uri);
103
+ if (!_ArazzoDocument.default.is(document)) {
104
+ throw new _InvalidEntryDocumentError.default(`Entry document at "${uri}" is not an Arazzo Document`, {
105
+ uri
106
+ });
107
+ }
108
+ document.isEntry = true;
109
+ return document;
110
+ }
111
+ clear() {
112
+ this.#documents.clear();
113
+ }
114
+
115
+ /**
116
+ * Retrieves a document and marks it as recently used.
117
+ */
118
+ #get(uri) {
119
+ const doc = this.#documents.get(uri);
120
+ if (doc === undefined) return undefined;
121
+
122
+ // move to end (most recently used)
123
+ this.#documents.delete(uri);
124
+ this.#documents.set(uri, doc);
125
+ return doc;
126
+ }
127
+
128
+ /**
129
+ * Registers a document in the registry.
130
+ *
131
+ * If the registry is at capacity, the least recently used document
132
+ * is evicted. The entry Arazzo document is never evicted.
133
+ */
134
+ #set(uri, document) {
135
+ if (this.#documents.has(uri)) {
136
+ this.#documents.delete(uri);
137
+ } else if (this.#documents.size >= constants.MAX_DOCUMENT_REGISTRY_SIZE) {
138
+ this.#evictOldest();
139
+ }
140
+ this.#documents.set(uri, document);
141
+ }
142
+
143
+ /**
144
+ * Removes a document from the registry.
145
+ * The entry document cannot be removed.
146
+ */
147
+ #delete(uri) {
148
+ const doc = this.#documents.get(uri);
149
+ if (doc && _ArazzoDocument.default.is(doc) && doc.isEntry) {
150
+ return false;
151
+ }
152
+ return this.#documents.delete(uri);
153
+ }
154
+ #evictOldest() {
155
+ for (const [uri] of this.#documents) {
156
+ if (this.#delete(uri)) return;
157
+ }
158
+ }
159
+ }
160
+ var _default = exports.default = DocumentRegistry;
@@ -0,0 +1,151 @@
1
+ import { url } from '@speclynx/apidom-reference/configuration/empty';
2
+ import ArazzoDocument from "../document/ArazzoDocument.mjs";
3
+ import ArazzoDocumentRegistryProvider from "./providers/ArazzoDocumentRegistryProvider.mjs";
4
+ import OpenAPIDocumentRegistryProvider from "./providers/OpenAPIDocumentRegistryProvider.mjs";
5
+ import InvalidEntryDocumentError from "../errors/InvalidEntryDocumentError.mjs";
6
+ import UnmatchedProviderError from "../errors/UnmatchedProviderError.mjs";
7
+ import * as constants from "../constants.mjs";
8
+ /**
9
+ * Options for the DocumentRegistry.
10
+ * @public
11
+ */
12
+ /**
13
+ * Registry for API documents keyed by canonical URI.
14
+ *
15
+ * Acts as an LRU cache for parsed documents. The entry Arazzo document
16
+ * is pinned and never evicted. Providers are tried in order to detect
17
+ * and load documents.
18
+ * @public
19
+ */
20
+ class DocumentRegistry {
21
+ #documents = new Map();
22
+ #providers;
23
+ constructor(options = {}) {
24
+ this.#providers = options.providers ?? [new ArazzoDocumentRegistryProvider(), new OpenAPIDocumentRegistryProvider()];
25
+ }
26
+
27
+ /**
28
+ * Returns the entry Arazzo document, or undefined if not yet registered.
29
+ */
30
+ get entryDocument() {
31
+ for (const doc of this.#documents.values()) {
32
+ if (ArazzoDocument.is(doc) && doc.isEntry) {
33
+ return doc;
34
+ }
35
+ }
36
+ return undefined;
37
+ }
38
+
39
+ /**
40
+ * Acquires a document by URI. Returns cached document if available,
41
+ * otherwise detects the format, loads via the matching provider,
42
+ * caches, and returns it.
43
+ */
44
+ async acquire(uri) {
45
+ const canonicalURI = this.#canonicalize(uri);
46
+ const cachedDocument = this.#get(canonicalURI);
47
+ if (cachedDocument) return cachedDocument;
48
+ for (const provider of this.#providers) {
49
+ if (await provider.canProvide(canonicalURI)) {
50
+ const document = await provider.provide(canonicalURI);
51
+ this.#set(canonicalURI, document);
52
+ return document;
53
+ }
54
+ }
55
+ throw new UnmatchedProviderError(`No provider can handle the document at "${canonicalURI}"`, {
56
+ uri: canonicalURI
57
+ });
58
+ }
59
+
60
+ /**
61
+ * Returns an already-loaded document by URI, or undefined if not cached.
62
+ *
63
+ * Synchronous counterpart to `acquire`: it never loads a document, only
64
+ * returns one the registry already holds, marking it most recently used like
65
+ * any other access. Consumers that must resolve a reference without awaiting
66
+ * (e.g. runtime expression evaluation) use this; the executor is responsible
67
+ * for having acquired the document beforehand.
68
+ */
69
+ get(uri) {
70
+ return this.#get(this.#canonicalize(uri));
71
+ }
72
+
73
+ /**
74
+ * Canonical form of a URI, used as the cache key and handed to providers.
75
+ *
76
+ * A relative file system path resolves against the current working directory
77
+ * first: the canonical URI doubles as the base URI for source description
78
+ * URLs, where a relative base resolves against the filesystem root instead of
79
+ * the document. A leading slash or backslash (UNC, drive-rooted) is already
80
+ * rooted and passes through untouched. The working directory is encoded so a
81
+ * directory name containing `#`, `?` or `%` survives URL parsing.
82
+ */
83
+ #canonicalize(uri) {
84
+ const absoluteURI = !url.isHttpUrl(uri) && url.getProtocol(uri) !== 'file' && !/^[\\/]/.test(uri) ? url.resolve(url.fromFileSystemPath(url.cwd()), uri) : uri;
85
+ return url.sanitize(url.stripHash(absoluteURI));
86
+ }
87
+
88
+ /**
89
+ * Acquires the entry Arazzo document and marks it with `isEntry: true`.
90
+ * Validates that the document is an Arazzo specification.
91
+ */
92
+ async acquireEntryDocument(uri) {
93
+ const document = await this.acquire(uri);
94
+ if (!ArazzoDocument.is(document)) {
95
+ throw new InvalidEntryDocumentError(`Entry document at "${uri}" is not an Arazzo Document`, {
96
+ uri
97
+ });
98
+ }
99
+ document.isEntry = true;
100
+ return document;
101
+ }
102
+ clear() {
103
+ this.#documents.clear();
104
+ }
105
+
106
+ /**
107
+ * Retrieves a document and marks it as recently used.
108
+ */
109
+ #get(uri) {
110
+ const doc = this.#documents.get(uri);
111
+ if (doc === undefined) return undefined;
112
+
113
+ // move to end (most recently used)
114
+ this.#documents.delete(uri);
115
+ this.#documents.set(uri, doc);
116
+ return doc;
117
+ }
118
+
119
+ /**
120
+ * Registers a document in the registry.
121
+ *
122
+ * If the registry is at capacity, the least recently used document
123
+ * is evicted. The entry Arazzo document is never evicted.
124
+ */
125
+ #set(uri, document) {
126
+ if (this.#documents.has(uri)) {
127
+ this.#documents.delete(uri);
128
+ } else if (this.#documents.size >= constants.MAX_DOCUMENT_REGISTRY_SIZE) {
129
+ this.#evictOldest();
130
+ }
131
+ this.#documents.set(uri, document);
132
+ }
133
+
134
+ /**
135
+ * Removes a document from the registry.
136
+ * The entry document cannot be removed.
137
+ */
138
+ #delete(uri) {
139
+ const doc = this.#documents.get(uri);
140
+ if (doc && ArazzoDocument.is(doc) && doc.isEntry) {
141
+ return false;
142
+ }
143
+ return this.#documents.delete(uri);
144
+ }
145
+ #evictOldest() {
146
+ for (const [uri] of this.#documents) {
147
+ if (this.#delete(uri)) return;
148
+ }
149
+ }
150
+ }
151
+ export default DocumentRegistry;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.providerOptionsOverride = exports.default = void 0;
9
+ var _parser = require("@usearazzo/parser");
10
+ var _empty = require("@speclynx/apidom-reference/configuration/empty");
11
+ var _apidomCore = require("@speclynx/apidom-core");
12
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
13
+ var _apidomTraverse = require("@speclynx/apidom-traverse");
14
+ var _apidomNsArazzo = require("@speclynx/apidom-ns-arazzo-1");
15
+ var constants = _interopRequireWildcard(require("../../constants.cjs"));
16
+ var _ArazzoDocument = _interopRequireDefault(require("../../document/ArazzoDocument.cjs"));
17
+ var _DocumentRegistryProvider = _interopRequireWildcard(require("./DocumentRegistryProvider.cjs"));
18
+ var _ArazzoWorkflowIndex = _interopRequireDefault(require("../../document/ArazzoWorkflowIndex.cjs"));
19
+ var _ArazzoStepIndex = _interopRequireDefault(require("../../document/ArazzoStepIndex.cjs"));
20
+ var _ArazzoSourceDescriptionIndex = _interopRequireDefault(require("../../document/ArazzoSourceDescriptionIndex.cjs"));
21
+ /**
22
+ * Options for loading an Arazzo document.
23
+ * @public
24
+ */
25
+
26
+ /**
27
+ * Default options for loading an Arazzo document.
28
+ *
29
+ * The provider only parses the Arazzo document; dereferencing is deferred
30
+ * to the normalizer when a specific workflow is accessed.
31
+ */
32
+ const providerOptionsOverride = exports.providerOptionsOverride = {
33
+ resolve: {
34
+ resolverOpts: {
35
+ cache: {
36
+ maxEntries: constants.MAX_HTTP_CACHE_ENTRIES,
37
+ maxStaleAge: constants.MAX_HTTP_CACHE_STALE_AGE
38
+ }
39
+ }
40
+ },
41
+ dereference: {
42
+ immutable: false,
43
+ circular: 'replace',
44
+ circularReplacer: _DocumentRegistryProvider.circularReplacer,
45
+ strategyOpts: {
46
+ sourceDescriptions: false
47
+ }
48
+ }
49
+ };
50
+
51
+ /**
52
+ * Provides ArazzoDocument instances for the DocumentRegistry.
53
+ *
54
+ * Parses the Arazzo document and builds its workflow and source description
55
+ * indexes — the document itself is a container.
56
+ * @public
57
+ */
58
+ class ArazzoDocumentRegistryProvider extends _DocumentRegistryProvider.default {
59
+ #options;
60
+ constructor(options = {}) {
61
+ super();
62
+ this.#options = (0, _empty.mergeOptions)(providerOptionsOverride, options);
63
+ }
64
+ async canProvide(uri) {
65
+ try {
66
+ const options = this.#buildParseOptions();
67
+ const data = await (0, _empty.readFile)(uri, options);
68
+ const file = new _empty.File({
69
+ uri,
70
+ data
71
+ });
72
+ const parsers = options.parse.parsers.filter(p => p.name.startsWith('arazzo'));
73
+ for (const parser of parsers) {
74
+ if (await parser.canParse(file)) return true;
75
+ }
76
+ } catch (error) {
77
+ if (error instanceof _empty.UnmatchedResolverError) return false;
78
+ throw error;
79
+ }
80
+ return false;
81
+ }
82
+
83
+ /**
84
+ * Loads an Arazzo document from a URI and produces an ArazzoDocument.
85
+ */
86
+ async provide(uri) {
87
+ const parseResult = await (0, _parser.parseArazzo)(uri, this.#buildParseOptions());
88
+ const {
89
+ workflowIndex,
90
+ stepIndex,
91
+ sourceDescriptionIndex
92
+ } = this.#buildIndexes(uri, parseResult);
93
+ return new _ArazzoDocument.default(uri, parseResult, workflowIndex, stepIndex, sourceDescriptionIndex);
94
+ }
95
+
96
+ /**
97
+ * Builds all indexes in one traversal of the parse result.
98
+ *
99
+ * A source description's canonical URI is resolved here too — against the
100
+ * document's base URI, into the exact form the document registry keys on —
101
+ * so every consumer works with a ready-to-use, non-relative URI. The first
102
+ * element of a duplicated source description name wins.
103
+ */
104
+ #buildIndexes(uri, parseResult) {
105
+ const workflowIndex = new _ArazzoWorkflowIndex.default();
106
+ const stepIndex = new _ArazzoStepIndex.default();
107
+ const sourceDescriptionIndex = new _ArazzoSourceDescriptionIndex.default();
108
+ (0, _apidomTraverse.traverse)(parseResult.api, {
109
+ WorkflowElement(path) {
110
+ const workflow = path.node;
111
+ const workflowId = (0, _apidomCore.toValue)(workflow.workflowId);
112
+ if (typeof workflowId !== 'string') return path.skip();
113
+ if (workflowId === '') return path.skip();
114
+ const workflowPointer = path.formatPath('jsonpointer');
115
+ workflowIndex.set(workflowId, workflowPointer);
116
+
117
+ // steps are indexed by list position; malformed entries are left to the
118
+ // executor to report, the index simply omits them.
119
+ const steps = new Map();
120
+ if ((0, _apidomDatamodel.isArrayElement)(workflow.steps)) {
121
+ [...workflow.steps].forEach((step, index) => {
122
+ if (!(0, _apidomNsArazzo.isStepElement)(step)) return;
123
+ const stepId = (0, _apidomCore.toValue)(step.stepId);
124
+ if (typeof stepId !== 'string' || stepId === '') return;
125
+ if (!steps.has(stepId)) steps.set(stepId, `${workflowPointer}/steps/${index}`);
126
+ });
127
+ }
128
+ stepIndex.set(workflowId, steps);
129
+ return path.skip();
130
+ },
131
+ SourceDescriptionElement(path) {
132
+ const element = path.node;
133
+ if (!(0, _apidomDatamodel.isStringElement)(element.name)) return path.skip();
134
+ const name = (0, _apidomCore.toValue)(element.name);
135
+ if (!sourceDescriptionIndex.has(name)) {
136
+ sourceDescriptionIndex.set(name, {
137
+ element,
138
+ uri: (0, _apidomDatamodel.isStringElement)(element.url) ? _empty.url.sanitize(_empty.url.stripHash(_empty.url.resolve(uri, (0, _apidomCore.toValue)(element.url)))) : undefined
139
+ });
140
+ }
141
+ return path.skip();
142
+ }
143
+ });
144
+ return {
145
+ workflowIndex,
146
+ stepIndex,
147
+ sourceDescriptionIndex
148
+ };
149
+ }
150
+ #buildParseOptions() {
151
+ return (0, _empty.mergeOptions)(_parser.defaultParseArazzoOptions, this.#options);
152
+ }
153
+ }
154
+ var _default = exports.default = ArazzoDocumentRegistryProvider;
@@ -0,0 +1,146 @@
1
+ import { parseArazzo, defaultParseArazzoOptions } from '@usearazzo/parser';
2
+ import { readFile, File, mergeOptions, url } from '@speclynx/apidom-reference/configuration/empty';
3
+ import { UnmatchedResolverError } from '@speclynx/apidom-reference/configuration/empty';
4
+ import { toValue } from '@speclynx/apidom-core';
5
+ import { isArrayElement, isStringElement } from '@speclynx/apidom-datamodel';
6
+ import { traverse } from '@speclynx/apidom-traverse';
7
+ import { isStepElement } from '@speclynx/apidom-ns-arazzo-1';
8
+ import * as constants from "../../constants.mjs";
9
+ import ArazzoDocument from "../../document/ArazzoDocument.mjs";
10
+ import DocumentRegistryProvider, { circularReplacer } from "./DocumentRegistryProvider.mjs";
11
+ import ArazzoWorkflowIndex from "../../document/ArazzoWorkflowIndex.mjs";
12
+ import ArazzoStepIndex from "../../document/ArazzoStepIndex.mjs";
13
+ import ArazzoSourceDescriptionIndex from "../../document/ArazzoSourceDescriptionIndex.mjs";
14
+ /**
15
+ * Options for loading an Arazzo document.
16
+ * @public
17
+ */
18
+ /**
19
+ * Default options for loading an Arazzo document.
20
+ *
21
+ * The provider only parses the Arazzo document; dereferencing is deferred
22
+ * to the normalizer when a specific workflow is accessed.
23
+ */
24
+ export const providerOptionsOverride = {
25
+ resolve: {
26
+ resolverOpts: {
27
+ cache: {
28
+ maxEntries: constants.MAX_HTTP_CACHE_ENTRIES,
29
+ maxStaleAge: constants.MAX_HTTP_CACHE_STALE_AGE
30
+ }
31
+ }
32
+ },
33
+ dereference: {
34
+ immutable: false,
35
+ circular: 'replace',
36
+ circularReplacer,
37
+ strategyOpts: {
38
+ sourceDescriptions: false
39
+ }
40
+ }
41
+ };
42
+
43
+ /**
44
+ * Provides ArazzoDocument instances for the DocumentRegistry.
45
+ *
46
+ * Parses the Arazzo document and builds its workflow and source description
47
+ * indexes — the document itself is a container.
48
+ * @public
49
+ */
50
+ class ArazzoDocumentRegistryProvider extends DocumentRegistryProvider {
51
+ #options;
52
+ constructor(options = {}) {
53
+ super();
54
+ this.#options = mergeOptions(providerOptionsOverride, options);
55
+ }
56
+ async canProvide(uri) {
57
+ try {
58
+ const options = this.#buildParseOptions();
59
+ const data = await readFile(uri, options);
60
+ const file = new File({
61
+ uri,
62
+ data
63
+ });
64
+ const parsers = options.parse.parsers.filter(p => p.name.startsWith('arazzo'));
65
+ for (const parser of parsers) {
66
+ if (await parser.canParse(file)) return true;
67
+ }
68
+ } catch (error) {
69
+ if (error instanceof UnmatchedResolverError) return false;
70
+ throw error;
71
+ }
72
+ return false;
73
+ }
74
+
75
+ /**
76
+ * Loads an Arazzo document from a URI and produces an ArazzoDocument.
77
+ */
78
+ async provide(uri) {
79
+ const parseResult = await parseArazzo(uri, this.#buildParseOptions());
80
+ const {
81
+ workflowIndex,
82
+ stepIndex,
83
+ sourceDescriptionIndex
84
+ } = this.#buildIndexes(uri, parseResult);
85
+ return new ArazzoDocument(uri, parseResult, workflowIndex, stepIndex, sourceDescriptionIndex);
86
+ }
87
+
88
+ /**
89
+ * Builds all indexes in one traversal of the parse result.
90
+ *
91
+ * A source description's canonical URI is resolved here too — against the
92
+ * document's base URI, into the exact form the document registry keys on —
93
+ * so every consumer works with a ready-to-use, non-relative URI. The first
94
+ * element of a duplicated source description name wins.
95
+ */
96
+ #buildIndexes(uri, parseResult) {
97
+ const workflowIndex = new ArazzoWorkflowIndex();
98
+ const stepIndex = new ArazzoStepIndex();
99
+ const sourceDescriptionIndex = new ArazzoSourceDescriptionIndex();
100
+ traverse(parseResult.api, {
101
+ WorkflowElement(path) {
102
+ const workflow = path.node;
103
+ const workflowId = toValue(workflow.workflowId);
104
+ if (typeof workflowId !== 'string') return path.skip();
105
+ if (workflowId === '') return path.skip();
106
+ const workflowPointer = path.formatPath('jsonpointer');
107
+ workflowIndex.set(workflowId, workflowPointer);
108
+
109
+ // steps are indexed by list position; malformed entries are left to the
110
+ // executor to report, the index simply omits them.
111
+ const steps = new Map();
112
+ if (isArrayElement(workflow.steps)) {
113
+ [...workflow.steps].forEach((step, index) => {
114
+ if (!isStepElement(step)) return;
115
+ const stepId = toValue(step.stepId);
116
+ if (typeof stepId !== 'string' || stepId === '') return;
117
+ if (!steps.has(stepId)) steps.set(stepId, `${workflowPointer}/steps/${index}`);
118
+ });
119
+ }
120
+ stepIndex.set(workflowId, steps);
121
+ return path.skip();
122
+ },
123
+ SourceDescriptionElement(path) {
124
+ const element = path.node;
125
+ if (!isStringElement(element.name)) return path.skip();
126
+ const name = toValue(element.name);
127
+ if (!sourceDescriptionIndex.has(name)) {
128
+ sourceDescriptionIndex.set(name, {
129
+ element,
130
+ uri: isStringElement(element.url) ? url.sanitize(url.stripHash(url.resolve(uri, toValue(element.url)))) : undefined
131
+ });
132
+ }
133
+ return path.skip();
134
+ }
135
+ });
136
+ return {
137
+ workflowIndex,
138
+ stepIndex,
139
+ sourceDescriptionIndex
140
+ };
141
+ }
142
+ #buildParseOptions() {
143
+ return mergeOptions(defaultParseArazzoOptions, this.#options);
144
+ }
145
+ }
146
+ export default ArazzoDocumentRegistryProvider;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.circularReplacer = void 0;
7
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
8
+ /**
9
+ * Replaces circular $ref references with an empty ObjectElement
10
+ * annotated with the original $ref value. This ensures the dereferenced
11
+ * output is a finite tree safe for downstream tools.
12
+ * @param ref - The RefElement being replaced at the cycle boundary.
13
+ * @public
14
+ */
15
+ const circularReplacer = ref => new _apidomDatamodel.ObjectElement({
16
+ 'x-circular': ref.meta.get('$ref')
17
+ });
18
+
19
+ /**
20
+ * Options for a document registry provider.
21
+ * @public
22
+ */
23
+ exports.circularReplacer = circularReplacer;
24
+ /**
25
+ * Base class for document registry providers.
26
+ *
27
+ * Subclasses implement `canProvide()` for format detection and `provide()` for loading.
28
+ * @public
29
+ */
30
+ class DocumentRegistryProvider {}
31
+ var _default = exports.default = DocumentRegistryProvider;
@@ -0,0 +1,25 @@
1
+ import { ObjectElement } from '@speclynx/apidom-datamodel';
2
+ /**
3
+ * Replaces circular $ref references with an empty ObjectElement
4
+ * annotated with the original $ref value. This ensures the dereferenced
5
+ * output is a finite tree safe for downstream tools.
6
+ * @param ref - The RefElement being replaced at the cycle boundary.
7
+ * @public
8
+ */
9
+ export const circularReplacer = ref => new ObjectElement({
10
+ 'x-circular': ref.meta.get('$ref')
11
+ });
12
+
13
+ /**
14
+ * Options for a document registry provider.
15
+ * @public
16
+ */
17
+
18
+ /**
19
+ * Base class for document registry providers.
20
+ *
21
+ * Subclasses implement `canProvide()` for format detection and `provide()` for loading.
22
+ * @public
23
+ */
24
+ class DocumentRegistryProvider {}
25
+ export default DocumentRegistryProvider;