@cmflow/atlas 3.4.0-beta.2 → 3.4.0-beta.20

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 (38) hide show
  1. package/README.md +231 -5
  2. package/dist/bin/atlas.d.mts +2 -0
  3. package/dist/bin/atlas.mjs +29100 -3106
  4. package/dist/bin/atlas.mjs.map +1 -0
  5. package/dist/defineExpressionRule-GhkeHHT8.mjs +10 -0
  6. package/dist/defineExpressionRule-GhkeHHT8.mjs.map +1 -0
  7. package/dist/index.d.mts +36 -0
  8. package/dist/index.mjs +1297 -0
  9. package/dist/index.mjs.map +1 -0
  10. package/dist/propertyExtractionService-8BjqpPFa.mjs +172 -0
  11. package/dist/propertyExtractionService-8BjqpPFa.mjs.map +1 -0
  12. package/dist/rolldown-runtime-CGR6nZuH.mjs +34 -0
  13. package/dist/routeBackendTopologyService-CkOLUfcj.mjs +8728 -0
  14. package/dist/routeBackendTopologyService-CkOLUfcj.mjs.map +1 -0
  15. package/dist/rules/lodashGetRule.d.mts +7 -0
  16. package/dist/rules/lodashGetRule.mjs +24 -0
  17. package/dist/rules/lodashGetRule.mjs.map +1 -0
  18. package/dist/rules/mappingUtilityRule.d.mts +7 -0
  19. package/dist/rules/mappingUtilityRule.mjs +38 -0
  20. package/dist/rules/mappingUtilityRule.mjs.map +1 -0
  21. package/dist/rules/memberGetFieldRule.d.mts +7 -0
  22. package/dist/rules/memberGetFieldRule.mjs +27 -0
  23. package/dist/rules/memberGetFieldRule.mjs.map +1 -0
  24. package/dist/taskProgressService-CAC_RIoa.mjs +1229 -0
  25. package/dist/taskProgressService-CAC_RIoa.mjs.map +1 -0
  26. package/dist/token-CiiblKFL.mjs +62 -0
  27. package/dist/token-CiiblKFL.mjs.map +1 -0
  28. package/dist/token-util-Br4-y5kE.mjs +7 -0
  29. package/dist/token-util-Dnzm6rU4.mjs +471 -0
  30. package/dist/token-util-Dnzm6rU4.mjs.map +1 -0
  31. package/dist/types-Af0_VOnh.d.mts +122 -0
  32. package/dist/workers/routeBackendTopologyWorker.d.mts +2 -0
  33. package/dist/workers/routeBackendTopologyWorker.mjs +34 -0
  34. package/dist/workers/routeBackendTopologyWorker.mjs.map +1 -0
  35. package/knowledges/cms-and-directus-indirect-routes.md +5 -3
  36. package/package.json +18 -13
  37. package/dist/defineRule-Dfvzj6n2.mjs +0 -2
  38. package/dist/defineRule-Dfvzj6n2.mjs.map +0 -1
package/README.md CHANGED
@@ -50,13 +50,238 @@ The configuration imports `defineConfig` from Atlas:
50
50
  import { defineConfig } from "@cmflow/atlas";
51
51
 
52
52
  export default defineConfig({
53
- backendTypesFile: "app/_infra/back/BackendTypes.ts",
53
+ envs: {
54
+ XM_API_URL: "https://xm.example/openapi.json"
55
+ },
54
56
  openapiUrl: "https://api.example.com/openapi.json",
55
57
  openapiTimeoutMs: 60_000,
56
- directusUrl: "https://cms.api.clubmed"
58
+ directusUrl: "https://cms.api.clubmed",
59
+ analysis: {
60
+ backends: ["ICC", "CMS", "CMS_B2C"]
61
+ }
57
62
  });
