@cmflow/atlas 3.4.0-beta.8 → 3.4.0

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 (50) hide show
  1. package/README.md +110 -18
  2. package/dist/{types-smD5SZe9.d.mts → UserConfig-BlRknCRh.d.mts} +40 -15
  3. package/dist/bin/atlas.d.mts +2 -0
  4. package/dist/bin/atlas.mjs +22554 -2981
  5. package/dist/bin/atlas.mjs.map +1 -0
  6. package/dist/defineExpressionRule-GhkeHHT8.mjs +10 -0
  7. package/dist/defineExpressionRule-GhkeHHT8.mjs.map +1 -0
  8. package/dist/dist-DedUrNm2.mjs +6950 -0
  9. package/dist/dist-DedUrNm2.mjs.map +1 -0
  10. package/dist/index.d.mts +17 -6
  11. package/dist/index.mjs +1317 -1
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/rolldown-runtime-CGR6nZuH.mjs +34 -0
  14. package/dist/routeBackendTopologyService-bbiOHBq0.mjs +8769 -0
  15. package/dist/routeBackendTopologyService-bbiOHBq0.mjs.map +1 -0
  16. package/dist/rules/lodashGetRule.d.mts +2 -1
  17. package/dist/rules/lodashGetRule.mjs +23 -1
  18. package/dist/rules/lodashGetRule.mjs.map +1 -1
  19. package/dist/rules/mappingUtilityRule.d.mts +2 -1
  20. package/dist/rules/mappingUtilityRule.mjs +37 -1
  21. package/dist/rules/mappingUtilityRule.mjs.map +1 -1
  22. package/dist/rules/memberGetFieldRule.d.mts +2 -1
  23. package/dist/rules/memberGetFieldRule.mjs +26 -1
  24. package/dist/rules/memberGetFieldRule.mjs.map +1 -1
  25. package/dist/taskProgressService-BIc_o1wl.mjs +1247 -0
  26. package/dist/taskProgressService-BIc_o1wl.mjs.map +1 -0
  27. package/dist/token-CiiblKFL.mjs +62 -0
  28. package/dist/token-CiiblKFL.mjs.map +1 -0
  29. package/dist/token-util-Br4-y5kE.mjs +7 -0
  30. package/dist/token-util-Dnzm6rU4.mjs +471 -0
  31. package/dist/token-util-Dnzm6rU4.mjs.map +1 -0
  32. package/dist/workers/routeBackendTopologyWorker.d.mts +2 -0
  33. package/dist/workers/routeBackendTopologyWorker.mjs +29 -19
  34. package/dist/workers/routeBackendTopologyWorker.mjs.map +1 -0
  35. package/package.json +15 -14
  36. package/dist/defineExpressionRule-Dfvzj6n2.mjs +0 -2
  37. package/dist/defineExpressionRule-Dfvzj6n2.mjs.map +0 -1
  38. package/dist/routeBackendTopologyService-DkNyCtKt.mjs +0 -815
  39. package/dist/rules/cleanObjectRule.d.mts +0 -6
  40. package/dist/rules/cleanObjectRule.mjs +0 -2
  41. package/dist/rules/cleanObjectRule.mjs.map +0 -1
  42. package/dist/rules/cmsI18nFieldRule.d.mts +0 -12
  43. package/dist/rules/cmsI18nFieldRule.mjs +0 -2
  44. package/dist/rules/cmsI18nFieldRule.mjs.map +0 -1
  45. package/dist/rules/dateConversionRule.d.mts +0 -6
  46. package/dist/rules/dateConversionRule.mjs +0 -2
  47. package/dist/rules/dateConversionRule.mjs.map +0 -1
  48. package/dist/rules/quableI18nFieldRule.d.mts +0 -6
  49. package/dist/rules/quableI18nFieldRule.mjs +0 -2
  50. package/dist/rules/quableI18nFieldRule.mjs.map +0 -1
package/README.md CHANGED
@@ -42,7 +42,7 @@ atlas init
42
42
  atlas --config /path/to/api/atlas.config.ts init
