@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 CHANGED
@@ -59,11 +59,143 @@ export default defineConfig({
59
59
  });
60
60
  ```
61
61
 
62
- Atlas reads `compilerOptions.paths` from the project's `tsconfig.json` and uses them as module aliases. Add `resolver.alias` only to override or complement those aliases.
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 the rule to `analysis.rules` in `atlas.config.ts`.
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:catalogue --output .tmp/datasource-catalogue
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:catalogue [route] Generate route review documents
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:catalogue`, 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.
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