@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.ebaebc4
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 +2 -1
- package/api/build/build.type.d.mts +2 -2
- package/api/build/build.type.mjs +2 -2
- package/api/component/component.type.d.mts +6 -6
- package/api/component/component.type.mjs +19 -19
- package/api/discover/discover.type.d.mts +4 -4
- package/api/discover/discover.type.mjs +10 -10
- package/api/docs/_adapter.d.mts +37 -24
- package/api/docs/_adapter.mjs +169 -83
- package/api/docs/compiled-topics.test.mjs +78 -0
- package/api/docs/detail/detail.mjs +14 -63
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +44 -20
- package/api/docs/detail/section/section.test.mjs +41 -0
- package/api/docs/docs.d.mts +7 -2
- package/api/docs/docs.doc.mjs +27 -10
- package/api/docs/docs.mjs +16 -9
- package/api/docs/docs.test.mjs +6 -0
- package/api/docs/docs.type.d.mts +40 -3
- package/api/docs/docs.type.mjs +36 -8
- package/api/docs/index/index.d.mts +18 -0
- package/api/docs/index/index.mjs +32 -0
- package/api/docs/index/index.test.mjs +62 -0
- package/api/docs/integrationDocs.test.mjs +106 -0
- package/api/doctor/doctor.d.mts +48 -0
- package/api/doctor/doctor.mjs +232 -0
- package/api/doctor/doctor.test.mjs +196 -0
- package/api/hook/hook.type.d.mts +3 -3
- package/api/hook/hook.type.mjs +11 -11
- package/api/hook/list/list.d.mts +1 -1
- package/api/integration/add-contribution.mjs +5 -3
- package/api/integration/add-contribution.test.mjs +4 -4
- package/api/integration/integration-authoring.type.d.mts +1 -1
- package/api/integration/pack-check.mjs +49 -7
- package/api/integration/pack-check.test.mjs +249 -0
- package/api/search/search.d.mts +1 -1
- package/api/search/search.mjs +5 -5
- package/api/search/search.type.d.mts +2 -2
- package/api/search/search.type.mjs +1 -1
- package/api/swizzle/swizzle.type.d.mts +2 -2
- package/api/swizzle/swizzle.type.mjs +2 -2
- package/api/template/template.d.mts +1 -1
- package/api/template/template.type.d.mts +6 -6
- package/api/template/template.type.mjs +12 -12
- package/api/theme/build/build.mjs +20 -6
- package/api/theme/build/build.test.mjs +127 -0
- package/api/theme/palette/generate/generate.mjs +1 -1
- package/api/theme/palette/generate/generator.d.mts +10 -13
- package/api/theme/palette/generate/generator.mjs +7 -3
- package/api/theme/theme.type.d.mts +170 -11
- package/api/theme/theme.type.mjs +94 -27
- package/api/upgrade/_adapter.mjs +71 -5
- package/api/upgrade/project-context.test.mjs +272 -0
- package/api/upgrade/upgrade.doc.mjs +4 -3
- package/api/upgrade/upgrade.type.d.mts +5 -5
- package/api/upgrade/upgrade.type.mjs +11 -11
- package/assets/codemods/integration-discovery.mjs +40 -2
- package/assets/codemods/integration-discovery.test.mjs +58 -0
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
- package/assets/docs/README.md +9 -0
- package/assets/docs/authoring.doc.mjs +14 -0
- package/assets/docs/cli-integrations.doc.mjs +86 -15
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- package/authoring/_shared/contract.ts +22 -0
- package/authoring/codemod/codemod.doc.mjs +6 -1
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +8 -6
- package/authoring/config/parse.d.mts +13 -13
- package/authoring/config/parse.mjs +8 -8
- package/authoring/config/type.ts +3 -3
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/debug/parse.mjs +3 -3
- package/authoring/doctypes/_schema.d.mts +788 -23
- package/authoring/doctypes/_schema.mjs +492 -39
- package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +62 -0
- package/authoring/doctypes/base/type.ts +40 -0
- package/authoring/doctypes/command/command.doc.mjs +3 -2
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +3 -2
- package/authoring/doctypes/component/component.doc.mjs +6 -3
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +4 -3
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +3 -1
- package/authoring/doctypes/function/function.doc.mjs +4 -0
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +6 -2
- package/authoring/doctypes/hook/hook.doc.mjs +4 -0
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +3 -2
- package/authoring/doctypes/legacy.d.mts +8 -6
- package/authoring/doctypes/legacy.mjs +5 -4
- package/authoring/doctypes/load-contract.test.mjs +207 -0
- package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +132 -0
- package/authoring/doctypes/namespace/parse.d.mts +12 -0
- package/authoring/doctypes/namespace/parse.mjs +25 -0
- package/authoring/doctypes/namespace/parse.test.mjs +165 -0
- package/authoring/doctypes/namespace/type.ts +71 -0
- package/authoring/doctypes/parse.d.mts +20 -18
- package/authoring/doctypes/parse.mjs +16 -10
- package/authoring/doctypes/parse.test.mjs +77 -3
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +8 -5
- package/authoring/doctypes/reference/reference.doc.mjs +17 -4
- package/authoring/doctypes/reference/type.ts +51 -5
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +3 -2
- package/authoring/doctypes/template/parse.d.mts +92 -1
- package/authoring/doctypes/template/parse.mjs +36 -2
- package/authoring/doctypes/template/parse.test.mjs +8 -2
- package/authoring/doctypes/template/template.doc.mjs +4 -0
- package/authoring/doctypes/template/type.ts +5 -2
- package/authoring/doctypes/types.ts +10 -9
- package/authoring/gap-report/parse.d.mts +10 -10
- package/authoring/gap-report/parse.mjs +6 -6
- package/authoring/gap-report/type.ts +1 -1
- package/authoring/identity/identity.doc.d.mts +9 -0
- package/authoring/identity/identity.doc.mjs +61 -0
- package/authoring/identity/type.ts +132 -0
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +49 -17
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +13 -6
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +10 -1
- package/authoring/integration/schema.d.mts +6 -4
- package/authoring/integration/schema.mjs +9 -3
- package/authoring/integration/type.ts +23 -6
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/commands/docs.doc.mjs +13 -3
- package/clients/cli/commands/docs.mjs +121 -21
- package/clients/cli/commands/docs.test.mjs +88 -0
- package/clients/cli/commands/integration-authoring.test.mjs +13 -9
- package/clients/cli/commands/theme-palette-generate.doc.mjs +8 -4
- package/clients/cli/commands/upgrade.doc.mjs +2 -2
- package/clients/cli/formatters/index.mjs +162 -1
- package/clients/cli/formatters/index.test.mjs +91 -0
- package/clients/cli/lib/manifest.mjs +7 -2
- package/foundation/config/project.mjs +21 -6
- package/foundation/discovery/authoring-self-docs.d.mts +69 -0
- package/foundation/discovery/authoring-self-docs.mjs +214 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +154 -0
- package/foundation/discovery/component-discovery.d.mts +1 -1
- package/foundation/discovery/component-discovery.mjs +2 -1
- package/foundation/discovery/docs-discovery.d.mts +11 -4
- package/foundation/discovery/docs-discovery.mjs +208 -88
- package/foundation/discovery/docs-discovery.test.mjs +279 -13
- package/foundation/discovery/docs-output-budget.d.mts +28 -0
- package/foundation/discovery/docs-output-budget.mjs +50 -0
- package/foundation/discovery/docs-section-key.d.mts +98 -0
- package/foundation/discovery/docs-section-key.mjs +221 -0
- package/foundation/discovery/docs-section-key.test.mjs +224 -0
- package/foundation/discovery/template-adapter.mjs +2 -1
- package/foundation/discovery/theming-targets.test.mjs +4 -0
- package/foundation/doc-compiler/compile.d.mts +162 -0
- package/foundation/doc-compiler/compile.mjs +262 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +687 -0
- package/foundation/doc-compiler/ir.d.mts +9 -0
- package/foundation/doc-compiler/ir.mjs +287 -0
- package/foundation/doc-compiler/lenses.d.mts +33 -0
- package/foundation/doc-compiler/lenses.mjs +127 -0
- package/foundation/identity/provider-identity.d.mts +90 -0
- package/foundation/identity/provider-identity.mjs +320 -0
- package/foundation/identity/provider-identity.test.mjs +254 -0
- package/foundation/identity/providers.d.mts +7 -0
- package/foundation/identity/providers.mjs +16 -0
- package/foundation/integrations/autolink.mjs +12 -5
- package/foundation/integrations/integration-warnings.mjs +6 -0
- package/foundation/integrations/integrations.d.mts +46 -2
- package/foundation/integrations/integrations.mjs +167 -8
- package/foundation/integrations/integrations.test.mjs +384 -1
- package/foundation/integrations/provider-conflicts.test.mjs +125 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +10 -0
- package/foundation/response/json-contract.test.mjs +46 -17
- package/foundation/response/response-types.doc.mjs +6 -1
- package/package.json +9 -11
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
2
|
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Resolve provider identity across loaded integrations, in precedence order.
|
|
6
|
+
*
|
|
7
|
+
* Artifact and document IDs are provider-scoped, so two packages cannot both
|
|
8
|
+
* contribute under one provider ID. The same package reached twice (an npm
|
|
9
|
+
* alias beside the package it aliases, with the same name and version) loads
|
|
10
|
+
* once. Any other later claimant, including the same package at another
|
|
11
|
+
* version, stays as an inert entry that carries the conflict. The package being
|
|
12
|
+
* authored claims its ID before precedence order is considered, because the
|
|
13
|
+
* source being edited is authoritative. The winner still contributes; Project
|
|
14
|
+
* issues, Doctor, and the per-command warning name the one set aside instead of
|
|
15
|
+
* dropping it without a word.
|
|
16
|
+
*
|
|
17
|
+
* @param {LoadedIntegration[]} integrations in precedence order
|
|
18
|
+
* @returns {LoadedIntegration[]}
|
|
19
|
+
*/
|
|
20
|
+
export function markProviderConflicts(integrations: LoadedIntegration[]): LoadedIntegration[];
|
|
4
21
|
/**
|
|
5
22
|
* Return the conventional root manifest paths present in `dir`, in
|
|
6
23
|
* load-precedence order. Unlike {@link resolveManifestPath} this never throws —
|
|
@@ -75,12 +92,15 @@ export function loadLocalIntegration(packageDir: string, { fresh }?: {
|
|
|
75
92
|
* Load configured integrations.
|
|
76
93
|
*
|
|
77
94
|
* @param {string[]} [specs] package names
|
|
78
|
-
* @param {{cwd?: string, fresh?: boolean}} [options]
|
|
95
|
+
* @param {{cwd?: string, fresh?: boolean, resolveProviders?: boolean}} [options]
|
|
96
|
+
* `resolveProviders: false` leaves provider identity to a caller that
|
|
97
|
+
* resolves it once over a larger set (Project.load)
|
|
79
98
|
* @returns {Promise<LoadedIntegration[]>}
|
|
80
99
|
*/
|
|
81
|
-
export function loadIntegrations(specs?: string[], { cwd, fresh }?: {
|
|
100
|
+
export function loadIntegrations(specs?: string[], { cwd, fresh, resolveProviders }?: {
|
|
82
101
|
cwd?: string;
|
|
83
102
|
fresh?: boolean;
|
|
103
|
+
resolveProviders?: boolean;
|
|
84
104
|
}): Promise<LoadedIntegration[]>;
|
|
85
105
|
/**
|
|
86
106
|
* A fully-resolved, loaded integration. Identity (`name`, `version`) comes from
|
|
@@ -89,6 +109,10 @@ export function loadIntegrations(specs?: string[], { cwd, fresh }?: {
|
|
|
89
109
|
* are internal bookkeeping used by Doctor integration validation and Project.
|
|
90
110
|
* @typedef {object} LoadedIntegration
|
|
91
111
|
* @property {string} name
|
|
112
|
+
* @property {import('../../authoring/identity/type').ProviderId} [providerId]
|
|
113
|
+
* normalized stable provider identity; absent only for a legacy unnamed local
|
|
114
|
+
* package. Unique among contributing integrations: a later claimant is kept
|
|
115
|
+
* inert with `__providerConflict` (see {@link markProviderConflicts})
|
|
92
116
|
* @property {string} [version]
|
|
93
117
|
* @property {string} [components]
|
|
94
118
|
* @property {string} [templates]
|
|
@@ -107,6 +131,10 @@ export function loadIntegrations(specs?: string[], { cwd, fresh }?: {
|
|
|
107
131
|
* @property {string} __manifestFile
|
|
108
132
|
* @property {string} [__loadError] set when the manifest failed to load/validate;
|
|
109
133
|
* such an integration contributes nothing and is surfaced via Project.issues()
|
|
134
|
+
* @property {{providerId: import('../../authoring/identity/type').ProviderId, claimedBy: string, message: string}} [__providerConflict]
|
|
135
|
+
* set on a package whose provider ID an earlier-loaded package already
|
|
136
|
+
* claims; it contributes nothing and is reported as a `duplicate_provider`
|
|
137
|
+
* warning
|
|
110
138
|
* @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
|
|
111
139
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
112
140
|
* @property {boolean} [__autolinked] loaded because the project declares the
|
|
@@ -134,6 +162,12 @@ export const MANIFEST_BASENAMES: string[];
|
|
|
134
162
|
*/
|
|
135
163
|
export type LoadedIntegration = {
|
|
136
164
|
name: string;
|
|
165
|
+
/**
|
|
166
|
+
* normalized stable provider identity; absent only for a legacy unnamed local
|
|
167
|
+
* package. Unique among contributing integrations: a later claimant is kept
|
|
168
|
+
* inert with `__providerConflict` (see {@link markProviderConflicts})
|
|
169
|
+
*/
|
|
170
|
+
providerId?: import("../../authoring/identity/type").ProviderId | undefined;
|
|
137
171
|
version?: string | undefined;
|
|
138
172
|
components?: string | undefined;
|
|
139
173
|
templates?: string | undefined;
|
|
@@ -163,6 +197,16 @@ export type LoadedIntegration = {
|
|
|
163
197
|
* such an integration contributes nothing and is surfaced via Project.issues()
|
|
164
198
|
*/
|
|
165
199
|
__loadError?: string | undefined;
|
|
200
|
+
/**
|
|
201
|
+
* set on a package whose provider ID an earlier-loaded package already
|
|
202
|
+
* claims; it contributes nothing and is reported as a `duplicate_provider`
|
|
203
|
+
* warning
|
|
204
|
+
*/
|
|
205
|
+
__providerConflict?: {
|
|
206
|
+
providerId: import("../../authoring/identity/type").ProviderId;
|
|
207
|
+
claimedBy: string;
|
|
208
|
+
message: string;
|
|
209
|
+
} | undefined;
|
|
166
210
|
/**
|
|
167
211
|
* manifest keys this CLI does not know —
|
|
168
212
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
@@ -6,13 +6,19 @@
|
|
|
6
6
|
* Integrations are PACKAGE NAMES listed in astryx.config.{ts,mjs,js}. Each
|
|
7
7
|
* package declares a single conventional root manifest sibling to its
|
|
8
8
|
* package.json — astryx.integration.{ts,mjs,js} — which contributes
|
|
9
|
-
* components/templates/codemods/docs/themes roots and an optional issuesUrl.
|
|
10
|
-
*
|
|
9
|
+
* components/templates/codemods/docs/themes roots and an optional issuesUrl.
|
|
10
|
+
* Stable provider identity and package metadata come from package.json, not the
|
|
11
|
+
* manifest.
|
|
12
|
+
*
|
|
13
|
+
* @input Integration package names, package.json files, and root manifests.
|
|
14
|
+
* @output LoadedIntegration records with normalized provider identity and roots.
|
|
15
|
+
* @position foundation/integrations — package contribution loading boundary.
|
|
11
16
|
*/
|
|
12
17
|
|
|
13
18
|
import * as fs from 'node:fs';
|
|
14
19
|
import * as path from 'node:path';
|
|
15
20
|
import {assertWithin} from '../fs/path-safety.mjs';
|
|
21
|
+
import {normalizeProviderId} from '../identity/provider-identity.mjs';
|
|
16
22
|
// The key census and contribution parsers are internal to the schema module on
|
|
17
23
|
// purpose: the public parser still validates the complete authored type, while
|
|
18
24
|
// the loader can isolate an invalid optional contribution from valid roots.
|
|
@@ -31,6 +37,10 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
|
|
|
31
37
|
* are internal bookkeeping used by Doctor integration validation and Project.
|
|
32
38
|
* @typedef {object} LoadedIntegration
|
|
33
39
|
* @property {string} name
|
|
40
|
+
* @property {import('../../authoring/identity/type').ProviderId} [providerId]
|
|
41
|
+
* normalized stable provider identity; absent only for a legacy unnamed local
|
|
42
|
+
* package. Unique among contributing integrations: a later claimant is kept
|
|
43
|
+
* inert with `__providerConflict` (see {@link markProviderConflicts})
|
|
34
44
|
* @property {string} [version]
|
|
35
45
|
* @property {string} [components]
|
|
36
46
|
* @property {string} [templates]
|
|
@@ -49,6 +59,10 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
|
|
|
49
59
|
* @property {string} __manifestFile
|
|
50
60
|
* @property {string} [__loadError] set when the manifest failed to load/validate;
|
|
51
61
|
* such an integration contributes nothing and is surfaced via Project.issues()
|
|
62
|
+
* @property {{providerId: import('../../authoring/identity/type').ProviderId, claimedBy: string, message: string}} [__providerConflict]
|
|
63
|
+
* set on a package whose provider ID an earlier-loaded package already
|
|
64
|
+
* claims; it contributes nothing and is reported as a `duplicate_provider`
|
|
65
|
+
* warning
|
|
52
66
|
* @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
|
|
53
67
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
54
68
|
* @property {boolean} [__autolinked] loaded because the project declares the
|
|
@@ -74,6 +88,137 @@ export const MANIFEST_BASENAMES = [
|
|
|
74
88
|
'astryx.integration.js',
|
|
75
89
|
];
|
|
76
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Normalize a package-owned provider ID without rejecting legacy unnamed local
|
|
93
|
+
* packages at this compatibility boundary.
|
|
94
|
+
* @param {unknown} name
|
|
95
|
+
* @returns {import('../../authoring/identity/type').ProviderId | undefined}
|
|
96
|
+
*/
|
|
97
|
+
function providerIdForPackage(name) {
|
|
98
|
+
if (typeof name !== 'string' || name.length === 0) return undefined;
|
|
99
|
+
try {
|
|
100
|
+
return normalizeProviderId(name);
|
|
101
|
+
} catch {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Resolve provider identity across loaded integrations, in precedence order.
|
|
108
|
+
*
|
|
109
|
+
* Artifact and document IDs are provider-scoped, so two packages cannot both
|
|
110
|
+
* contribute under one provider ID. The same package reached twice (an npm
|
|
111
|
+
* alias beside the package it aliases, with the same name and version) loads
|
|
112
|
+
* once. Any other later claimant, including the same package at another
|
|
113
|
+
* version, stays as an inert entry that carries the conflict. The package being
|
|
114
|
+
* authored claims its ID before precedence order is considered, because the
|
|
115
|
+
* source being edited is authoritative. The winner still contributes; Project
|
|
116
|
+
* issues, Doctor, and the per-command warning name the one set aside instead of
|
|
117
|
+
* dropping it without a word.
|
|
118
|
+
*
|
|
119
|
+
* @param {LoadedIntegration[]} integrations in precedence order
|
|
120
|
+
* @returns {LoadedIntegration[]}
|
|
121
|
+
*/
|
|
122
|
+
export function markProviderConflicts(integrations) {
|
|
123
|
+
/** @type {Map<string, LoadedIntegration>} */
|
|
124
|
+
const claims = new Map();
|
|
125
|
+
for (const integration of integrations) {
|
|
126
|
+
if (integration?.__local && claimsProvider(integration)) {
|
|
127
|
+
const providerId = /** @type {string} */ (integration.providerId);
|
|
128
|
+
if (!claims.has(providerId)) claims.set(providerId, integration);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** @type {LoadedIntegration[]} */
|
|
132
|
+
const resolved = [];
|
|
133
|
+
for (const integration of integrations) {
|
|
134
|
+
if (!claimsProvider(integration)) {
|
|
135
|
+
resolved.push(integration);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const providerId = /** @type {string} */ (integration.providerId);
|
|
139
|
+
const claimant = claims.get(providerId);
|
|
140
|
+
if (claimant == null) {
|
|
141
|
+
claims.set(providerId, integration);
|
|
142
|
+
resolved.push(integration);
|
|
143
|
+
} else if (claimant === integration) {
|
|
144
|
+
resolved.push(integration);
|
|
145
|
+
} else if (
|
|
146
|
+
claimant.name !== integration.name ||
|
|
147
|
+
claimant.version !== integration.version
|
|
148
|
+
) {
|
|
149
|
+
resolved.push(providerConflict(integration, claimant));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return resolved;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Whether an entry contributes under its provider ID: it has one, its manifest
|
|
157
|
+
* loaded, and it has not already been set aside.
|
|
158
|
+
* @param {LoadedIntegration | undefined} integration
|
|
159
|
+
* @returns {boolean}
|
|
160
|
+
*/
|
|
161
|
+
function claimsProvider(integration) {
|
|
162
|
+
return (
|
|
163
|
+
integration?.providerId != null &&
|
|
164
|
+
integration.__loadError == null &&
|
|
165
|
+
integration.__providerConflict == null
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {LoadedIntegration} integration
|
|
171
|
+
* @returns {string}
|
|
172
|
+
*/
|
|
173
|
+
function describeIntegration(integration) {
|
|
174
|
+
const id = integration.version
|
|
175
|
+
? `${integration.name}@${integration.version}`
|
|
176
|
+
: integration.name;
|
|
177
|
+
return integration.__spec && integration.__spec !== integration.name
|
|
178
|
+
? `${id} (from "${integration.__spec}")`
|
|
179
|
+
: id;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* An inert record for a package whose provider ID is already claimed. It keeps
|
|
184
|
+
* the package's identity and location for reporting, and drops every
|
|
185
|
+
* contribution root and handler.
|
|
186
|
+
* @param {LoadedIntegration} integration
|
|
187
|
+
* @param {LoadedIntegration} claimant
|
|
188
|
+
* @returns {LoadedIntegration}
|
|
189
|
+
*/
|
|
190
|
+
function providerConflict(integration, claimant) {
|
|
191
|
+
const providerId =
|
|
192
|
+
/** @type {import('../../authoring/identity/type').ProviderId} */ (
|
|
193
|
+
integration.providerId
|
|
194
|
+
);
|
|
195
|
+
const winner = describeIntegration(claimant);
|
|
196
|
+
const setAside = describeIntegration(integration);
|
|
197
|
+
const reason = claimant.__local
|
|
198
|
+
? 'is the package being authored, so it is used'
|
|
199
|
+
: 'loads first and is used';
|
|
200
|
+
return {
|
|
201
|
+
name: integration.name,
|
|
202
|
+
providerId,
|
|
203
|
+
version: integration.version,
|
|
204
|
+
__spec: integration.__spec,
|
|
205
|
+
__packageDir: integration.__packageDir,
|
|
206
|
+
__manifestFile: integration.__manifestFile,
|
|
207
|
+
...(integration.__local ? {__local: true} : {}),
|
|
208
|
+
...(integration.__autolinked
|
|
209
|
+
? {__autolinked: true, __dependencyField: integration.__dependencyField}
|
|
210
|
+
: {}),
|
|
211
|
+
__providerConflict: {
|
|
212
|
+
providerId,
|
|
213
|
+
claimedBy: claimant.name,
|
|
214
|
+
message:
|
|
215
|
+
`${setAside} and ${winner} both claim provider ID "${providerId}". ` +
|
|
216
|
+
`${winner} ${reason}; ${setAside} contributes nothing ` +
|
|
217
|
+
'until one package changes its providerId.',
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
77
222
|
/**
|
|
78
223
|
* Return the conventional root manifest paths present in `dir`, in
|
|
79
224
|
* load-precedence order. Unlike {@link resolveManifestPath} this never throws —
|
|
@@ -274,6 +419,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
274
419
|
typeof pkg.name === 'string' && pkg.name.length > 0
|
|
275
420
|
? pkg.name
|
|
276
421
|
: '(local integration)';
|
|
422
|
+
const packageProviderId = providerIdForPackage(pkg.name);
|
|
277
423
|
const manifestFile = resolveManifestPath(packageDir, spec);
|
|
278
424
|
|
|
279
425
|
let manifest;
|
|
@@ -299,6 +445,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
299
445
|
} catch (err) {
|
|
300
446
|
return {
|
|
301
447
|
name: spec,
|
|
448
|
+
...(packageProviderId == null ? {} : {providerId: packageProviderId}),
|
|
302
449
|
version: pkg.version,
|
|
303
450
|
__spec: spec,
|
|
304
451
|
__packageDir: packageDir,
|
|
@@ -308,6 +455,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
308
455
|
};
|
|
309
456
|
}
|
|
310
457
|
|
|
458
|
+
const providerId = providerIdForPackage(manifest.providerId ?? pkg.name);
|
|
459
|
+
|
|
311
460
|
/** @param {string | null | undefined} value */
|
|
312
461
|
const resolveRoot = value => {
|
|
313
462
|
if (value == null) return undefined;
|
|
@@ -320,6 +469,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
320
469
|
|
|
321
470
|
return {
|
|
322
471
|
name: spec,
|
|
472
|
+
...(providerId == null ? {} : {providerId}),
|
|
323
473
|
version: pkg.version,
|
|
324
474
|
components: resolveRoot(manifest.components),
|
|
325
475
|
templates: resolveRoot(manifest.templates),
|
|
@@ -345,20 +495,22 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
345
495
|
* Load configured integrations.
|
|
346
496
|
*
|
|
347
497
|
* @param {string[]} [specs] package names
|
|
348
|
-
* @param {{cwd?: string, fresh?: boolean}} [options]
|
|
498
|
+
* @param {{cwd?: string, fresh?: boolean, resolveProviders?: boolean}} [options]
|
|
499
|
+
* `resolveProviders: false` leaves provider identity to a caller that
|
|
500
|
+
* resolves it once over a larger set (Project.load)
|
|
349
501
|
* @returns {Promise<LoadedIntegration[]>}
|
|
350
502
|
*/
|
|
351
503
|
export async function loadIntegrations(
|
|
352
504
|
specs = [],
|
|
353
|
-
{cwd = process.cwd(), fresh = false} = {},
|
|
505
|
+
{cwd = process.cwd(), fresh = false, resolveProviders = true} = {},
|
|
354
506
|
) {
|
|
355
507
|
/** @type {LoadedIntegration[]} */
|
|
356
508
|
const integrations = [];
|
|
357
|
-
const
|
|
509
|
+
const seenSpecs = new Set();
|
|
358
510
|
|
|
359
511
|
for (const spec of specs) {
|
|
360
|
-
if (!spec ||
|
|
361
|
-
|
|
512
|
+
if (!spec || seenSpecs.has(spec)) continue;
|
|
513
|
+
seenSpecs.add(spec);
|
|
362
514
|
|
|
363
515
|
const packageDir = resolvePackageDir(spec, cwd);
|
|
364
516
|
const pkgPath = path.join(packageDir, 'package.json');
|
|
@@ -371,6 +523,7 @@ export async function loadIntegrations(
|
|
|
371
523
|
);
|
|
372
524
|
}
|
|
373
525
|
|
|
526
|
+
const packageProviderId = providerIdForPackage(pkg.name ?? spec);
|
|
374
527
|
const manifestFile = resolveManifestPath(packageDir, spec);
|
|
375
528
|
let manifest;
|
|
376
529
|
/** @type {string[]} */
|
|
@@ -399,6 +552,7 @@ export async function loadIntegrations(
|
|
|
399
552
|
// discovery loops naturally skip it (no components/templates/codemods).
|
|
400
553
|
integrations.push({
|
|
401
554
|
name: pkg.name ?? spec,
|
|
555
|
+
...(packageProviderId == null ? {} : {providerId: packageProviderId}),
|
|
402
556
|
version: pkg.version,
|
|
403
557
|
__spec: spec,
|
|
404
558
|
__packageDir: packageDir,
|
|
@@ -408,6 +562,10 @@ export async function loadIntegrations(
|
|
|
408
562
|
continue;
|
|
409
563
|
}
|
|
410
564
|
|
|
565
|
+
const providerId = providerIdForPackage(
|
|
566
|
+
manifest.providerId ?? pkg.name ?? spec,
|
|
567
|
+
);
|
|
568
|
+
|
|
411
569
|
/** @param {string | null | undefined} value */
|
|
412
570
|
const resolveRoot = value => {
|
|
413
571
|
if (value == null) return undefined;
|
|
@@ -421,6 +579,7 @@ export async function loadIntegrations(
|
|
|
421
579
|
|
|
422
580
|
integrations.push({
|
|
423
581
|
name: pkg.name ?? spec,
|
|
582
|
+
...(providerId == null ? {} : {providerId}),
|
|
424
583
|
version: pkg.version,
|
|
425
584
|
components: resolveRoot(manifest.components),
|
|
426
585
|
templates: resolveRoot(manifest.templates),
|
|
@@ -441,5 +600,5 @@ export async function loadIntegrations(
|
|
|
441
600
|
});
|
|
442
601
|
}
|
|
443
602
|
|
|
444
|
-
return integrations;
|
|
603
|
+
return resolveProviders ? markProviderConflicts(integrations) : integrations;
|
|
445
604
|
}
|