43
43
  ```
44
44
 
45
- By default, Atlas loads `atlas.config.ts` from the directory where the command is launched. Use `--config` (or `-c`) to reference another configuration file. Use `--project-root` only to override the API project directory to analyze.
45
+ By default, Atlas loads `atlas.config.ts` from the directory where the command is launched. Use `--config` (or `-c`) to reference another configuration file. Use `--analysis-dir` only to override the API source directory to analyze.
46
46
 
47
47
  The configuration imports `defineConfig` from Atlas:
48
48
 
@@ -50,26 +50,57 @@ The configuration imports `defineConfig` from Atlas:
50
50
  import { defineConfig } from "@cmflow/atlas";
51
51
 
52
52
  export default defineConfig({
53
+ outputDir: "./tmp/atlas",
54
+ envs: {
55
+ XM_API_URL: "https://xm.example/openapi.json"
56
+ },
53
57
  openapiUrl: "https://api.example.com/openapi.json",
54
58
  openapiTimeoutMs: 60_000,
55
59
  directusUrl: "https://cms.api.clubmed",
56
60
  analysis: {
61
+ rootDir: "./app",
57
62
  backends: ["ICC", "CMS", "CMS_B2C"]
58
63
  }
59
64
  });
60
65
  ```
61
66
 
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.
67
+ `process.cwd()` is always the project root: `outputDir`, `tsconfig.json`, Git paths and serialized source paths are resolved from it. `analysis.rootDir` only defines the source tree to analyze and may therefore point to a subdirectory such as `./app`. Atlas reads `compilerOptions.paths` from the root `tsconfig.json` and uses them as module aliases. Add `resolver.alias` only to override or complement those aliases.
68
+
69
+ `outputDir` is resolved from the project root, not from `analysis.rootDir`. With the configuration above, artifacts are written to `<project-root>/tmp/atlas`, never to `<project-root>/app/tmp/atlas`.
70
+
71
+ Use `analysis.excluded` for project-root-relative technical files that must not enter dependency traversal or `analysis_files`:
72
+
73
+ ```ts
74
+ analysis: {
75
+ rootDir: "./app",
76
+ excluded: ["tools/build/*-reference.json"],
77
+ backends: [/* ... */]
78
+ }
79
+ ```
63
80
 
64
81
  ## Backend sources
65
82
 
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.
83
+ Atlas starts from accesses actually detected in code on a backend reached by the route graph. It then consolidates those code candidates against the canonical properties returned by the matching `BackendSource`. Atlas never creates a confirmed mapping from API field-name similarity alone.
84
+
85
+ For a backend with no configured source, Atlas preserves code candidates for optional AI inference. A configured source is authoritative: only its resolved properties can validate the code access.
67
86
 
68
87
  A backend can be either a string or a `BackendSource` created with `defineBackendSource`:
69
88
 
70
89
  - a string (for example `"ICC"`) has no field reference; Atlas keeps the current code-analysis and optional inference flow;
71
90
  - a `BackendSource` provides a `resolve` function that returns the backend's known properties. Atlas assigns its `name` as `backend` on every resolved property.
72
91
 
92
+ Any backend source can persist its resolved properties in a YAML cache. When the cache exists, Atlas uses it and does not call the remote source. Refresh it explicitly with `atlas backend-source --refresh` (or the compatible `atlas backend-sources --refresh`). Use `atlas backend-sources --refresh --all` to refresh every configured source without an interactive prompt.
93
+
94
+ ```ts
95
+ export const xm = defineBackendSource({
96
+ name: "XM",
97
+ cache: `${__dirname}/cache.yaml`,
98
+ resolve: () => openapiSource({ url: "https://xm.example/openapi.json" })
99
+ });
100
+ ```
101
+
102
+ 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]`.
103
+
73
104
  The resolver returns one of the following shapes. Document-oriented backends have no route; REST backends have no document.
74
105
 
75
106
  ```ts
@@ -89,12 +120,23 @@ type BackendProperty =
89
120
 
90
121
  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
122
 
123
+ ## Resolved backend metadata artifacts
124
+
125
+ At the start of `generate:graph` and `generate:catalog`, Atlas resolves every configured backend source and writes its metadata for inspection:
126
+
127
+ ```text
128
+ <outputDir>/backends/<backend>.yaml
129
+ ```
130
+
131
+ For example, `<outputDir>/backends/quable_rest.yaml` contains the source name, generation date and canonical properties returned by Quable. Backends declared as strings still receive an artifact with `resolved: false`; this makes missing metadata sources visible during analysis.
132
+
92
133
  ### Quable
