@zenwave360/workspace-mcp 1.0.0-next.0 → 1.0.0-next.19.1
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 +349 -323
- package/kotlin/antlr-kotlin-antlr-kotlin-runtime.js +2957 -2957
- package/kotlin/antlr-kotlin-antlr-kotlin-runtime.js.map +1 -1
- package/kotlin/dsl-kotlin.js +6213 -6213
- package/kotlin/dsl-kotlin.js.map +1 -1
- package/kotlin/json-schema-ref-parser-kmp.js +880 -652
- package/kotlin/json-schema-ref-parser-kmp.js.map +1 -1
- package/kotlin/kotlin-kotlin-stdlib.js +1037 -1009
- package/kotlin/kotlin-kotlin-stdlib.js.map +1 -1
- package/kotlin/kotlinx-atomicfu.js +10 -10
- package/kotlin/kotlinx-coroutines-core.js +785 -785
- package/kotlin/kotlinx-coroutines-core.js.map +1 -1
- package/kotlin/okio-parent-okio.js +369 -369
- package/kotlin/okio-parent-okio.js.map +1 -1
- package/kotlin/snakeyaml-engine-kmp.js +1568 -1568
- package/kotlin/snakeyaml-engine-kmp.js.map +1 -1
- package/kotlin/urlencoder-urlencoder-lib.js +52 -52
- package/kotlin/urlencoder-urlencoder-lib.js.map +1 -1
- package/package.json +1 -1
- package/kotlin/kotlin-js-core.js +0 -15
- package/kotlin/kotlin-js-core.js.map +0 -1
- package/kotlin/kotlin-js.js +0 -15
- package/kotlin/kotlin-js.js.map +0 -1
- package/kotlin/kotlin-node.js +0 -15
- package/kotlin/kotlin-node.js.map +0 -1
- package/kotlin/kotlin-plugins-js-plain-objects-runtime.js +0 -15
- package/kotlin/kotlin-plugins-js-plain-objects-runtime.js.map +0 -1
- package/kotlin/kotlin-web.js +0 -15
- package/kotlin/kotlin-web.js.map +0 -1
- package/kotlin/seskar-core.js +0 -15
- package/kotlin/seskar-core.js.map +0 -1
- package/kotlin/seskar-react.js +0 -15
- package/kotlin/seskar-react.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,208 +1,208 @@
|
|
|
1
|
-
# ZenWave Manifest
|
|
2
|
-
|
|
3
|
-
[](https://search.maven.org/artifact/io.zenwave360.manifest/manifest-core)
|
|
4
|
-
[](https://github.com/ZenWave360/zenwave-manifest/actions/workflows/publish-maven-snapshots.yml)
|
|
5
|
-
[](https://github.com/ZenWave360/zenwave-manifest/actions/workflows/main.yml)
|
|
6
|
-
[](https://github.com/ZenWave360/zenwave-manifest/actions/workflows/main.yml)
|
|
7
|
-
[](https://github.com/ZenWave360/zenwave-manifest/blob/main/LICENSE)
|
|
8
|
-
|
|
9
|
-
ZenWave Manifest is the architecture contract shared by ZenWave tools. A hand-authored `zenwave-architecture.yml` describes domains, services, documentation, and artifacts; the Kotlin Multiplatform library resolves that content deterministically from workspace, Git, Apicurio Registry, generic Artifactory, or Maven sources. Its source-aware editor can update existing scalar values without reserializing the surrounding YAML.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- Versioned schema: `https://schemas.zenwave360.io/zenwave-architecture/1.0/schema.json`
|
|
13
|
-
- Latest schema: `https://schemas.zenwave360.io/zenwave-architecture/latest/schema.json`
|
|
14
|
-
- Detailed authoring guide: [docs/source-resolution-guide.md](docs/source-resolution-guide.md)
|
|
1
|
+
# ZenWave Manifest
|
|
2
|
+
|
|
3
|
+
[](https://search.maven.org/artifact/io.zenwave360.manifest/manifest-core)
|
|
4
|
+
[](https://github.com/ZenWave360/zenwave-manifest/actions/workflows/publish-maven-snapshots.yml)
|
|
5
|
+
[](https://github.com/ZenWave360/zenwave-manifest/actions/workflows/main.yml)
|
|
6
|
+
[](https://github.com/ZenWave360/zenwave-manifest/actions/workflows/main.yml)
|
|
7
|
+
[](https://github.com/ZenWave360/zenwave-manifest/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
ZenWave Manifest is the architecture contract shared by ZenWave tools. A hand-authored `zenwave-architecture.yml` describes domains, services, documentation, and artifacts; the Kotlin Multiplatform library resolves that content deterministically from workspace, Git, Apicurio Registry, generic Artifactory, or Maven sources. Its source-aware editor can update existing scalar values without reserializing the surrounding YAML.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
- Versioned schema: `https://schemas.zenwave360.io/zenwave-architecture/1.0/schema.json`
|
|
13
|
+
- Latest schema: `https://schemas.zenwave360.io/zenwave-architecture/latest/schema.json`
|
|
14
|
+
- Detailed authoring guide: [docs/source-resolution-guide.md](docs/source-resolution-guide.md)
|
|
15
15
|
- Normative source-resolution specification: [docs/source-resolution-specification.md](docs/source-resolution-specification.md)
|
|
16
16
|
- Workspace diagnostic codes: [docs/diagnostics.md](docs/diagnostics.md)
|
|
17
|
-
|
|
18
|
-
## Complete manifest
|
|
19
|
-
|
|
20
|
-
```yaml
|
|
21
|
-
# schema-test: valid
|
|
22
|
-
# yaml-language-server: $schema=https://schemas.zenwave360.io/zenwave-architecture/1.0/schema.json
|
|
23
|
-
|
|
24
|
-
config:
|
|
25
|
-
title: Arcadia architecture
|
|
26
|
-
groupIdExpression: "io.arcadia.${service.id}"
|
|
27
|
-
|
|
28
|
-
contentResolution:
|
|
29
|
-
- workspace
|
|
30
|
-
- git
|
|
31
|
-
- apicurio
|
|
32
|
-
- artifactory
|
|
33
|
-
- maven
|
|
34
|
-
|
|
35
|
-
sources:
|
|
36
|
-
workspace:
|
|
37
|
-
basePathExpression: "../../${domain.id}/${subdomain.id}/${service.id}"
|
|
38
|
-
|
|
39
|
-
git:
|
|
40
|
-
provider: gitlab
|
|
41
|
-
server: https://gitlab.com
|
|
42
|
-
|
|
43
|
-
apicurio:
|
|
44
|
-
server: https://registry.example.com
|
|
45
|
-
|
|
46
|
-
artifactory:
|
|
47
|
-
server: https://artifacts.example.com
|
|
48
|
-
|
|
49
|
-
maven:
|
|
50
|
-
provider: artifactory
|
|
51
|
-
server: https://artifacts.example.com/artifactory
|
|
52
|
-
repository: maven-releases
|
|
53
|
-
|
|
54
|
-
domains:
|
|
55
|
-
commerce:
|
|
56
|
-
version: 1.0.0
|
|
57
|
-
|
|
58
|
-
services:
|
|
59
|
-
orders:
|
|
60
|
-
id: orders-api
|
|
61
|
-
docs:
|
|
62
|
-
summary: docs/SUMMARY.md
|
|
63
|
-
catalog: docs/EVENT_CATALOG.md
|
|
64
|
-
readme: docs/README.md
|
|
65
|
-
artifacts:
|
|
66
|
-
- type: openapi
|
|
67
|
-
path: contracts/orders.openapi.yaml
|
|
68
|
-
version: 1.1.0
|
|
69
|
-
|
|
70
|
-
subdomains:
|
|
71
|
-
fulfillment:
|
|
72
|
-
version: 2.0.0
|
|
73
|
-
services:
|
|
74
|
-
shipping:
|
|
75
|
-
artifacts:
|
|
76
|
-
- type: asyncapi
|
|
77
|
-
path: contracts/shipping.asyncapi.yaml
|
|
78
|
-
version: 2.0.0
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Domains, subdomains, and services use a non-blank explicit `id` when present and otherwise use their YAML map key. A direct service has an empty `subdomain.id`. Every artifact declares its own required `version`; domain, subdomain, and service versions are optional and apply only to service documents. The primary example deliberately omits artifact `name` and `artifactId`: names are never derived from paths, while artifact IDs use their configured fallback.
|
|
82
|
-
|
|
83
|
-
For a manifest stored at `/work/architecture/manifests/zenwave-architecture.yml`, the `../../` prefix reaches `/work`; the first artifact's workspace candidate is:
|
|
84
|
-
|
|
85
|
-
```text
|
|
86
|
-
/work/commerce/orders-api/contracts/orders.openapi.yaml
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
The same artifact has these remote candidates:
|
|
90
|
-
|
|
91
|
-
```text
|
|
92
|
-
https://gitlab.com/commerce/orders-api/-/raw/v1.1.0/contracts/orders.openapi.yaml
|
|
93
|
-
https://registry.example.com/apis/registry/v3/groups/orders-api/artifacts/contracts%2Forders.openapi.yaml/versions/1.1.0/content
|
|
94
|
-
https://artifacts.example.com/artifactory/contracts/commerce/orders-api/1.1.0/contracts/orders.openapi.yaml
|
|
95
|
-
https://artifacts.example.com/artifactory/maven-releases/io/arcadia/orders-api/contracts%2Forders.openapi/1.1.0/contracts%2Forders.openapi-1.1.0.jar!/contracts/orders.openapi.yaml
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
The empty direct-service subdomain segment is removed without damaging `https://`.
|
|
99
|
-
The Artifactory URL above comes from its preset `contentUrlExpression`; declare the field only when the repository key or layout differs from `artifactory/contracts/...`.
|
|
100
|
-
|
|
101
|
-
## Runtime values
|
|
102
|
-
|
|
103
|
-
Static `config.properties` substitution runs first. It cannot override canonical values or source-local `${server}`. Runtime interpolation is literal: no functions, conditionals, nested expressions, or fallback syntax are supported.
|
|
104
|
-
|
|
105
|
-
| Variable | Value |
|
|
106
|
-
| --- | --- |
|
|
107
|
-
| `${owner.id}` | Resolved ID of the service or domain that declares the artifact. |
|
|
108
|
-
| `${owner.repository}` | Explicit repository of the service or domain artifact owner; unresolved when omitted. |
|
|
109
|
-
| `${domain.id}` | Explicit domain ID, otherwise its map key. |
|
|
110
|
-
| `${subdomain.id}` | Explicit subdomain ID, otherwise its map key; empty for direct services. |
|
|
111
|
-
| `${service.id}` | Explicit service ID, otherwise its map key. |
|
|
112
|
-
| `${service.repository}` | Explicit service repository name; unresolved when omitted. |
|
|
113
|
-
| `${domain.version}` | Explicit domain version, when declared. |
|
|
114
|
-
| `${subdomain.version}` | Explicit subdomain version, when declared. |
|
|
115
|
-
| `${service.version}` | Explicit service version, when declared. |
|
|
116
|
-
| `${artifact.version}` | Declared artifact version; artifact `version` is required. |
|
|
117
|
-
| `${artifact.path}` | Complete declared artifact path. |
|
|
118
|
-
| `${artifact.pathWithoutExtension}` | Complete artifact path with only its final extension removed. |
|
|
119
|
-
| `${artifact.name}` | Explicit non-blank artifact name only; unresolved when omitted. |
|
|
120
|
-
| `${artifact.fileName}` | Final artifact path segment, with every extension. |
|
|
121
|
-
| `${artifact.fileNameWithoutExtension}` | Filename with only its final extension removed. |
|
|
122
|
-
| `${content.path}` | Current artifact path or selected document path. |
|
|
123
|
-
| `${service.docs[key]}` | Declared document path for the literal key. |
|
|
124
|
-
| `${groupId}` | Common resolved group coordinate. |
|
|
125
|
-
| `${artifactId}` | Common resolved artifact coordinate. |
|
|
126
|
-
| `${version}` | Effective content version: `artifact.version` for an artifact, the inherited service, subdomain, or domain version for a service document. |
|
|
127
|
-
|
|
128
|
-
Services and domains may own artifacts. Owner identity and source-control location are deliberately separate; repository identity is never inferred from `owner.id`:
|
|
129
|
-
|
|
130
|
-
```yaml
|
|
131
|
-
config:
|
|
132
|
-
sources:
|
|
133
|
-
workspace:
|
|
134
|
-
basePathExpression: "../${service.repository}"
|
|
135
|
-
git:
|
|
136
|
-
provider: github
|
|
137
|
-
server: https://github.com
|
|
138
|
-
contentUrlExpression: "${server}/arcadia-editions/${service.repository}/raw/main/${content.path}"
|
|
139
|
-
maven:
|
|
140
|
-
provider: github
|
|
141
|
-
server: https://maven.pkg.github.com
|
|
142
|
-
repository: "arcadia-editions/${service.repository}"
|
|
143
|
-
domains:
|
|
144
|
-
catalog:
|
|
145
|
-
services:
|
|
146
|
-
products:
|
|
147
|
-
id: catalog.catalog-management.catalog-products
|
|
148
|
-
repository: catalog-products-api
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
`maven.repository` accepts the same runtime expressions and is resolved once per artifact, so services publishing to their own GitHub Packages repositories share a single Maven source declaration.
|
|
152
|
-
|
|
153
|
-
If `repository` is omitted, `${service.repository}` stays unresolved and any selected expression that uses it fails with the standard unresolved-runtime-variable diagnostic.
|
|
154
|
-
|
|
155
|
-
Filename behavior is exact:
|
|
156
|
-
|
|
157
|
-
| Path | `artifact.pathWithoutExtension` | `artifact.fileName` | `artifact.fileNameWithoutExtension` |
|
|
158
|
-
| --- | --- | --- | --- |
|
|
159
|
-
| `contracts/orders.openapi.yaml` | `contracts/orders.openapi` | `orders.openapi.yaml` | `orders.openapi` |
|
|
160
|
-
| `archive.tar.gz` | `archive.tar` | `archive.tar.gz` | `archive.tar` |
|
|
161
|
-
| `domain-model.zdl` | `domain-model` | `domain-model.zdl` | `domain-model` |
|
|
162
|
-
| `.gitignore` | `.gitignore` | `.gitignore` | `.gitignore` |
|
|
163
|
-
| `README` | `README` | `README` | `README` |
|
|
164
|
-
|
|
165
|
-
Documents are selected from the service map. Keys may contain letters, numbers, `.`, `_`, and `-`:
|
|
166
|
-
|
|
167
|
-
```text
|
|
168
|
-
${service.docs[summary]} = docs/SUMMARY.md
|
|
169
|
-
${service.docs[catalog]} = docs/EVENT_CATALOG.md
|
|
170
|
-
${service.docs[readme]} = docs/README.md
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
`${service.docs}` alone, an invalid lookup, or a missing key fails before I/O. Loading all docs evaluates the source URL once per entry, so `${content.path}` changes from `docs/SUMMARY.md` to `docs/EVENT_CATALOG.md` and then `docs/README.md`.
|
|
174
|
-
|
|
175
|
-
`${version}` resolves differently for the two kinds of content. For an artifact it is exactly `artifact.version`, which is a required field and never inherits from the service, subdomain, or domain. For a service document it inherits service, then subdomain, then domain. The qualified version expressions expose only their corresponding explicit declaration and do not inherit. Blank versions count as absent. YAML strings and numbers normalize to strings; `config.version` and artifact contents never supply a content version.
|
|
176
|
-
|
|
177
|
-
## Coordinates and explicit overrides
|
|
178
|
-
|
|
179
|
-
Common coordinates resolve as:
|
|
180
|
-
|
|
181
|
-
```text
|
|
182
|
-
groupId = owner.groupId, otherwise config.groupIdExpression
|
|
183
|
-
artifactId = artifact.artifactId, otherwise config.artifactIdExpression
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Defaults are `${owner.id}` and `${artifact.pathWithoutExtension}`. Coordinate expressions cannot recursively reference `${groupId}` or `${artifactId}`. Overrides are valid:
|
|
187
|
-
|
|
188
|
-
```yaml
|
|
189
|
-
domains:
|
|
190
|
-
commerce:
|
|
191
|
-
services:
|
|
192
|
-
orders:
|
|
193
|
-
groupId: io.arcadia.orders
|
|
194
|
-
artifacts:
|
|
195
|
-
- name: public-orders-api
|
|
196
|
-
artifactId: orders-openapi
|
|
197
|
-
type: openapi
|
|
198
|
-
path: contracts/orders.openapi.yaml
|
|
199
|
-
version: 1.1.0
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
`${groupId}` and `${artifactId}` can be selected by any artifact provider expression, not only Maven.
|
|
203
|
-
|
|
17
|
+
|
|
18
|
+
## Complete manifest
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
# schema-test: valid
|
|
22
|
+
# yaml-language-server: $schema=https://schemas.zenwave360.io/zenwave-architecture/1.0/schema.json
|
|
23
|
+
|
|
24
|
+
config:
|
|
25
|
+
title: Arcadia architecture
|
|
26
|
+
groupIdExpression: "io.arcadia.${service.id}"
|
|
27
|
+
|
|
28
|
+
contentResolution:
|
|
29
|
+
- workspace
|
|
30
|
+
- git
|
|
31
|
+
- apicurio
|
|
32
|
+
- artifactory
|
|
33
|
+
- maven
|
|
34
|
+
|
|
35
|
+
sources:
|
|
36
|
+
workspace:
|
|
37
|
+
basePathExpression: "../../${domain.id}/${subdomain.id}/${service.id}"
|
|
38
|
+
|
|
39
|
+
git:
|
|
40
|
+
provider: gitlab
|
|
41
|
+
server: https://gitlab.com
|
|
42
|
+
|
|
43
|
+
apicurio:
|
|
44
|
+
server: https://registry.example.com
|
|
45
|
+
|
|
46
|
+
artifactory:
|
|
47
|
+
server: https://artifacts.example.com
|
|
48
|
+
|
|
49
|
+
maven:
|
|
50
|
+
provider: artifactory
|
|
51
|
+
server: https://artifacts.example.com/artifactory
|
|
52
|
+
repository: maven-releases
|
|
53
|
+
|
|
54
|
+
domains:
|
|
55
|
+
commerce:
|
|
56
|
+
version: 1.0.0
|
|
57
|
+
|
|
58
|
+
services:
|
|
59
|
+
orders:
|
|
60
|
+
id: orders-api
|
|
61
|
+
docs:
|
|
62
|
+
summary: docs/SUMMARY.md
|
|
63
|
+
catalog: docs/EVENT_CATALOG.md
|
|
64
|
+
readme: docs/README.md
|
|
65
|
+
artifacts:
|
|
66
|
+
- type: openapi
|
|
67
|
+
path: contracts/orders.openapi.yaml
|
|
68
|
+
version: 1.1.0
|
|
69
|
+
|
|
70
|
+
subdomains:
|
|
71
|
+
fulfillment:
|
|
72
|
+
version: 2.0.0
|
|
73
|
+
services:
|
|
74
|
+
shipping:
|
|
75
|
+
artifacts:
|
|
76
|
+
- type: asyncapi
|
|
77
|
+
path: contracts/shipping.asyncapi.yaml
|
|
78
|
+
version: 2.0.0
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Domains, subdomains, and services use a non-blank explicit `id` when present and otherwise use their YAML map key. A direct service has an empty `subdomain.id`. Every artifact declares its own required `version`; domain, subdomain, and service versions are optional and apply only to service documents. The primary example deliberately omits artifact `name` and `artifactId`: names are never derived from paths, while artifact IDs use their configured fallback.
|
|
82
|
+
|
|
83
|
+
For a manifest stored at `/work/architecture/manifests/zenwave-architecture.yml`, the `../../` prefix reaches `/work`; the first artifact's workspace candidate is:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
/work/commerce/orders-api/contracts/orders.openapi.yaml
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The same artifact has these remote candidates:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
https://gitlab.com/commerce/orders-api/-/raw/v1.1.0/contracts/orders.openapi.yaml
|
|
93
|
+
https://registry.example.com/apis/registry/v3/groups/orders-api/artifacts/contracts%2Forders.openapi.yaml/versions/1.1.0/content
|
|
94
|
+
https://artifacts.example.com/artifactory/contracts/commerce/orders-api/1.1.0/contracts/orders.openapi.yaml
|
|
95
|
+
https://artifacts.example.com/artifactory/maven-releases/io/arcadia/orders-api/contracts%2Forders.openapi/1.1.0/contracts%2Forders.openapi-1.1.0.jar!/contracts/orders.openapi.yaml
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The empty direct-service subdomain segment is removed without damaging `https://`.
|
|
99
|
+
The Artifactory URL above comes from its preset `contentUrlExpression`; declare the field only when the repository key or layout differs from `artifactory/contracts/...`.
|
|
100
|
+
|
|
101
|
+
## Runtime values
|
|
102
|
+
|
|
103
|
+
Static `config.properties` substitution runs first. It cannot override canonical values or source-local `${server}`. Runtime interpolation is literal: no functions, conditionals, nested expressions, or fallback syntax are supported.
|
|
104
|
+
|
|
105
|
+
| Variable | Value |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| `${owner.id}` | Resolved ID of the service or domain that declares the artifact. |
|
|
108
|
+
| `${owner.repository}` | Explicit repository of the service or domain artifact owner; unresolved when omitted. |
|
|
109
|
+
| `${domain.id}` | Explicit domain ID, otherwise its map key. |
|
|
110
|
+
| `${subdomain.id}` | Explicit subdomain ID, otherwise its map key; empty for direct services. |
|
|
111
|
+
| `${service.id}` | Explicit service ID, otherwise its map key. |
|
|
112
|
+
| `${service.repository}` | Explicit service repository name; unresolved when omitted. |
|
|
113
|
+
| `${domain.version}` | Explicit domain version, when declared. |
|
|
114
|
+
| `${subdomain.version}` | Explicit subdomain version, when declared. |
|
|
115
|
+
| `${service.version}` | Explicit service version, when declared. |
|
|
116
|
+
| `${artifact.version}` | Declared artifact version; artifact `version` is required. |
|
|
117
|
+
| `${artifact.path}` | Complete declared artifact path. |
|
|
118
|
+
| `${artifact.pathWithoutExtension}` | Complete artifact path with only its final extension removed. |
|
|
119
|
+
| `${artifact.name}` | Explicit non-blank artifact name only; unresolved when omitted. |
|
|
120
|
+
| `${artifact.fileName}` | Final artifact path segment, with every extension. |
|
|
121
|
+
| `${artifact.fileNameWithoutExtension}` | Filename with only its final extension removed. |
|
|
122
|
+
| `${content.path}` | Current artifact path or selected document path. |
|
|
123
|
+
| `${service.docs[key]}` | Declared document path for the literal key. |
|
|
124
|
+
| `${groupId}` | Common resolved group coordinate. |
|
|
125
|
+
| `${artifactId}` | Common resolved artifact coordinate. |
|
|
126
|
+
| `${version}` | Effective content version: `artifact.version` for an artifact, the inherited service, subdomain, or domain version for a service document. |
|
|
127
|
+
|
|
128
|
+
Services and domains may own artifacts. Owner identity and source-control location are deliberately separate; repository identity is never inferred from `owner.id`:
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
config:
|
|
132
|
+
sources:
|
|
133
|
+
workspace:
|
|
134
|
+
basePathExpression: "../${service.repository}"
|
|
135
|
+
git:
|
|
136
|
+
provider: github
|
|
137
|
+
server: https://github.com
|
|
138
|
+
contentUrlExpression: "${server}/arcadia-editions/${service.repository}/raw/main/${content.path}"
|
|
139
|
+
maven:
|
|
140
|
+
provider: github
|
|
141
|
+
server: https://maven.pkg.github.com
|
|
142
|
+
repository: "arcadia-editions/${service.repository}"
|
|
143
|
+
domains:
|
|
144
|
+
catalog:
|
|
145
|
+
services:
|
|
146
|
+
products:
|
|
147
|
+
id: catalog.catalog-management.catalog-products
|
|
148
|
+
repository: catalog-products-api
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`maven.repository` accepts the same runtime expressions and is resolved once per artifact, so services publishing to their own GitHub Packages repositories share a single Maven source declaration.
|
|
152
|
+
|
|
153
|
+
If `repository` is omitted, `${service.repository}` stays unresolved and any selected expression that uses it fails with the standard unresolved-runtime-variable diagnostic.
|
|
154
|
+
|
|
155
|
+
Filename behavior is exact:
|
|
156
|
+
|
|
157
|
+
| Path | `artifact.pathWithoutExtension` | `artifact.fileName` | `artifact.fileNameWithoutExtension` |
|
|
158
|
+
| --- | --- | --- | --- |
|
|
159
|
+
| `contracts/orders.openapi.yaml` | `contracts/orders.openapi` | `orders.openapi.yaml` | `orders.openapi` |
|
|
160
|
+
| `archive.tar.gz` | `archive.tar` | `archive.tar.gz` | `archive.tar` |
|
|
161
|
+
| `domain-model.zdl` | `domain-model` | `domain-model.zdl` | `domain-model` |
|
|
162
|
+
| `.gitignore` | `.gitignore` | `.gitignore` | `.gitignore` |
|
|
163
|
+
| `README` | `README` | `README` | `README` |
|
|
164
|
+
|
|
165
|
+
Documents are selected from the service map. Keys may contain letters, numbers, `.`, `_`, and `-`:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
${service.docs[summary]} = docs/SUMMARY.md
|
|
169
|
+
${service.docs[catalog]} = docs/EVENT_CATALOG.md
|
|
170
|
+
${service.docs[readme]} = docs/README.md
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`${service.docs}` alone, an invalid lookup, or a missing key fails before I/O. Loading all docs evaluates the source URL once per entry, so `${content.path}` changes from `docs/SUMMARY.md` to `docs/EVENT_CATALOG.md` and then `docs/README.md`.
|
|
174
|
+
|
|
175
|
+
`${version}` resolves differently for the two kinds of content. For an artifact it is exactly `artifact.version`, which is a required field and never inherits from the service, subdomain, or domain. For a service document it inherits service, then subdomain, then domain. The qualified version expressions expose only their corresponding explicit declaration and do not inherit. Blank versions count as absent. YAML strings and numbers normalize to strings; `config.version` and artifact contents never supply a content version.
|
|
176
|
+
|
|
177
|
+
## Coordinates and explicit overrides
|
|
178
|
+
|
|
179
|
+
Common coordinates resolve as:
|
|
180
|
+
|
|
181
|
+
```text
|
|
182
|
+
groupId = owner.groupId, otherwise config.groupIdExpression
|
|
183
|
+
artifactId = artifact.artifactId, otherwise config.artifactIdExpression
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Defaults are `${owner.id}` and `${artifact.pathWithoutExtension}`. Coordinate expressions cannot recursively reference `${groupId}` or `${artifactId}`. Overrides are valid:
|
|
187
|
+
|
|
188
|
+
```yaml
|
|
189
|
+
domains:
|
|
190
|
+
commerce:
|
|
191
|
+
services:
|
|
192
|
+
orders:
|
|
193
|
+
groupId: io.arcadia.orders
|
|
194
|
+
artifacts:
|
|
195
|
+
- name: public-orders-api
|
|
196
|
+
artifactId: orders-openapi
|
|
197
|
+
type: openapi
|
|
198
|
+
path: contracts/orders.openapi.yaml
|
|
199
|
+
version: 1.1.0
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`${groupId}` and `${artifactId}` can be selected by any artifact provider expression, not only Maven.
|
|
203
|
+
|
|
204
204
|
## Artifact catalog and selections
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
`ManifestArtifactCatalog` resolves every declared artifact together with its owner and effective
|
|
207
207
|
coordinates. Declared artifact `type` values remain an open string namespace: `openapi`,
|
|
208
208
|
`asyncapi`, `zdl`, `zfl`, `grpc`, and future types require no registration with the library.
|
|
@@ -285,26 +285,26 @@ one owner:
|
|
|
285
285
|
|
|
286
286
|
```kotlin
|
|
287
287
|
val owner = ManifestOwnerSelector.Repository("orders-api")
|
|
288
|
-
val openApis = catalog.resolveByType(owner, "openapi").artifacts
|
|
289
|
-
val contract = catalog.resolveByArtifactId(owner, "contracts/orders").artifact
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
Type resolution also supports library-defined virtual behavior. `asyncapi-all` selects every
|
|
293
|
-
declared `asyncapi` and `asyncapi-client` artifact on exactly one service and returns the concrete
|
|
294
|
-
members; it is never inserted into `ZenWaveManifest.artifacts`.
|
|
295
|
-
|
|
296
|
-
```kotlin
|
|
297
|
-
val catalog = ManifestArtifactCatalog.resolve(manifest, loader)
|
|
298
|
-
val selection = catalog.resolve(
|
|
299
|
-
ManifestArtifactSelector.typeInRepository(
|
|
300
|
-
"orders-api",
|
|
301
|
-
ManifestArtifactSelector.ASYNCAPI_ALL,
|
|
302
|
-
),
|
|
303
|
-
)
|
|
304
|
-
val bundleMembers: List<ResolvedManifestArtifact> = selection.artifacts
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
Repository selectors may generally span several owners. An artifact-ID selector must resolve one
|
|
288
|
+
val openApis = catalog.resolveByType(owner, "openapi").artifacts
|
|
289
|
+
val contract = catalog.resolveByArtifactId(owner, "contracts/orders").artifact
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Type resolution also supports library-defined virtual behavior. `asyncapi-all` selects every
|
|
293
|
+
declared `asyncapi` and `asyncapi-client` artifact on exactly one service and returns the concrete
|
|
294
|
+
members; it is never inserted into `ZenWaveManifest.artifacts`.
|
|
295
|
+
|
|
296
|
+
```kotlin
|
|
297
|
+
val catalog = ManifestArtifactCatalog.resolve(manifest, loader)
|
|
298
|
+
val selection = catalog.resolve(
|
|
299
|
+
ManifestArtifactSelector.typeInRepository(
|
|
300
|
+
"orders-api",
|
|
301
|
+
ManifestArtifactSelector.ASYNCAPI_ALL,
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
val bundleMembers: List<ResolvedManifestArtifact> = selection.artifacts
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Repository selectors may generally span several owners. An artifact-ID selector must resolve one
|
|
308
308
|
artifact. A declared type must resolve artifacts on one owner, while `asyncapi-all` must resolve one
|
|
309
309
|
matching service; missing and ambiguous selections fail with `ManifestArtifactSelectionException`.
|
|
310
310
|
|
|
@@ -346,104 +346,130 @@ workspace-cli/build/install/zenwave/bin/zenwave validate /workspace/zenwave-arch
|
|
|
346
346
|
```
|
|
347
347
|
|
|
348
348
|
## Source-aware editing
|
|
349
|
-
|
|
350
|
-
`ZenWaveManifestEditor.updateArtifactVersions` accepts one or more artifact-ID or type selectors.
|
|
351
|
-
It snapshots the root and referenced documents, resolves every selection, patches only the existing
|
|
352
|
-
version scalar ranges, and validates the complete overlay before returning document changes.
|
|
353
|
-
|
|
354
|
-
```kotlin
|
|
355
|
-
val result = editor.updateArtifactVersions(
|
|
356
|
-
manifestUri,
|
|
357
|
-
listOf(
|
|
358
|
-
ManifestArtifactVersionUpdate(
|
|
359
|
-
ManifestArtifactSelector.typeInRepository(
|
|
360
|
-
"orders-api",
|
|
361
|
-
ManifestArtifactSelector.ASYNCAPI_ALL,
|
|
362
|
-
),
|
|
363
|
-
"1.4.0",
|
|
364
|
-
),
|
|
365
|
-
),
|
|
366
|
-
)
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
The returned `ManifestDocumentTextUpdate` values preserve unrelated formatting, comments, scalar
|
|
370
|
-
quote style, and source ownership through external `$ref` documents. The editor does not persist
|
|
371
|
-
them; callers can compare `originalText` before writing. JVM and Java callers can use
|
|
372
|
-
`BlockingZenWaveManifestEditor` with the default file and HTTP(S) document reader.
|
|
373
|
-
|
|
374
|
-
`updateScalars` is the lower-level API for updating another existing owner or artifact scalar.
|
|
375
|
-
Structural edits such as adding or removing manifest nodes remain out of scope.
|
|
376
|
-
|
|
377
|
-
## Ordered reads
|
|
378
|
-
|
|
379
|
-
`contentResolution` defaults to `[workspace]`. Only listed sources participate; configuring a source does not activate it. Transport and not-found failures advance to the next applicable source. Apicurio and Maven are artifact-only and are skipped for service documents. A preferred source may reorder or restrict only active sources.
|
|
380
|
-
|
|
381
|
-
Supported absolute URIs bypass the list. Exhausted reads report redacted candidates in attempted order and the final error. Unknown sources, active unconfigured sources, invalid providers, missing required fields, and unresolved expressions fail deterministically before transport I/O where possible.
|
|
382
|
-
|
|
383
|
-
| Source | Artifacts | Service docs |
|
|
384
|
-
| --- | --- | --- |
|
|
385
|
-
| `workspace` | Yes | Yes |
|
|
386
|
-
| `git` | Yes | Yes |
|
|
387
|
-
| `apicurio` | Yes | No |
|
|
388
|
-
| `artifactory` | Yes | Yes |
|
|
389
|
-
| `maven` | Yes | No |
|
|
390
|
-
|
|
391
|
-
See [the detailed source guide](docs/source-resolution-guide.md) for provider defaults, custom Git recipes, encoding, workspace traversal, Artifactory layouts, and Maven Central JAR extraction.
|
|
392
|
-
|
|
393
|
-
## Loading API
|
|
394
|
-
|
|
395
|
-
`ZenWaveManifestLoader` is the canonical multiplatform API. Its loading operations are
|
|
396
|
-
`suspend` functions so JVM and Node.js/Kotlin callers can perform manifest, document, and
|
|
397
|
-
artifact I/O without blocking their server event loop:
|
|
398
|
-
|
|
399
|
-
```kotlin
|
|
400
|
-
val loader = ZenWaveManifestLoader()
|
|
401
|
-
val manifest = loader.load("file:///workspace/zenwave-architecture.yml") // http also work
|
|
402
|
-
val service = manifest.findService("commerce/orders")!!
|
|
403
|
-
val openApis = service.findArtifacts("openapi")
|
|
404
|
-
val text = loader.loadArtifactText(manifest, service, openApis.first())
|
|
405
|
-
val schema = loader.resolveArtifactReference(
|
|
406
|
-
manifest,
|
|
407
|
-
service,
|
|
408
|
-
openApis.first(),
|
|
409
|
-
"schemas/order.yaml",
|
|
410
|
-
)
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
Java and synchronous JVM integrations can use `BlockingZenWaveManifestLoader`. It exposes the
|
|
414
|
-
same I/O operations without coroutine continuations and accepts either `String` or `java.net.URI`
|
|
415
|
-
for root resources:
|
|
416
|
-
|
|
417
|
-
```java
|
|
418
|
-
var loader = new BlockingZenWaveManifestLoader();
|
|
419
|
-
var manifest = loader.load(URI.create("file:///workspace/zenwave-architecture.yml"));
|
|
420
|
-
var service = manifest.findService("commerce/orders");
|
|
421
|
-
var artifact = service.findArtifact("openapi");
|
|
422
|
-
var options = new ManifestLoadOptions()
|
|
423
|
-
.withPreferredSource("workspace")
|
|
424
|
-
.withFallback(true);
|
|
425
|
-
var text = loader.loadArtifactText(manifest, service, artifact, options);
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
For batch service documents, `loadServiceDocResults` preserves one result per configured
|
|
429
|
-
document, including its resolved resource or error message. `loadAvailableServiceDocs` is the
|
|
430
|
-
convenience variant for generators that only need successfully loaded content.
|
|
431
|
-
`loadServiceDocs` remains the fail-fast variant.
|
|
432
|
-
|
|
433
|
-
Candidate and reference construction remains non-blocking on the common loader. Use
|
|
434
|
-
`ManifestResolvedResource.referenceUri()` when a consumer needs a single URI-like reference,
|
|
435
|
-
including a resource stored inside an archive.
|
|
436
|
-
|
|
437
|
-
##
|
|
438
|
-
|
|
439
|
-
`manifest-core`
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
|
|
349
|
+
|
|
350
|
+
`ZenWaveManifestEditor.updateArtifactVersions` accepts one or more artifact-ID or type selectors.
|
|
351
|
+
It snapshots the root and referenced documents, resolves every selection, patches only the existing
|
|
352
|
+
version scalar ranges, and validates the complete overlay before returning document changes.
|
|
353
|
+
|
|
354
|
+
```kotlin
|
|
355
|
+
val result = editor.updateArtifactVersions(
|
|
356
|
+
manifestUri,
|
|
357
|
+
listOf(
|
|
358
|
+
ManifestArtifactVersionUpdate(
|
|
359
|
+
ManifestArtifactSelector.typeInRepository(
|
|
360
|
+
"orders-api",
|
|
361
|
+
ManifestArtifactSelector.ASYNCAPI_ALL,
|
|
362
|
+
),
|
|
363
|
+
"1.4.0",
|
|
364
|
+
),
|
|
365
|
+
),
|
|
366
|
+
)
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
The returned `ManifestDocumentTextUpdate` values preserve unrelated formatting, comments, scalar
|
|
370
|
+
quote style, and source ownership through external `$ref` documents. The editor does not persist
|
|
371
|
+
them; callers can compare `originalText` before writing. JVM and Java callers can use
|
|
372
|
+
`BlockingZenWaveManifestEditor` with the default file and HTTP(S) document reader.
|
|
373
|
+
|
|
374
|
+
`updateScalars` is the lower-level API for updating another existing owner or artifact scalar.
|
|
375
|
+
Structural edits such as adding or removing manifest nodes remain out of scope.
|
|
376
|
+
|
|
377
|
+
## Ordered reads
|
|
378
|
+
|
|
379
|
+
`contentResolution` defaults to `[workspace]`. Only listed sources participate; configuring a source does not activate it. Transport and not-found failures advance to the next applicable source. Apicurio and Maven are artifact-only and are skipped for service documents. A preferred source may reorder or restrict only active sources.
|
|
380
|
+
|
|
381
|
+
Supported absolute URIs bypass the list. Exhausted reads report redacted candidates in attempted order and the final error. Unknown sources, active unconfigured sources, invalid providers, missing required fields, and unresolved expressions fail deterministically before transport I/O where possible.
|
|
382
|
+
|
|
383
|
+
| Source | Artifacts | Service docs |
|
|
384
|
+
| --- | --- | --- |
|
|
385
|
+
| `workspace` | Yes | Yes |
|
|
386
|
+
| `git` | Yes | Yes |
|
|
387
|
+
| `apicurio` | Yes | No |
|
|
388
|
+
| `artifactory` | Yes | Yes |
|
|
389
|
+
| `maven` | Yes | No |
|
|
390
|
+
|
|
391
|
+
See [the detailed source guide](docs/source-resolution-guide.md) for provider defaults, custom Git recipes, encoding, workspace traversal, Artifactory layouts, and Maven Central JAR extraction.
|
|
392
|
+
|
|
393
|
+
## Loading API
|
|
394
|
+
|
|
395
|
+
`ZenWaveManifestLoader` is the canonical multiplatform API. Its loading operations are
|
|
396
|
+
`suspend` functions so JVM and Node.js/Kotlin callers can perform manifest, document, and
|
|
397
|
+
artifact I/O without blocking their server event loop:
|
|
398
|
+
|
|
399
|
+
```kotlin
|
|
400
|
+
val loader = ZenWaveManifestLoader()
|
|
401
|
+
val manifest = loader.load("file:///workspace/zenwave-architecture.yml") // http also work
|
|
402
|
+
val service = manifest.findService("commerce/orders")!!
|
|
403
|
+
val openApis = service.findArtifacts("openapi")
|
|
404
|
+
val text = loader.loadArtifactText(manifest, service, openApis.first())
|
|
405
|
+
val schema = loader.resolveArtifactReference(
|
|
406
|
+
manifest,
|
|
407
|
+
service,
|
|
408
|
+
openApis.first(),
|
|
409
|
+
"schemas/order.yaml",
|
|
410
|
+
)
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Java and synchronous JVM integrations can use `BlockingZenWaveManifestLoader`. It exposes the
|
|
414
|
+
same I/O operations without coroutine continuations and accepts either `String` or `java.net.URI`
|
|
415
|
+
for root resources:
|
|
416
|
+
|
|
417
|
+
```java
|
|
418
|
+
var loader = new BlockingZenWaveManifestLoader();
|
|
419
|
+
var manifest = loader.load(URI.create("file:///workspace/zenwave-architecture.yml"));
|
|
420
|
+
var service = manifest.findService("commerce/orders");
|
|
421
|
+
var artifact = service.findArtifact("openapi");
|
|
422
|
+
var options = new ManifestLoadOptions()
|
|
423
|
+
.withPreferredSource("workspace")
|
|
424
|
+
.withFallback(true);
|
|
425
|
+
var text = loader.loadArtifactText(manifest, service, artifact, options);
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
For batch service documents, `loadServiceDocResults` preserves one result per configured
|
|
429
|
+
document, including its resolved resource or error message. `loadAvailableServiceDocs` is the
|
|
430
|
+
convenience variant for generators that only need successfully loaded content.
|
|
431
|
+
`loadServiceDocs` remains the fail-fast variant.
|
|
432
|
+
|
|
433
|
+
Candidate and reference construction remains non-blocking on the common loader. Use
|
|
434
|
+
`ManifestResolvedResource.referenceUri()` when a consumer needs a single URI-like reference,
|
|
435
|
+
including a resource stored inside an archive.
|
|
436
|
+
|
|
437
|
+
## Browsers and Web Workers
|
|
438
|
+
|
|
439
|
+
`manifest-core` and `manifest-graph` load and run in a browser or Web Worker with no Node runtime.
|
|
440
|
+
Supply the means of reading content: every manifest, `$ref`, document and artifact read goes
|
|
441
|
+
through the `DocumentLoader`s you pass, and nothing else is needed to load the library.
|
|
442
|
+
|
|
443
|
+
```kotlin
|
|
444
|
+
val loader = ZenWaveManifestLoader(documentLoaders = listOf(myHostReader), archiveEntryLoader = null)
|
|
445
|
+
val manifest = loader.load("https://example.com/zenwave-architecture.yml")
|
|
446
|
+
val graph = ArchitectureGraphBuilder(loader).build(manifest).graph
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
Ask what the platform offers before presenting a feature; asking never fails:
|
|
450
|
+
|
|
451
|
+
- `ManifestPlatform.capabilities()` / `isAvailable(ManifestPlatform.ARCHIVE_EXTRACTION)`: reading an
|
|
452
|
+
entry inside an archive (Maven Central/GitHub Packages JARs). Available on the JVM; not on JS unless
|
|
453
|
+
the host passes its own `ManifestArchiveEntryLoader`.
|
|
454
|
+
- `ManifestPlatform.name`: `"jvm"`, `"node"` or `"browser"`.
|
|
455
|
+
- `RefParserPlatform` (from `json-schema-ref-parser-kmp`): filesystem, classpath and HTTP reads,
|
|
456
|
+
reported separately by that library and with its own `CapabilityUnavailableException`.
|
|
457
|
+
|
|
458
|
+
A candidate that needs an unavailable manifest capability fails with
|
|
459
|
+
`ManifestCapabilityUnavailableException`, and the next content-resolution candidate is tried; if none
|
|
460
|
+
succeeds, the `ManifestResourceLoadException` names the capability. The build runs the JS test suites in headless Chromium (`jsBrowserTest`, part of
|
|
461
|
+
`check`; set `CHROME_BIN` if no Chrome, Chromium or Edge is found in a standard location).
|
|
462
|
+
|
|
463
|
+
## Kotlin module and verification
|
|
464
|
+
|
|
465
|
+
`manifest-core` contains common parsing, diagnostics, interpolation, and candidate construction for JVM and JavaScript. JVM also provides Maven Central JAR entry extraction; JavaScript hosts can supply an archive-entry loader.
|
|
466
|
+
|
|
467
|
+
Published library coordinates are `io.zenwave360.manifest:manifest-core`, `manifest-core-jvm`, and `manifest-core-js`.
|
|
468
|
+
|
|
469
|
+
Run:
|
|
470
|
+
|
|
471
|
+
```text
|
|
472
|
+
./gradlew :manifest-core:jvmTest
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
The suite validates both schemas and every complete README YAML block marked `schema-test: valid`. Release workflow details are in [RELEASING.md](RELEASING.md); this repository is licensed under the [MIT License](LICENSE).
|