58
63
  ```
59
64
 
65
+ 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.
66
+
67
+ ## Backend sources
68
+
69
+ 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.
70
+
71
+ A backend can be either a string or a `BackendSource` created with `defineBackendSource`:
72
+
73
+ - a string (for example `"ICC"`) has no field reference; Atlas keeps the current code-analysis and optional inference flow;
74
+ - a `BackendSource` provides a `resolve` function that returns the backend's known properties. Atlas assigns its `name` as `backend` on every resolved property.
75
+
76
+ When a string and a source share the same name, the last declaration wins. This lets a source enrich a list of backend names, for example `[..., Object.values(BackendTypes), quableBackendSource]`.
77
+
78
+ The resolver returns one of the following shapes. Document-oriented backends have no route; REST backends have no document.
79
+
80
+ ```ts
81
+ type BackendProperty =
82
+ | {
83
+ document: string;
84
+ field: string;
85
+ description?: string;
86
+ }
87
+ | {
88
+ route: string;
89
+ method: string;
90
+ field: string;
91
+ description?: string;
92
+ };
93
+ ```
94
+
95
+ 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`.
96
+
97
+ ### Quable
98
+
99
+ 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.
100
+
101
+ ```ts
102
+ import { defineBackendSource, httpClient } from "@cmflow/atlas";
103
+ import { quableI18nFieldRule } from "./atlas-rules";
104
+
105
+ export const quable = defineBackendSource({
106
+ name: "QUABLE",
107
+ rules: [quableI18nFieldRule],
108
+ resolve: async () => {
109
+ const documentTypes = await httpClient.get<QuableDocumentType[]>("https://quable.example/document-types");
110
+
111
+ return documentTypes.flatMap((document) =>
112
+ document.properties.map((property) => ({
113
+ document: document.code,
114
+ field: property.code,
115
+ description: "récupéré via le backend resolver"
116
+ }))
117
+ );
118
+ }
119
+ });
120
+ ```
121
+
122
+ For example, the resolver above may return:
123
+
124
+ ```ts
125
+ {
126
+ backend: "QUABLE",
127
+ document: "products",
128
+ field: "product_geographical_area",
129
+ description: "récupéré via le backend resolver"
130
+ }
131
+ ```
132
+
133
+ ### CMS Directus
134
+
135
+ CMS Directus follows the same document-oriented contract. Its `cmsI18nFieldRule` is owned by the CMS source rather than registered as a global expression rule.
136
+
137
+ ```ts
138
+ import { defineBackendSource } from "@cmflow/atlas";
139
+ import { cmsI18nFieldRule } from "./atlas-rules";
140
+
141
+ export const cmsDirectus = defineBackendSource({
142
+ name: "CMS",
143
+ rules: [cmsI18nFieldRule],
144
+ resolve: async () => directusResolver.listProperties()
145
+ });
146
+ ```
147
+
148
+ `directusResolver.listProperties()` returns items such as `{ document: "offers", field: "title", description: "…" }`.
149
+
150
+ ### CMS Legacy
151
+
152
+ CMS Legacy is configured identically, with its own resolver and backend identifier. It may reuse `cmsI18nFieldRule` when the backend uses `CmsI18n` helpers.
153
+
154
+ ```ts
155
+ import { defineBackendSource } from "@cmflow/atlas";
156
+ import { cmsI18nFieldRule } from "./atlas-rules";
157
+
158
+ export const cmsLegacy = defineBackendSource({
159
+ name: "CMS_LEGACY",
160
+ rules: [cmsI18nFieldRule],
161
+ resolve: async () => cmsLegacyResolver.listProperties()
162
+ });
163
+ ```
164
+
165
+ ### Custom REST backend with OpenAPI
166
+
167
+ `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.
168
+
169
+ ```ts
170
+ import { constant, defineBackendSource, openapiSource } from "@cmflow/atlas";
171
+
172
+ export const xm = defineBackendSource({
173
+ name: "XM",
174
+ resolve: () =>
175
+ openapiSource({
176
+ url: constant<string>("XM_API_URL", "https://xm.example/openapi.json")
177
+ })
178
+ });
179
+ ```
180
+
181
+ `constant` resolves a value declared in `envs`, falling back to its second argument. No resolver context is required.
182
+
183
+ ### Environment constants
184
+
185
+ Use `constant` when a backend source needs a configurable value such as a URL or an access token. Declare injected values at the root of `atlas.config.ts`; the value is resolved when the source runs:
186
+
187
+ 1. Atlas uses `envs[name]` when it is set.
188
+ 2. Otherwise, it returns the supplied default value.
189
+
190
+ ```ts
191
+ import { constant, defineBackendSource, openapiSource } from "@cmflow/atlas";
192
+
193
+ export const xmBackendSource = defineBackendSource({
194
+ name: "XM",
195
+ resolve: () =>
196
+ openapiSource({
197
+ url: constant<string>("XM_API_URL", "https://xm.example/openapi.json")
198
+ })
199
+ });
200
+ ```
201
+
202
+ For example, configure the endpoint used by the source:
203
+
204
+ ```ts
205
+ export default defineConfig({
206
+ envs: {
207
+ XM_API_URL: "https://xm.internal/openapi.json"
208
+ },
209
+ // …other Atlas options
210
+ });
211
+ ```
212
+
213
+ `envs` can itself be populated from `process.env` when appropriate for the project.
214
+
215
+ This returns entries such as:
216
+
217
+ ```ts
218
+ {
219
+ backend: "XM",
220
+ route: "/path/to",
221
+ method: "GET",
222
+ field: "path.to.field",
223
+ description: "Description extraite du Swagger"
224
+ }
225
+ ```
226
+
227
+ Register strings and sources together:
228
+
229
+ ```ts
230
+ import { defineConfig } from "@cmflow/atlas";
231
+ import { cmsDirectus, cmsLegacy, quable, xm } from "./backend-sources";
232
+
233
+ export default defineConfig({
234
+ // …other Atlas options
235
+ analysis: {
236
+ backends: ["ICC", quable, cmsDirectus, cmsLegacy, xm]
237
+ }
238
+ });
239
+ ```
240
+
241
+ ## Custom expression rules
242
+
243
+ Use `defineExpressionRule` when a project-specific helper hides a backend field or wraps an expression that Atlas should follow. Define those rules in the analyzed project, add a cross-backend rule to `analysis.rules` in `atlas.config.ts`, and attach backend-specific rules to `defineBackendSource({ rules: [...] })` instead.
244
+
245
+ `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.
246
+
247
+ ```ts
248
+ import { defineConfig, defineExpressionRule } from "@cmflow/atlas";
249
+ import { Node } from "ts-morph";
250
+
251
+ const localizedFieldRule = defineExpressionRule({
252
+ name: "localized-field",
253
+ match: (expression) => Node.isCallExpression(expression) && expression.getExpression().getText() === "localizedField",
254
+ parse: (expression) => {
255
+ if (!Node.isCallExpression(expression)) return undefined;
256
+
257
+ const [source, field] = expression.getArguments();
258
+ if (!source || !Node.isExpression(source) || !Node.isStringLiteral(field)) return undefined;
259
+
260
+ return { backendField: `${source.getText()}.${field.getLiteralValue()}` };
261
+ }
262
+ });
263
+
264
+ export default defineConfig({
265
+ // …other Atlas options
266
+ analysis: {
267
+ // …other analysis options
268
+ rules: [localizedFieldRule]
269
+ }
270
+ });
271
+ ```
272
+
273
+ For a wrapper that does not change the field path, return `transparent: true`:
274
+
275
+ ```ts
276
+ const unwrapRule = defineExpressionRule({
277
+ name: "unwrap-api-value",
278
+ match: (expression) => Node.isCallExpression(expression) && expression.getExpression().getText() === "unwrap",
279
+ parse: () => ({ transparent: true })
280
+ });
281
+ ```
282
+
283
+ `parse` may also set `mapperType` to annotate the generated mapping, or `apiMapping: true` when the helper maps an API value rather than a backend value.
284
+
60
285
  Create a `.env.local` in the target API project when pushing to Directus:
