@astryxdesign/cli 0.6.3-canary.f22695a → 0.6.3
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 +1 -2
- 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 +24 -37
- package/api/docs/_adapter.mjs +83 -169
- package/api/docs/detail/detail.mjs +63 -14
- package/api/docs/detail/section/section.d.mts +1 -1
- package/api/docs/detail/section/section.mjs +20 -44
- package/api/docs/detail/section/section.test.mjs +0 -41
- package/api/docs/docs.d.mts +2 -7
- package/api/docs/docs.doc.mjs +10 -27
- package/api/docs/docs.mjs +9 -16
- package/api/docs/docs.test.mjs +0 -6
- package/api/docs/docs.type.d.mts +3 -40
- package/api/docs/docs.type.mjs +8 -36
- package/api/docs/integrationDocs.test.mjs +0 -106
- package/api/doctor/doctor.d.mts +0 -48
- package/api/doctor/doctor.mjs +0 -232
- package/api/doctor/doctor.test.mjs +0 -196
- 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 +3 -5
- 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 +7 -49
- package/api/integration/pack-check.test.mjs +0 -249
- 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 +6 -20
- package/api/theme/build/build.test.mjs +0 -127
- package/api/theme/palette/generate/generate.mjs +1 -1
- package/api/theme/palette/generate/generator.d.mts +13 -10
- package/api/theme/palette/generate/generator.mjs +3 -7
- package/api/theme/theme.type.d.mts +11 -170
- package/api/theme/theme.type.mjs +27 -94
- package/api/upgrade/_adapter.mjs +5 -71
- package/api/upgrade/upgrade.doc.mjs +3 -4
- package/api/upgrade/upgrade.type.d.mts +5 -5
- package/api/upgrade/upgrade.type.mjs +11 -11
- package/assets/codemods/integration-discovery.mjs +2 -40
- package/assets/codemods/integration-discovery.test.mjs +0 -58
- package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +5 -27
- package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +5 -20
- package/assets/docs/README.md +0 -9
- package/assets/docs/cli-integrations.doc.mjs +15 -86
- package/assets/docs/styling-libraries.doc.mjs +1 -1
- package/assets/docs/working-with-ai.doc.mjs +1 -1
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +3 -19
- package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +65 -383
- package/authoring/_shared/contract.ts +0 -22
- package/authoring/codemod/codemod.doc.mjs +1 -6
- package/authoring/codemod/parse.d.mts +8 -8
- package/authoring/codemod/parse.mjs +6 -8
- 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 +23 -788
- package/authoring/doctypes/_schema.mjs +39 -492
- package/authoring/doctypes/base/type.ts +0 -40
- package/authoring/doctypes/command/command.doc.mjs +2 -3
- package/authoring/doctypes/command/parse.d.mts +2 -2
- package/authoring/doctypes/command/parse.mjs +1 -1
- package/authoring/doctypes/command/type.ts +2 -3
- package/authoring/doctypes/component/component.doc.mjs +3 -6
- package/authoring/doctypes/component/parse.d.mts +2 -2
- package/authoring/doctypes/component/parse.mjs +1 -1
- package/authoring/doctypes/component/type.ts +3 -4
- package/authoring/doctypes/enum/parse.d.mts +2 -2
- package/authoring/doctypes/enum/parse.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +1 -3
- package/authoring/doctypes/function/function.doc.mjs +0 -4
- package/authoring/doctypes/function/parse.d.mts +2 -2
- package/authoring/doctypes/function/parse.mjs +1 -1
- package/authoring/doctypes/function/type.ts +2 -6
- package/authoring/doctypes/hook/hook.doc.mjs +0 -4
- package/authoring/doctypes/hook/parse.d.mts +2 -2
- package/authoring/doctypes/hook/parse.mjs +1 -1
- package/authoring/doctypes/hook/type.ts +2 -3
- package/authoring/doctypes/legacy.d.mts +6 -8
- package/authoring/doctypes/legacy.mjs +4 -5
- package/authoring/doctypes/parse.d.mts +18 -20
- package/authoring/doctypes/parse.mjs +10 -16
- package/authoring/doctypes/parse.test.mjs +3 -77
- package/authoring/doctypes/reference/parse.d.mts +2 -2
- package/authoring/doctypes/reference/parse.mjs +5 -8
- package/authoring/doctypes/reference/reference.doc.mjs +4 -17
- package/authoring/doctypes/reference/type.ts +5 -51
- package/authoring/doctypes/schema/parse.d.mts +2 -2
- package/authoring/doctypes/schema/parse.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +2 -3
- package/authoring/doctypes/template/parse.d.mts +1 -92
- package/authoring/doctypes/template/parse.mjs +2 -36
- package/authoring/doctypes/template/parse.test.mjs +2 -8
- package/authoring/doctypes/template/template.doc.mjs +0 -4
- package/authoring/doctypes/template/type.ts +2 -5
- package/authoring/doctypes/types.ts +9 -10
- 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/index.d.mts +0 -1
- package/authoring/index.d.ts +17 -49
- package/authoring/index.mjs +0 -1
- package/authoring/integration/integration.doc.mjs +6 -13
- package/authoring/integration/parse.d.mts +2 -2
- package/authoring/integration/parse.mjs +1 -1
- package/authoring/integration/parse.test.mjs +1 -10
- package/authoring/integration/schema.d.mts +4 -6
- package/authoring/integration/schema.mjs +3 -9
- package/authoring/integration/type.ts +6 -23
- package/authoring/shadcn/receipt.d.mts +6 -6
- package/clients/cli/commands/docs.doc.mjs +3 -13
- package/clients/cli/commands/docs.mjs +21 -121
- package/clients/cli/commands/docs.test.mjs +0 -88
- package/clients/cli/commands/integration-authoring.test.mjs +9 -13
- package/clients/cli/commands/theme-palette-generate.doc.mjs +4 -8
- package/clients/cli/commands/upgrade.doc.mjs +2 -2
- package/clients/cli/formatters/index.mjs +1 -162
- package/clients/cli/formatters/index.test.mjs +0 -91
- package/clients/cli/lib/manifest.mjs +2 -7
- package/foundation/config/project.mjs +6 -21
- package/foundation/discovery/component-discovery.d.mts +1 -1
- package/foundation/discovery/component-discovery.mjs +1 -2
- package/foundation/discovery/docs-discovery.d.mts +4 -11
- package/foundation/discovery/docs-discovery.mjs +88 -208
- package/foundation/discovery/docs-discovery.test.mjs +13 -279
- package/foundation/discovery/template-adapter.mjs +1 -2
- package/foundation/integrations/autolink.mjs +5 -12
- package/foundation/integrations/integration-warnings.mjs +0 -6
- package/foundation/integrations/integrations.d.mts +2 -46
- package/foundation/integrations/integrations.mjs +8 -167
- package/foundation/integrations/integrations.test.mjs +1 -384
- package/foundation/integrations/validate-contributions.d.mts +0 -2
- package/foundation/integrations/validate-contributions.mjs +0 -10
- package/foundation/response/json-contract.test.mjs +17 -46
- package/foundation/response/response-types.doc.mjs +1 -6
- package/package.json +11 -9
- package/api/docs/compiled-topics.test.mjs +0 -78
- package/api/docs/index/index.d.mts +0 -18
- package/api/docs/index/index.mjs +0 -32
- package/api/docs/index/index.test.mjs +0 -62
- package/api/upgrade/project-context.test.mjs +0 -272
- package/assets/docs/authoring.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerFormats.tsx +0 -34
- package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerInline.tsx +0 -14
- package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +0 -13
- package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +0 -47
- package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +0 -14
- package/assets/templates/blocks/components/Timer/TimerTypography.tsx +0 -31
- package/authoring/doctypes/base/graph-fields.doc.d.mts +0 -9
- package/authoring/doctypes/base/graph-fields.doc.mjs +0 -62
- package/authoring/doctypes/load-contract.test.mjs +0 -207
- package/authoring/doctypes/namespace/namespace.doc.d.mts +0 -9
- package/authoring/doctypes/namespace/namespace.doc.mjs +0 -132
- package/authoring/doctypes/namespace/parse.d.mts +0 -12
- package/authoring/doctypes/namespace/parse.mjs +0 -25
- package/authoring/doctypes/namespace/parse.test.mjs +0 -165
- package/authoring/doctypes/namespace/type.ts +0 -71
- package/authoring/identity/identity.doc.d.mts +0 -9
- package/authoring/identity/identity.doc.mjs +0 -61
- package/authoring/identity/type.ts +0 -132
- package/foundation/discovery/authoring-self-docs.d.mts +0 -69
- package/foundation/discovery/authoring-self-docs.mjs +0 -214
- package/foundation/discovery/authoring-self-docs.test.mjs +0 -154
- package/foundation/discovery/docs-output-budget.d.mts +0 -28
- package/foundation/discovery/docs-output-budget.mjs +0 -50
- package/foundation/discovery/docs-section-key.d.mts +0 -98
- package/foundation/discovery/docs-section-key.mjs +0 -221
- package/foundation/discovery/docs-section-key.test.mjs +0 -224
- package/foundation/doc-compiler/compile.d.mts +0 -162
- package/foundation/doc-compiler/compile.mjs +0 -262
- package/foundation/doc-compiler/doc-compiler.test.mjs +0 -687
- package/foundation/doc-compiler/ir.d.mts +0 -9
- package/foundation/doc-compiler/ir.mjs +0 -287
- package/foundation/doc-compiler/lenses.d.mts +0 -33
- package/foundation/doc-compiler/lenses.mjs +0 -127
- package/foundation/identity/provider-identity.d.mts +0 -90
- package/foundation/identity/provider-identity.mjs +0 -320
- package/foundation/identity/provider-identity.test.mjs +0 -254
- package/foundation/identity/providers.d.mts +0 -7
- package/foundation/identity/providers.mjs +0 -16
- package/foundation/integrations/provider-conflicts.test.mjs +0 -125
|
@@ -6,19 +6,13 @@
|
|
|
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
|
-
*
|
|
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.
|
|
9
|
+
* components/templates/codemods/docs/themes roots and an optional issuesUrl. Identity
|
|
10
|
+
* (name, version) comes from the package's package.json, not the manifest.
|
|
16
11
|
*/
|
|
17
12
|
|
|
18
13
|
import * as fs from 'node:fs';
|
|
19
14
|
import * as path from 'node:path';
|
|
20
15
|
import {assertWithin} from '../fs/path-safety.mjs';
|
|
21
|
-
import {normalizeProviderId} from '../identity/provider-identity.mjs';
|
|
22
16
|
// The key census and contribution parsers are internal to the schema module on
|
|
23
17
|
// purpose: the public parser still validates the complete authored type, while
|
|
24
18
|
// the loader can isolate an invalid optional contribution from valid roots.
|
|
@@ -37,10 +31,6 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
|
|
|
37
31
|
* are internal bookkeeping used by Doctor integration validation and Project.
|
|
38
32
|
* @typedef {object} LoadedIntegration
|
|
39
33
|
* @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})
|
|
44
34
|
* @property {string} [version]
|
|
45
35
|
* @property {string} [components]
|
|
46
36
|
* @property {string} [templates]
|
|
@@ -59,10 +49,6 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
|
|
|
59
49
|
* @property {string} __manifestFile
|
|
60
50
|
* @property {string} [__loadError] set when the manifest failed to load/validate;
|
|
61
51
|
* 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
|
|
66
52
|
* @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
|
|
67
53
|
* surfaced as a warning; the rest of the manifest still contributes
|
|
68
54
|
* @property {boolean} [__autolinked] loaded because the project declares the
|
|
@@ -88,137 +74,6 @@ export const MANIFEST_BASENAMES = [
|
|
|
88
74
|
'astryx.integration.js',
|
|
89
75
|
];
|
|
90
76
|
|
|
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
|
-
|
|
222
77
|
/**
|
|
223
78
|
* Return the conventional root manifest paths present in `dir`, in
|
|
224
79
|
* load-precedence order. Unlike {@link resolveManifestPath} this never throws —
|
|
@@ -419,7 +274,6 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
419
274
|
typeof pkg.name === 'string' && pkg.name.length > 0
|
|
420
275
|
? pkg.name
|
|
421
276
|
: '(local integration)';
|
|
422
|
-
const packageProviderId = providerIdForPackage(pkg.name);
|
|
423
277
|
const manifestFile = resolveManifestPath(packageDir, spec);
|
|
424
278
|
|
|
425
279
|
let manifest;
|
|
@@ -445,7 +299,6 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
445
299
|
} catch (err) {
|
|
446
300
|
return {
|
|
447
301
|
name: spec,
|
|
448
|
-
...(packageProviderId == null ? {} : {providerId: packageProviderId}),
|
|
449
302
|
version: pkg.version,
|
|
450
303
|
__spec: spec,
|
|
451
304
|
__packageDir: packageDir,
|
|
@@ -455,8 +308,6 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
455
308
|
};
|
|
456
309
|
}
|
|
457
310
|
|
|
458
|
-
const providerId = providerIdForPackage(manifest.providerId ?? pkg.name);
|
|
459
|
-
|
|
460
311
|
/** @param {string | null | undefined} value */
|
|
461
312
|
const resolveRoot = value => {
|
|
462
313
|
if (value == null) return undefined;
|
|
@@ -469,7 +320,6 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
469
320
|
|
|
470
321
|
return {
|
|
471
322
|
name: spec,
|
|
472
|
-
...(providerId == null ? {} : {providerId}),
|
|
473
323
|
version: pkg.version,
|
|
474
324
|
components: resolveRoot(manifest.components),
|
|
475
325
|
templates: resolveRoot(manifest.templates),
|
|
@@ -495,22 +345,20 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
|
|
|
495
345
|
* Load configured integrations.
|
|
496
346
|
*
|
|
497
347
|
* @param {string[]} [specs] package names
|
|
498
|
-
* @param {{cwd?: string, fresh?: boolean
|
|
499
|
-
* `resolveProviders: false` leaves provider identity to a caller that
|
|
500
|
-
* resolves it once over a larger set (Project.load)
|
|
348
|
+
* @param {{cwd?: string, fresh?: boolean}} [options]
|
|
501
349
|
* @returns {Promise<LoadedIntegration[]>}
|
|
502
350
|
*/
|
|
503
351
|
export async function loadIntegrations(
|
|
504
352
|
specs = [],
|
|
505
|
-
{cwd = process.cwd(), fresh = false
|
|
353
|
+
{cwd = process.cwd(), fresh = false} = {},
|
|
506
354
|
) {
|
|
507
355
|
/** @type {LoadedIntegration[]} */
|
|
508
356
|
const integrations = [];
|
|
509
|
-
const
|
|
357
|
+
const seen = new Set();
|
|
510
358
|
|
|
511
359
|
for (const spec of specs) {
|
|
512
|
-
if (!spec ||
|
|
513
|
-
|
|
360
|
+
if (!spec || seen.has(spec)) continue;
|
|
361
|
+
seen.add(spec);
|
|
514
362
|
|
|
515
363
|
const packageDir = resolvePackageDir(spec, cwd);
|
|
516
364
|
const pkgPath = path.join(packageDir, 'package.json');
|
|
@@ -523,7 +371,6 @@ export async function loadIntegrations(
|
|
|
523
371
|
);
|
|
524
372
|
}
|
|
525
373
|
|
|
526
|
-
const packageProviderId = providerIdForPackage(pkg.name ?? spec);
|
|
527
374
|
const manifestFile = resolveManifestPath(packageDir, spec);
|
|
528
375
|
let manifest;
|
|
529
376
|
/** @type {string[]} */
|
|
@@ -552,7 +399,6 @@ export async function loadIntegrations(
|
|
|
552
399
|
// discovery loops naturally skip it (no components/templates/codemods).
|
|
553
400
|
integrations.push({
|
|
554
401
|
name: pkg.name ?? spec,
|
|
555
|
-
...(packageProviderId == null ? {} : {providerId: packageProviderId}),
|
|
556
402
|
version: pkg.version,
|
|
557
403
|
__spec: spec,
|
|
558
404
|
__packageDir: packageDir,
|
|
@@ -562,10 +408,6 @@ export async function loadIntegrations(
|
|
|
562
408
|
continue;
|
|
563
409
|
}
|
|
564
410
|
|
|
565
|
-
const providerId = providerIdForPackage(
|
|
566
|
-
manifest.providerId ?? pkg.name ?? spec,
|
|
567
|
-
);
|
|
568
|
-
|
|
569
411
|
/** @param {string | null | undefined} value */
|
|
570
412
|
const resolveRoot = value => {
|
|
571
413
|
if (value == null) return undefined;
|
|
@@ -579,7 +421,6 @@ export async function loadIntegrations(
|
|
|
579
421
|
|
|
580
422
|
integrations.push({
|
|
581
423
|
name: pkg.name ?? spec,
|
|
582
|
-
...(providerId == null ? {} : {providerId}),
|
|
583
424
|
version: pkg.version,
|
|
584
425
|
components: resolveRoot(manifest.components),
|
|
585
426
|
templates: resolveRoot(manifest.templates),
|
|
@@ -600,5 +441,5 @@ export async function loadIntegrations(
|
|
|
600
441
|
});
|
|
601
442
|
}
|
|
602
443
|
|
|
603
|
-
return
|
|
444
|
+
return integrations;
|
|
604
445
|
}
|
|
@@ -77,7 +77,6 @@ describe('configured integrations', () => {
|
|
|
77
77
|
const loaded = project.loadedIntegrations[0];
|
|
78
78
|
// Identity comes from package.json, not the manifest.
|
|
79
79
|
expect(loaded.name).toBe('@acme/widgets');
|
|
80
|
-
expect(loaded.providerId).toBe('@acme/widgets');
|
|
81
80
|
expect(loaded.version).toBe('1.2.3');
|
|
82
81
|
expect(loaded.components).toBe(path.join(pkgDir, 'docs'));
|
|
83
82
|
expect(loaded.templates).toBe(path.join(pkgDir, 'blocks'));
|
|
@@ -85,43 +84,6 @@ describe('configured integrations', () => {
|
|
|
85
84
|
expect(loaded.issuesUrl).toBe('https://example.com/issues');
|
|
86
85
|
});
|
|
87
86
|
|
|
88
|
-
it('preserves provider identity across an explicit package rename', async () => {
|
|
89
|
-
writeManifestPackage(tmpDir, {
|
|
90
|
-
body: `export default {providerId: '@acme/legacy-widgets'};\n`,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const [loaded] = await loadIntegrations(['@acme/widgets'], {cwd: tmpDir});
|
|
94
|
-
expect(loaded.name).toBe('@acme/widgets');
|
|
95
|
-
expect(loaded.providerId).toBe('@acme/legacy-widgets');
|
|
96
|
-
expect(loaded.__unknownKeys).toEqual([]);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('deduplicates package aliases by canonical provider identity', async () => {
|
|
100
|
-
writeManifestPackage(tmpDir, {body: `export default {};\n`});
|
|
101
|
-
const aliasDir = path.join(
|
|
102
|
-
tmpDir,
|
|
103
|
-
'node_modules',
|
|
104
|
-
'@acme',
|
|
105
|
-
'widgets-alias',
|
|
106
|
-
);
|
|
107
|
-
fs.mkdirSync(aliasDir, {recursive: true});
|
|
108
|
-
fs.writeFileSync(
|
|
109
|
-
path.join(aliasDir, 'package.json'),
|
|
110
|
-
JSON.stringify({name: '@acme/widgets', version: '1.2.3'}),
|
|
111
|
-
);
|
|
112
|
-
fs.writeFileSync(
|
|
113
|
-
path.join(aliasDir, 'astryx.integration.mjs'),
|
|
114
|
-
`export default {};\n`,
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const loaded = await loadIntegrations(
|
|
118
|
-
['@acme/widgets', '@acme/widgets-alias'],
|
|
119
|
-
{cwd: tmpDir},
|
|
120
|
-
);
|
|
121
|
-
expect(loaded).toHaveLength(1);
|
|
122
|
-
expect(loaded[0].providerId).toBe('@acme/widgets');
|
|
123
|
-
});
|
|
124
|
-
|
|
125
87
|
it('makes integration components discoverable', async () => {
|
|
126
88
|
const pkgDir = writeManifestPackage(tmpDir, {
|
|
127
89
|
body: `export default { components: './docs' };\n`,
|
|
@@ -245,347 +207,6 @@ describe('configured integrations', () => {
|
|
|
245
207
|
});
|
|
246
208
|
});
|
|
247
209
|
|
|
248
|
-
describe('provider identity conflicts', () => {
|
|
249
|
-
/**
|
|
250
|
-
* Install one integration package that contributes a single component.
|
|
251
|
-
* @param {string} dir directory under node_modules
|
|
252
|
-
* @param {{name: string, version: string}} pkg package.json identity
|
|
253
|
-
* @param {Record<string, unknown>} manifest extra manifest fields
|
|
254
|
-
* @param {string} component the component it contributes
|
|
255
|
-
*/
|
|
256
|
-
function installPackage(dir, pkg, manifest, component) {
|
|
257
|
-
const pkgDir = path.join(tmpDir, 'node_modules', ...dir.split('/'));
|
|
258
|
-
const componentsDir = path.join(pkgDir, 'components');
|
|
259
|
-
fs.mkdirSync(componentsDir, {recursive: true});
|
|
260
|
-
fs.writeFileSync(path.join(pkgDir, 'package.json'), JSON.stringify(pkg));
|
|
261
|
-
fs.writeFileSync(
|
|
262
|
-
path.join(pkgDir, 'astryx.integration.mjs'),
|
|
263
|
-
`export default ${JSON.stringify({components: './components', ...manifest})};\n`,
|
|
264
|
-
);
|
|
265
|
-
fs.writeFileSync(
|
|
266
|
-
path.join(componentsDir, `${component}.doc.mjs`),
|
|
267
|
-
`export default {type: 'component', name: '${component}', props: []};\n`,
|
|
268
|
-
);
|
|
269
|
-
fs.writeFileSync(
|
|
270
|
-
path.join(componentsDir, `${component}.tsx`),
|
|
271
|
-
`export function ${component}() { return null; }\n`,
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/** @param {string[]} integrations */
|
|
276
|
-
function configure(integrations) {
|
|
277
|
-
fs.writeFileSync(
|
|
278
|
-
path.join(tmpDir, 'astryx.config.mjs'),
|
|
279
|
-
`export default ${JSON.stringify({integrations})};\n`,
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Make the project directory itself the package being authored.
|
|
285
|
-
* @param {Record<string, unknown>} pkg package.json fields
|
|
286
|
-
* @param {Record<string, unknown>} manifest extra manifest fields
|
|
287
|
-
* @param {string} component the component it contributes
|
|
288
|
-
*/
|
|
289
|
-
function writeLocalPackage(pkg, manifest, component) {
|
|
290
|
-
const componentsDir = path.join(tmpDir, 'local-components');
|
|
291
|
-
fs.mkdirSync(componentsDir, {recursive: true});
|
|
292
|
-
fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify(pkg));
|
|
293
|
-
fs.writeFileSync(
|
|
294
|
-
path.join(tmpDir, 'astryx.integration.mjs'),
|
|
295
|
-
`export default ${JSON.stringify({components: './local-components', ...manifest})};\n`,
|
|
296
|
-
);
|
|
297
|
-
fs.writeFileSync(
|
|
298
|
-
path.join(componentsDir, `${component}.doc.mjs`),
|
|
299
|
-
`export default {type: 'component', name: '${component}', props: []};\n`,
|
|
300
|
-
);
|
|
301
|
-
fs.writeFileSync(
|
|
302
|
-
path.join(componentsDir, `${component}.tsx`),
|
|
303
|
-
`export function ${component}() { return null; }\n`,
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/** @param {import('../config/project.mjs').Project} project */
|
|
308
|
-
async function conflictIssues(project) {
|
|
309
|
-
return (await project.issues()).filter(
|
|
310
|
-
issue => issue.code === 'duplicate_provider',
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
it('keeps the first package and reports a different package claiming its ID', async () => {
|
|
315
|
-
installPackage(
|
|
316
|
-
'@acme/widgets',
|
|
317
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
318
|
-
{},
|
|
319
|
-
'Widget',
|
|
320
|
-
);
|
|
321
|
-
installPackage(
|
|
322
|
-
'@acme/renamed',
|
|
323
|
-
{name: '@acme/renamed', version: '2.0.0'},
|
|
324
|
-
{providerId: '@acme/widgets'},
|
|
325
|
-
'RenamedWidget',
|
|
326
|
-
);
|
|
327
|
-
configure(['@acme/widgets', '@acme/renamed']);
|
|
328
|
-
|
|
329
|
-
const loaded = await loadIntegrations(['@acme/widgets', '@acme/renamed'], {
|
|
330
|
-
cwd: tmpDir,
|
|
331
|
-
});
|
|
332
|
-
expect(loaded.map(integration => integration.name)).toEqual([
|
|
333
|
-
'@acme/widgets',
|
|
334
|
-
'@acme/renamed',
|
|
335
|
-
]);
|
|
336
|
-
expect(loaded[1]).toMatchObject({
|
|
337
|
-
providerId: '@acme/widgets',
|
|
338
|
-
__providerConflict: {
|
|
339
|
-
providerId: '@acme/widgets',
|
|
340
|
-
claimedBy: '@acme/widgets',
|
|
341
|
-
},
|
|
342
|
-
});
|
|
343
|
-
expect(loaded[1].components).toBeUndefined();
|
|
344
|
-
|
|
345
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
346
|
-
const owned = (await project.components()).map(component => [
|
|
347
|
-
component.package,
|
|
348
|
-
component.name,
|
|
349
|
-
]);
|
|
350
|
-
expect(owned).toContainEqual(['@acme/widgets', 'Widget']);
|
|
351
|
-
expect(owned.some(([pkg]) => pkg === '@acme/renamed')).toBe(false);
|
|
352
|
-
expect(await project.issues()).toContainEqual(
|
|
353
|
-
expect.objectContaining({
|
|
354
|
-
package: '@acme/renamed@2.0.0',
|
|
355
|
-
code: 'duplicate_provider',
|
|
356
|
-
severity: 'warning',
|
|
357
|
-
message: expect.stringContaining(
|
|
358
|
-
'@acme/widgets@1.0.0 loads first and is used',
|
|
359
|
-
),
|
|
360
|
-
}),
|
|
361
|
-
);
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
it('reports the same package configured again at another version', async () => {
|
|
365
|
-
installPackage(
|
|
366
|
-
'@acme/widgets',
|
|
367
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
368
|
-
{},
|
|
369
|
-
'Widget',
|
|
370
|
-
);
|
|
371
|
-
installPackage(
|
|
372
|
-
'widgets-next',
|
|
373
|
-
{name: '@acme/widgets', version: '2.0.0'},
|
|
374
|
-
{},
|
|
375
|
-
'NextWidget',
|
|
376
|
-
);
|
|
377
|
-
configure(['@acme/widgets', 'widgets-next']);
|
|
378
|
-
|
|
379
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
380
|
-
const owned = (await project.components()).map(component => component.name);
|
|
381
|
-
expect(owned).toContain('Widget');
|
|
382
|
-
expect(owned).not.toContain('NextWidget');
|
|
383
|
-
expect(await project.issues()).toContainEqual(
|
|
384
|
-
expect.objectContaining({
|
|
385
|
-
package: '@acme/widgets@2.0.0',
|
|
386
|
-
code: 'duplicate_provider',
|
|
387
|
-
severity: 'warning',
|
|
388
|
-
message: expect.stringContaining('(from "widgets-next")'),
|
|
389
|
-
}),
|
|
390
|
-
);
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
it('reports an autolinked dependency that claims a configured ID', async () => {
|
|
394
|
-
installPackage(
|
|
395
|
-
'@acme/widgets',
|
|
396
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
397
|
-
{},
|
|
398
|
-
'Widget',
|
|
399
|
-
);
|
|
400
|
-
installPackage(
|
|
401
|
-
'@acme/renamed',
|
|
402
|
-
{name: '@acme/renamed', version: '2.0.0'},
|
|
403
|
-
{providerId: '@acme/widgets'},
|
|
404
|
-
'RenamedWidget',
|
|
405
|
-
);
|
|
406
|
-
configure(['@acme/widgets']);
|
|
407
|
-
fs.writeFileSync(
|
|
408
|
-
path.join(tmpDir, 'package.json'),
|
|
409
|
-
JSON.stringify({
|
|
410
|
-
name: 'consumer',
|
|
411
|
-
dependencies: {'@acme/renamed': '2.0.0'},
|
|
412
|
-
}),
|
|
413
|
-
);
|
|
414
|
-
|
|
415
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
416
|
-
expect(
|
|
417
|
-
project.loadedIntegrations.find(
|
|
418
|
-
integration => integration.name === '@acme/renamed',
|
|
419
|
-
),
|
|
420
|
-
).toMatchObject({
|
|
421
|
-
__autolinked: true,
|
|
422
|
-
__providerConflict: {claimedBy: '@acme/widgets'},
|
|
423
|
-
});
|
|
424
|
-
expect(await project.issues()).toContainEqual(
|
|
425
|
-
expect.objectContaining({
|
|
426
|
-
package: '@acme/renamed@2.0.0',
|
|
427
|
-
code: 'duplicate_provider',
|
|
428
|
-
}),
|
|
429
|
-
);
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
it("reports a set-aside package whose spec is the winner's name", async () => {
|
|
433
|
-
installPackage(
|
|
434
|
-
'widgets-old',
|
|
435
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
436
|
-
{},
|
|
437
|
-
'OldWidget',
|
|
438
|
-
);
|
|
439
|
-
installPackage(
|
|
440
|
-
'@acme/widgets',
|
|
441
|
-
{name: '@acme/widgets', version: '2.0.0'},
|
|
442
|
-
{},
|
|
443
|
-
'NewWidget',
|
|
444
|
-
);
|
|
445
|
-
configure(['widgets-old', '@acme/widgets']);
|
|
446
|
-
|
|
447
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
448
|
-
const owned = (await project.components()).map(component => component.name);
|
|
449
|
-
expect(owned).toContain('OldWidget');
|
|
450
|
-
expect(owned).not.toContain('NewWidget');
|
|
451
|
-
expect(await conflictIssues(project)).toEqual([
|
|
452
|
-
expect.objectContaining({
|
|
453
|
-
package: '@acme/widgets@2.0.0',
|
|
454
|
-
severity: 'warning',
|
|
455
|
-
message: expect.stringContaining(
|
|
456
|
-
'@acme/widgets@2.0.0 and @acme/widgets@1.0.0 (from "widgets-old") both claim',
|
|
457
|
-
),
|
|
458
|
-
}),
|
|
459
|
-
]);
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
it('reports an unversioned set-aside package whose spec is the winner\'s name', async () => {
|
|
463
|
-
installPackage(
|
|
464
|
-
'widgets-old',
|
|
465
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
466
|
-
{},
|
|
467
|
-
'OldWidget',
|
|
468
|
-
);
|
|
469
|
-
installPackage('@acme/widgets', {name: '@acme/widgets'}, {}, 'NewWidget');
|
|
470
|
-
configure(['widgets-old', '@acme/widgets']);
|
|
471
|
-
|
|
472
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
473
|
-
expect(await conflictIssues(project)).toEqual([
|
|
474
|
-
expect.objectContaining({
|
|
475
|
-
package: '@acme/widgets',
|
|
476
|
-
message: expect.stringContaining(
|
|
477
|
-
'@acme/widgets@1.0.0 (from "widgets-old") loads first and is used',
|
|
478
|
-
),
|
|
479
|
-
}),
|
|
480
|
-
]);
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
it('reports an autolinked alias of the same package at another version', async () => {
|
|
484
|
-
installPackage(
|
|
485
|
-
'@acme/legacy-ui',
|
|
486
|
-
{name: '@acme/ui', version: '0.1.22'},
|
|
487
|
-
{},
|
|
488
|
-
'LegacyButton',
|
|
489
|
-
);
|
|
490
|
-
installPackage(
|
|
491
|
-
'@acme/ui',
|
|
492
|
-
{name: '@acme/ui', version: '1.0.0'},
|
|
493
|
-
{},
|
|
494
|
-
'NewButton',
|
|
495
|
-
);
|
|
496
|
-
fs.rmSync(path.join(tmpDir, 'astryx.config.mjs'));
|
|
497
|
-
fs.writeFileSync(
|
|
498
|
-
path.join(tmpDir, 'package.json'),
|
|
499
|
-
JSON.stringify({
|
|
500
|
-
name: 'consumer',
|
|
501
|
-
dependencies: {
|
|
502
|
-
'@acme/legacy-ui': 'npm:@acme/ui@0.1.22',
|
|
503
|
-
'@acme/ui': '1.0.0',
|
|
504
|
-
},
|
|
505
|
-
}),
|
|
506
|
-
);
|
|
507
|
-
|
|
508
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
509
|
-
const owned = (await project.components()).map(component => component.name);
|
|
510
|
-
expect(owned).toContain('LegacyButton');
|
|
511
|
-
expect(owned).not.toContain('NewButton');
|
|
512
|
-
expect(await conflictIssues(project)).toEqual([
|
|
513
|
-
expect.objectContaining({
|
|
514
|
-
package: '@acme/ui@1.0.0',
|
|
515
|
-
message: expect.stringContaining(
|
|
516
|
-
'@acme/ui@1.0.0 and @acme/ui@0.1.22 (from "@acme/legacy-ui") both claim',
|
|
517
|
-
),
|
|
518
|
-
}),
|
|
519
|
-
]);
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
it('recomputes conflicts after the authored package replaces its installed copy', async () => {
|
|
523
|
-
installPackage(
|
|
524
|
-
'@acme/widgets',
|
|
525
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
526
|
-
{},
|
|
527
|
-
'Widget',
|
|
528
|
-
);
|
|
529
|
-
installPackage(
|
|
530
|
-
'@acme/renamed',
|
|
531
|
-
{name: '@acme/renamed', version: '2.0.0'},
|
|
532
|
-
{providerId: '@acme/widgets'},
|
|
533
|
-
'RenamedWidget',
|
|
534
|
-
);
|
|
535
|
-
configure(['@acme/widgets', '@acme/renamed']);
|
|
536
|
-
writeLocalPackage(
|
|
537
|
-
{name: '@acme/widgets', version: '3.0.0-dev'},
|
|
538
|
-
{providerId: '@acme/widgets-next'},
|
|
539
|
-
'LocalWidget',
|
|
540
|
-
);
|
|
541
|
-
|
|
542
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
543
|
-
expect(
|
|
544
|
-
project.loadedIntegrations.some(
|
|
545
|
-
integration => integration.__providerConflict,
|
|
546
|
-
),
|
|
547
|
-
).toBe(false);
|
|
548
|
-
const owned = (await project.components()).map(component => component.name);
|
|
549
|
-
expect(owned).toEqual(
|
|
550
|
-
expect.arrayContaining(['LocalWidget', 'RenamedWidget']),
|
|
551
|
-
);
|
|
552
|
-
expect(owned).not.toContain('Widget');
|
|
553
|
-
expect(await conflictIssues(project)).toEqual([]);
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
it('lets the package being authored win over its installed predecessor', async () => {
|
|
557
|
-
installPackage(
|
|
558
|
-
'@acme/widgets',
|
|
559
|
-
{name: '@acme/widgets', version: '1.0.0'},
|
|
560
|
-
{},
|
|
561
|
-
'Widget',
|
|
562
|
-
);
|
|
563
|
-
fs.rmSync(path.join(tmpDir, 'astryx.config.mjs'));
|
|
564
|
-
writeLocalPackage(
|
|
565
|
-
{
|
|
566
|
-
name: '@acme/renamed',
|
|
567
|
-
version: '2.0.0-dev',
|
|
568
|
-
devDependencies: {'@acme/widgets': '1.0.0'},
|
|
569
|
-
},
|
|
570
|
-
{providerId: '@acme/widgets'},
|
|
571
|
-
'RenamedWidget',
|
|
572
|
-
);
|
|
573
|
-
|
|
574
|
-
const project = await Project.load(tmpDir, {fresh: true});
|
|
575
|
-
const owned = (await project.components()).map(component => component.name);
|
|
576
|
-
expect(owned).toContain('RenamedWidget');
|
|
577
|
-
expect(owned).not.toContain('Widget');
|
|
578
|
-
expect(await conflictIssues(project)).toEqual([
|
|
579
|
-
expect.objectContaining({
|
|
580
|
-
package: '@acme/widgets@1.0.0',
|
|
581
|
-
message: expect.stringContaining(
|
|
582
|
-
'@acme/renamed@2.0.0-dev is the package being authored, so it is used',
|
|
583
|
-
),
|
|
584
|
-
}),
|
|
585
|
-
]);
|
|
586
|
-
});
|
|
587
|
-
});
|
|
588
|
-
|
|
589
210
|
describe('local integration self-resolution', () => {
|
|
590
211
|
it('preserves a valid gapReport named export', async () => {
|
|
591
212
|
fs.writeFileSync(
|
|
@@ -604,11 +225,7 @@ export default {};
|
|
|
604
225
|
|
|
605
226
|
const loaded = await loadLocalIntegration(tmpDir, {fresh: true});
|
|
606
227
|
|
|
607
|
-
expect(loaded).toMatchObject({
|
|
608
|
-
name: '@acme/local',
|
|
609
|
-
providerId: '@acme/local',
|
|
610
|
-
__local: true,
|
|
611
|
-
});
|
|
228
|
+
expect(loaded).toMatchObject({name: '@acme/local', __local: true});
|
|
612
229
|
expect(loaded?.__gapReport?.audience).toBe('internal');
|
|
613
230
|
expect(
|
|
614
231
|
loaded?.__gapReport?.handle(
|
|
@@ -22,7 +22,5 @@ export function validateLoadedIntegration(loaded: LoadedIntegration): Promise<Is
|
|
|
22
22
|
*/
|
|
23
23
|
/** Stable issue code for an invalid optional agent-doc contribution. */
|
|
24
24
|
export const INVALID_AGENT_DOCS: "invalid_agent_docs";
|
|
25
|
-
/** Stable issue code for a package whose provider ID is already claimed. */
|
|
26
|
-
export const DUPLICATE_PROVIDER: "duplicate_provider";
|
|
27
25
|
export type Issue = import("./issue").AstryxIntegrationIssue;
|
|
28
26
|
export type LoadedIntegration = import("./integrations.mjs").LoadedIntegration;
|