@cmflow/atlas 3.4.0-beta.6 → 3.4.0-beta.8
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 +139 -7
- package/dist/bin/atlas.mjs +203 -386
- package/dist/index.d.mts +23 -2
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/routeBackendTopologyService-DkNyCtKt.mjs +815 -0
- package/dist/rules/cleanObjectRule.d.mts +1 -1
- package/dist/rules/cmsI18nFieldRule.d.mts +1 -1
- package/dist/rules/dateConversionRule.d.mts +1 -1
- package/dist/rules/lodashGetRule.d.mts +1 -1
- package/dist/rules/mappingUtilityRule.d.mts +1 -1
- package/dist/rules/mappingUtilityRule.mjs.map +1 -1
- package/dist/rules/memberGetFieldRule.d.mts +1 -1
- package/dist/rules/memberGetFieldRule.mjs.map +1 -1
- package/dist/rules/quableI18nFieldRule.d.mts +1 -1
- package/dist/{types-3y34Gf8R.d.mts → types-smD5SZe9.d.mts} +18 -3
- package/dist/workers/routeBackendTopologyWorker.mjs +29 -0
- package/knowledges/cms-and-directus-indirect-routes.md +5 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -59,11 +59,143 @@ export default defineConfig({
|
|
|
59
59
|
});
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
Atlas reads `compilerOptions.paths` from the
|
|
62
|
+
Atlas reads `compilerOptions.paths` from the `tsconfig.json` in the directory where the command is run (`process.cwd()`) and uses them as module aliases. `repoRoot` only defines the source tree to analyze and may therefore point to a subdirectory. Add `resolver.alias` only to override or complement those aliases.
|
|
63
|
+
|
|
64
|
+
## Backend sources
|
|
65
|
+
|
|
66
|
+
Atlas extracts a candidate mapping from code, then optionally consolidates it against a strict backend field reference. Configure these references in the same `analysis.backends` list used to declare backends.
|
|
67
|
+
|
|
68
|
+
A backend can be either a string or a `BackendSource` created with `defineBackendSource`:
|
|
69
|
+
|
|
70
|
+
- a string (for example `"ICC"`) has no field reference; Atlas keeps the current code-analysis and optional inference flow;
|
|
71
|
+
- a `BackendSource` provides a `resolve` function that returns the backend's known properties. Atlas assigns its `name` as `backend` on every resolved property.
|
|
72
|
+
|
|
73
|
+
The resolver returns one of the following shapes. Document-oriented backends have no route; REST backends have no document.
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
type BackendProperty =
|
|
77
|
+
| {
|
|
78
|
+
document: string;
|
|
79
|
+
field: string;
|
|
80
|
+
description?: string;
|
|
81
|
+
}
|
|
82
|
+
| {
|
|
83
|
+
route: string;
|
|
84
|
+
method: string;
|
|
85
|
+
field: string;
|
|
86
|
+
description?: string;
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The generated mapping preserves this shape. In particular, `document` is a separate property: Atlas does not turn a Quable field into an artificial path such as `products.product_geographical_area`.
|
|
91
|
+
|
|
92
|
+
### Quable
|
|
93
|
+
|
|
94
|
+
Attach rules that are specific to Quable directly to its source. They inherit the source backend automatically and their candidates are validated by the Quable property list.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { defineBackendSource, httpClient, quableI18nFieldRule } from "@cmflow/atlas";
|
|
98
|
+
|
|
99
|
+
export const quable = defineBackendSource({
|
|
100
|
+
name: "QUABLE",
|
|
101
|
+
rules: [quableI18nFieldRule],
|
|
102
|
+
resolve: async () => {
|
|
103
|
+
const documentTypes = await httpClient.get<QuableDocumentType[]>("https://quable.example/document-types");
|
|
104
|
+
|
|
105
|
+
return documentTypes.flatMap((document) =>
|
|
106
|
+
document.properties.map((property) => ({
|
|
107
|
+
document: document.code,
|
|
108
|
+
field: property.code,
|
|
109
|
+
description: "récupéré via le backend resolver"
|
|
110
|
+
}))
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For example, the resolver above may return:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
{
|
|
120
|
+
backend: "QUABLE",
|
|
121
|
+
document: "products",
|
|
122
|
+
field: "product_geographical_area",
|
|
123
|
+
description: "récupéré via le backend resolver"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### CMS Directus
|
|
128
|
+
|
|
129
|
+
CMS Directus follows the same document-oriented contract. Its `cmsI18nFieldRule` is owned by the CMS source rather than registered as a global expression rule.
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { defineBackendSource, cmsI18nFieldRule } from "@cmflow/atlas";
|
|
133
|
+
|
|
134
|
+
export const cmsDirectus = defineBackendSource({
|
|
135
|
+
name: "CMS",
|
|
136
|
+
rules: [cmsI18nFieldRule],
|
|
137
|
+
resolve: async () => directusResolver.listProperties()
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`directusResolver.listProperties()` returns items such as `{ document: "offers", field: "title", description: "…" }`.
|
|
142
|
+
|
|
143
|
+
### CMS Legacy
|
|
144
|
+
|
|
145
|
+
CMS Legacy is configured identically, with its own resolver and backend identifier. It may reuse `cmsI18nFieldRule` when the backend uses `CmsI18n` helpers.
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { defineBackendSource, cmsI18nFieldRule } from "@cmflow/atlas";
|
|
149
|
+
|
|
150
|
+
export const cmsLegacy = defineBackendSource({
|
|
151
|
+
name: "CMS_LEGACY",
|
|
152
|
+
rules: [cmsI18nFieldRule],
|
|
153
|
+
resolve: async () => cmsLegacyResolver.listProperties()
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Custom REST backend with OpenAPI
|
|
158
|
+
|
|
159
|
+
`openapiSource` reuses Atlas's OpenAPI parsing utilities: downloading the document, resolving references, traversing operations, and extracting field descriptions. A project therefore only supplies the URL.
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { defineBackendSource, openapiSource } from "@cmflow/atlas";
|
|
163
|
+
|
|
164
|
+
export const xm = defineBackendSource({
|
|
165
|
+
name: "XM",
|
|
166
|
+
resolve: () => openapiSource({ url: "https://xm.example/openapi.json" })
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
This returns entries such as:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
{
|
|
174
|
+
backend: "XM",
|
|
175
|
+
route: "/path/to",
|
|
176
|
+
method: "GET",
|
|
177
|
+
field: "path.to.field",
|
|
178
|
+
description: "Description extraite du Swagger"
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Register strings and sources together:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { defineConfig } from "@cmflow/atlas";
|
|
186
|
+
import { cmsDirectus, cmsLegacy, quable, xm } from "./backend-sources";
|
|
187
|
+
|
|
188
|
+
export default defineConfig({
|
|
189
|
+
// …other Atlas options
|
|
190
|
+
analysis: {
|
|
191
|
+
backends: ["ICC", quable, cmsDirectus, cmsLegacy, xm]
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
```
|
|
63
195
|
|
|
64
196
|
## Custom expression rules
|
|
65
197
|
|
|
66
|
-
Use `defineExpressionRule` when a project-specific helper hides a backend field or wraps an expression that Atlas should follow. Add
|
|
198
|
+
Use `defineExpressionRule` when a project-specific helper hides a backend field or wraps an expression that Atlas should follow. Add a cross-backend rule to `analysis.rules` in `atlas.config.ts`. Attach a backend-specific rule, such as `quableI18nFieldRule` or `cmsI18nFieldRule`, to `defineBackendSource({ rules: [...] })` instead.
|
|
67
199
|
|
|
68
200
|
`match` is a cheap predicate that selects the `ts-morph` expression. `parse` returns the information Atlas should use: a backend field, a transparent wrapper, or both.
|
|
69
201
|
|
|
@@ -73,8 +205,7 @@ import { Node } from "ts-morph";
|
|
|
73
205
|
|
|
74
206
|
const localizedFieldRule = defineExpressionRule({
|
|
75
207
|
name: "localized-field",
|
|
76
|
-
match: (expression) =>
|
|
77
|
-
Node.isCallExpression(expression) && expression.getExpression().getText() === "localizedField",
|
|
208
|
+
match: (expression) => Node.isCallExpression(expression) && expression.getExpression().getText() === "localizedField",
|
|
78
209
|
parse: (expression) => {
|
|
79
210
|
if (!Node.isCallExpression(expression)) return undefined;
|
|
80
211
|
|
|
@@ -119,7 +250,7 @@ Generate the topology first, then the route catalogue:
|
|
|
119
250
|
|
|
120
251
|
```bash
|
|
121
252
|
atlas --project-root /path/to/api generate:graph
|
|
122
|
-
atlas --project-root /path/to/api generate:
|
|
253
|
+
atlas --project-root /path/to/api generate:catalog --output .tmp/datasource-catalogue
|
|
123
254
|
```
|
|
124
255
|
|
|
125
256
|
Each route produces a YAML document and a `.graph.yaml` topology artifact. The catalogue requires a valid graph and leaves ambiguous fields marked `needs_review`.
|
|
@@ -151,8 +282,9 @@ Without `--write`, the command performs a dry run. Use `clean-orphans` to inspec
|
|
|
151
282
|
|
|
152
283
|
```text
|
|
153
284
|
atlas init Create atlas.config.ts
|
|
285
|
+
atlas backend-sources Execute backend sources and display resolved metadata
|
|
154
286
|
atlas generate:graph Trace API routes to backends
|
|
155
|
-
atlas generate:
|
|
287
|
+
atlas generate:catalog [route] Generate route review documents
|
|
156
288
|
atlas generate:test Check configured coverage baselines
|
|
157
289
|
atlas needs-review Rank unresolved routes
|
|
158
290
|
atlas infer [route|directory] Optionally enrich unresolved mappings
|
|
@@ -163,7 +295,7 @@ atlas report:changed Report coverage for changed routes
|
|
|
163
295
|
|
|
164
296
|
## CI
|
|
165
297
|
|
|
166
|
-
The recommended static CI flow is `generate:graph`, `generate:
|
|
298
|
+
The recommended static CI flow is `generate:graph`, `generate:catalog`, then `push`. Do not run optional inference in CI. Supply `DIRECTUS_URL` and `DIRECTUS_TOKEN` through the CI secret context; skip the push if either value is absent.
|
|
167
299
|
|
|
168
300
|
## Development
|
|
169
301
|
|