61
286
 
62
287
  ```dotenv
@@ -70,7 +295,7 @@ Generate the topology first, then the route catalogue:
70
295
 
71
296
  ```bash
72
297
  atlas --project-root /path/to/api generate:graph
73
- atlas --project-root /path/to/api generate:catalogue --output .tmp/datasource-catalogue
298
+ atlas --project-root /path/to/api generate:catalog --output .tmp/datasource-catalogue
74
299
  ```
75
300
 
76
301
  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`.
@@ -102,8 +327,9 @@ Without `--write`, the command performs a dry run. Use `clean-orphans` to inspec
102
327
 
103
328
  ```text
104
329
  atlas init Create atlas.config.ts
330
+ atlas backend-sources Execute backend sources and display resolved metadata
105
331
  atlas generate:graph Trace API routes to backends
106
- atlas generate:catalogue [route] Generate route review documents
332
+ atlas generate:catalog [route] Generate route review documents
107
333
  atlas generate:test Check configured coverage baselines
108
334
  atlas needs-review Rank unresolved routes
109
335
  atlas infer [route|directory] Optionally enrich unresolved mappings
@@ -114,7 +340,7 @@ atlas report:changed Report coverage for changed routes
114
340
 
115
341
  ## CI
116
342
 
117
- 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.
343
+ 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.
118
344
 
119
345
  ## Development
120
346
 
@@ -0,0 +1,2 @@
1
+
2
+ export {}