93
134
 
94
135
  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
136
 
96
137
  ```ts
97
- import { defineBackendSource, httpClient, quableI18nFieldRule } from "@cmflow/atlas";
138
+ import { defineBackendSource, httpClient } from "@cmflow/atlas";
139
+ import { quableI18nFieldRule } from "./atlas-rules";
98
140
 
99
141
  export const quable = defineBackendSource({
100
142
  name: "QUABLE",
@@ -129,7 +171,8 @@ For example, the resolver above may return:
129
171
  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
172
 
131
173
  ```ts
132
- import { defineBackendSource, cmsI18nFieldRule } from "@cmflow/atlas";
174
+ import { defineBackendSource } from "@cmflow/atlas";
175
+ import { cmsI18nFieldRule } from "./atlas-rules";
133
176
 
134
177
  export const cmsDirectus = defineBackendSource({
135
178
  name: "CMS",
@@ -145,7 +188,8 @@ export const cmsDirectus = defineBackendSource({
145
188
  CMS Legacy is configured identically, with its own resolver and backend identifier. It may reuse `cmsI18nFieldRule` when the backend uses `CmsI18n` helpers.
146
189
 
147
190
  ```ts
148
- import { defineBackendSource, cmsI18nFieldRule } from "@cmflow/atlas";
191
+ import { defineBackendSource } from "@cmflow/atlas";
192
+ import { cmsI18nFieldRule } from "./atlas-rules";
149
193
 
150
194
  export const cmsLegacy = defineBackendSource({
151
195
  name: "CMS_LEGACY",
@@ -159,14 +203,52 @@ export const cmsLegacy = defineBackendSource({
159
203
  `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
204
 
161
205
  ```ts
162
- import { defineBackendSource, openapiSource } from "@cmflow/atlas";
206
+ import { constant, defineBackendSource, openapiSource } from "@cmflow/atlas";
163
207
 
164
208
  export const xm = defineBackendSource({
165
209
  name: "XM",
166
- resolve: () => openapiSource({ url: "https://xm.example/openapi.json" })
210
+ cache: `${__dirname}/xm-openapi.yaml`,
211
+ resolve: () =>
212
+ openapiSource({
213
+ url: constant<string>("XM_API_URL", "https://xm.example/openapi.json")
214
+ })
167
215
  });
168
216
  ```
169
217
 
218
+ `constant` resolves a value declared in `envs`, falling back to its second argument. No resolver context is required.
219
+
220
+ ### Environment constants
221
+
222
+ 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:
223
+
224
+ 1. Atlas uses `envs[name]` when it is set.
225
+ 2. Otherwise, it returns the supplied default value.
226
+
227
+ ```ts
228
+ import { constant, defineBackendSource, openapiSource } from "@cmflow/atlas";
229
+
230
+ export const xmBackendSource = defineBackendSource({
231
+ name: "XM",
232
+ resolve: () =>
233
+ openapiSource({
234
+ url: constant<string>("XM_API_URL", "https://xm.example/openapi.json")
235
+ })
236
+ });
237
+ ```
238
+
239
+ For example, configure the endpoint used by the source:
240
+
241
+ ```ts
242
+ export default defineConfig({
243
+ envs: {
244
+ XM_API_URL: "https://xm.internal/openapi.json"
245
+ }
246
+ // …other Atlas options
247
+ });
248
+ ```
249
+
250
+ `envs` can itself be populated from `process.env` when appropriate for the project.
251
+
170
252
  This returns entries such as:
171
253
 
172
254
  ```ts
@@ -195,7 +277,7 @@ export default defineConfig({
195
277
 
196
278
  ## Custom expression rules
197
279
 
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.
280
+ 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.
199
281
 
200
282
  `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.
201
283
 
@@ -249,23 +331,30 @@ DIRECTUS_TOKEN=replace-with-a-static-token
249
331
  Generate the topology first, then the route catalogue:
250
332
 
251
333
  ```bash
252
- atlas --project-root /path/to/api generate:graph
253
- atlas --project-root /path/to/api generate:catalog --output .tmp/datasource-catalogue
334
+ atlas --analysis-dir /path/to/api generate:graph
335
+ atlas --analysis-dir /path/to/api generate:catalog --output .tmp/datasource-catalogue
254
336
  ```
255
337
 
256
338
  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`.
257
339
 
340
+ When changing `analysis.rootDir`, backend sources or exclusions, regenerate the graph before the catalogue so the route graph and metadata artifacts use the same configuration:
341
+
342
+ ```bash
343
+ atlas generate:graph "GET /v2/products"
344
+ atlas generate:catalog "GET /v2/products"
345
+ ```
346
+
258
347
  Check configured coverage baselines:
259
348
 
260
349
  ```bash
261
- atlas --project-root /path/to/api generate:test
350
+ atlas --analysis-dir /path/to/api generate:test
262
351
  ```
263
352
 
264
353
  Review unresolved mappings or run optional AI inference:
265
354
 
266
355
  ```bash
267
- atlas --project-root /path/to/api needs-review --sort percentage --limit 25
268
- atlas --project-root /path/to/api infer .tmp/datasource-catalogue
356
+ atlas --analysis-dir /path/to/api needs-review --sort percentage --limit 25
357
+ atlas --analysis-dir /path/to/api infer .tmp/datasource-catalogue
269
358
  ```
270
359
 
271
360
  The inference pass only reads analysis files referenced by each route graph. Accepted suggestions remain marked `inferred`; suggestions below the configured confidence threshold are retained for manual review.
@@ -273,16 +362,17 @@ The inference pass only reads analysis files referenced by each route graph. Acc
273
362
  Push route artifacts to Directus with an explicit write flag:
274
363
 
275
364
  ```bash
276
- atlas --project-root /path/to/api push .tmp/datasource-catalogue --write
365
+ atlas --analysis-dir /path/to/api push .tmp/datasource-catalogue --update
277
366
  ```
278
367
 
279
- Without `--write`, the command performs a dry run. Use `clean-orphans` to inspect Directus links that no longer reference an API or backend property.
368
+ Without `--update`, the command performs a dry run. Use `clean-orphans` to inspect Directus links that no longer reference an API or backend property.
280
369
 
281
370
  ## Command reference
282
371
 
283
372
  ```text
284
373
  atlas init Create atlas.config.ts
285
- atlas backend-sources Execute backend sources and display resolved metadata
374
+ atlas backend-source [--refresh] Display backend metadata; refresh configured source caches when requested
375
+ atlas backend-sources [--refresh] [--all] Compatible plural alias; --all skips the source picker
286
376
  atlas generate:graph Trace API routes to backends
287
377
  atlas generate:catalog [route] Generate route review documents
288
378
  atlas generate:test Check configured coverage baselines
@@ -308,6 +398,8 @@ yarn workspace @cmflow/atlas test
308
398
 
309
399
  ## License
310
400
 
311
- LicenseThe MIT License (MIT)Copyright (c) 2016 - Today ClubMed
401
+ The MIT License (MIT)
402
+
403
+ Copyright (c) 2016 - Today ClubMed
312
404
 
313
405
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,5 +1,6 @@
1
+
1
2
  import { Expression } from "ts-morph";
2
- //#region src/utils/defineExpressionRule.d.ts
3
+ //#region src/fn/defineExpressionRule.d.ts
3
4
  type FieldExtractionRuleResult = {
4
5
  backendField?: string;
5
6
  transparent?: boolean;
@@ -8,17 +9,28 @@ type FieldExtractionRuleResult = {
8
9
  };
9
10
  type FieldExtractionRule = {
10
11
  name: string;
12
+ /** Higher-priority rules are evaluated first. Defaults to 0. */
13
+ priority?: number;
11
14
  match: (expression: Expression, config: UserConfig) => boolean;
12
15
  parse: (expression: Expression, config: UserConfig) => FieldExtractionRuleResult | undefined;
13
16
  };
14
17
  declare function defineExpressionRule(rule: FieldExtractionRule): FieldExtractionRule;
15
18
  //#endregion
16
- //#region src/models/types.d.ts
17
- interface NeutralExpressionMatcher {
18
- prefix: string;
19
- apiMapping?: boolean;
19
+ //#region src/interfaces/Direction.d.ts
20
+ type Direction = "input" | "output";
21
+ //#endregion
22
+ //#region src/interfaces/PropertyLocation.d.ts
23
+ type PropertyLocation = "query" | "path" | "header" | "body";
24
+ //#endregion
25
+ //#region src/interfaces/PropertyMetadata.d.ts
26
+ interface PropertyMetadata {
27
+ direction?: Direction;
28
+ location?: PropertyLocation;
29
+ type?: string;
20
30
  }
21
- type BackendProperty = {
31
+ //#endregion
32
+ //#region src/interfaces/BackendProperty.d.ts
33
+ type BackendProperty = PropertyMetadata & ({
22
34
  document: string;
23
35
  field: string;
24
36
  description?: string;
@@ -27,18 +39,27 @@ type BackendProperty = {
27
39
  method: string;
28
40
  field: string;
29
41
  description?: string;
30
- };
42
+ });
43
+ //#endregion
44
+ //#region src/interfaces/BackendSource.d.ts
31
45
  interface BackendSource {
32
46
  name: string;
47
+ /** YAML file containing resolved properties. Existing caches are read before calling `resolve`. */
48
+ cache?: string;
33
49
  resolve?: () => Promise<BackendProperty[]>;
34
50
  rules?: FieldExtractionRule[];
35
51
  }
52
+ //#endregion
53
+ //#region src/config/interfaces/UserConfig.d.ts
54
+ interface NeutralExpressionMatcher {
55
+ prefix: string;
56
+ apiMapping?: boolean;
57
+ }
36
58
  interface UserConfig {
37
- /**
38
- * Absolute path to the root of the repository to analyze (e.g. the digital-api repo).
39
- * Can be set via the ATLAS_CWD environment variable.
40
- */
41
- repoRoot?: string;
59
+ /** Values injectable into backend source resolvers through `constant`. */
60
+ envs?: Record<string, unknown>;
61
+ /** Directory where Atlas writes generated graph and catalogue artifacts, resolved from `process.cwd()`. */
62
+ outputDir: string;
42
63
  /**
43
64
  * Default OpenAPI document URL used to extract the public contract exposed by the API.
44
65
  * The CLI can still override this value with `--openapi-url`.
@@ -48,6 +69,8 @@ interface UserConfig {
48
69
  openapiTimeoutMs: number;
49
70
  /** Default Directus base URL used by `push` when no CLI option or environment variable overrides it. */
50
71
  directusUrl: string;
72
+ /** Default Directus token used by `push` when no CLI option or environment variable overrides it. */
73
+ directusToken: string;
51
74
  /**
52
75
  * Module aliases resolved while traversing static-analysis dependencies.
53
76
  * Defaults are read from `compilerOptions.paths` in the repository tsconfig.
@@ -73,10 +96,12 @@ interface UserConfig {
73
96
  * Static analysis options used to keep generated artifacts focused on business-relevant files and fields.
74
97
  */
75
98
  analysis: {
99
+ /** Directory containing the application source tree to analyze, resolved from `process.cwd()`. */
100
+ rootDir: string;
76
101
  /** Backend identifiers used by the API project. */
77
102
  backends: Array<string | BackendSource>;
78
103
  /**
79
- * Glob patterns excluded from `analysis_files`.
104
+ * Glob patterns, relative to the project working directory, excluded from `analysis_files`.
80
105
  * Use this to hide technical plumbing files that add noise to route review documents.
81
106
  */
82
107
  excluded: string[];
@@ -113,5 +138,5 @@ interface UserConfig {
113
138
  };
114
139
  }
115
140
  //#endregion
116
- export { defineExpressionRule as a, FieldExtractionRule as i, BackendSource as n, UserConfig as r, BackendProperty as t };
117
- //# sourceMappingURL=types-smD5SZe9.d.mts.map
141
+ export { defineExpressionRule as a, FieldExtractionRule as i, BackendSource as n, BackendProperty as r, UserConfig as t };
142
+ //# sourceMappingURL=UserConfig-BlRknCRh.d.mts.map
@@ -0,0 +1,2 @@
1
+
2
+ export {}