@astryxdesign/cli 0.7.2-canary.c9f2659 → 0.7.2-canary.cbb7fa3
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/api/component/_adapter.d.mts +41 -1
- package/api/component/_adapter.mjs +93 -7
- package/api/component/component.mjs +22 -5
- package/api/component/component.test.mjs +420 -167
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/gap-report/gap-report.mjs +67 -4
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +7 -3
- package/api/integration/pack-check.mjs +61 -107
- package/api/integration/pack-check.test.mjs +359 -0
- package/api/search/search.d.mts +9 -0
- package/api/search/search.mjs +108 -16
- package/api/search/search.test.mjs +36 -0
- package/api/swizzle/copy/copy.mjs +28 -14
- package/api/template/template.test.mjs +120 -3
- package/api/theme/build/build.family.test.mjs +16 -0
- package/api/theme/build/build.mjs +77 -18
- package/api/theme/themeBuild.doc.mjs +3 -3
- package/assets/codemods/transforms/next/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/next/index.mjs +11 -1
- package/assets/codemods/transforms/next/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/docs/tree/add-a-component.doc.mjs +10 -0
- package/assets/docs/tree/checks.doc.mjs +1 -1
- package/assets/docs/tree/component-family.doc.mjs +5 -1
- package/assets/docs/tree/component-imports.doc.mjs +8 -0
- package/assets/docs/tree/single-component.doc.mjs +1 -1
- package/assets/docs/tree/troubleshooting.doc.mjs +9 -1
- package/assets/docs/tree/versioning.doc.mjs +1 -0
- package/assets/docs/working-with-ai.doc.mjs +43 -4
- package/assets/templates/blocks/components/Drawer/DrawerForm.doc.mjs +24 -0
- package/assets/templates/blocks/components/Drawer/DrawerForm.tsx +62 -0
- package/assets/templates/blocks/components/Drawer/DrawerScrim.doc.mjs +22 -0
- package/assets/templates/blocks/components/Drawer/DrawerScrim.tsx +68 -0
- package/assets/templates/blocks/components/Drawer/DrawerShowcase.doc.mjs +22 -0
- package/assets/templates/blocks/components/Drawer/DrawerShowcase.tsx +41 -0
- package/assets/templates/blocks/components/Drawer/DrawerStart.doc.mjs +21 -0
- package/assets/templates/blocks/components/Drawer/DrawerStart.tsx +41 -0
- package/assets/templates/blocks/components/Drawer/DrawerWidths.doc.mjs +22 -0
- package/assets/templates/blocks/components/Drawer/DrawerWidths.tsx +54 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderShowcase.doc.mjs +15 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderShowcase.tsx +73 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderSubtitleEndContent.doc.mjs +22 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderSubtitleEndContent.tsx +49 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderWithCloseButton.doc.mjs +21 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderWithCloseButton.tsx +42 -0
- package/assets/templates/pages/detail-page/page.tsx +3 -3
- package/assets/templates/pages/table-inbox/page.tsx +10 -8
- package/authoring/doctypes/base/type.ts +6 -0
- package/authoring/doctypes/component/component.doc.mjs +4 -4
- package/authoring/doctypes/component/type.ts +6 -3
- package/clients/cli/commands/build-theme.path-safety.test.mjs +84 -0
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/theme-build.doc.mjs +2 -2
- package/clients/cli/lib/component-format.mjs +5 -1
- package/foundation/discovery/component-discovery.d.mts +172 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +863 -55
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +18 -0
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/doc-compiler/doc-loads.test.mjs +5 -1
- package/foundation/doc-compiler/inputs.mjs +23 -0
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/integrations/contribution-inventory.mjs +6 -1
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +10 -10
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
* @property {string|null} sourcePath
|
|
27
27
|
* @property {string|undefined} issuesUrl
|
|
28
28
|
* @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration|null} integration
|
|
29
|
+
* @property {import('../../foundation/discovery/component-discovery.mjs').NameHold} hold
|
|
30
|
+
* how the owner holds the name, for the owner rule
|
|
29
31
|
*/
|
|
30
32
|
/**
|
|
31
33
|
* What ownership shaping needs from an owner. The core and legacy-external
|
|
@@ -138,6 +140,25 @@ export function assertUnambiguousOwners(owners: ComponentOwner[], dirName: strin
|
|
|
138
140
|
* @returns {string | null}
|
|
139
141
|
*/
|
|
140
142
|
export function resolveLegacyExternalDoc(ext: ExternalPackageRef, dirName: string): string | null;
|
|
143
|
+
/**
|
|
144
|
+
* Whether a legacy external package documents `dirName`.
|
|
145
|
+
* @param {string} cwd
|
|
146
|
+
* @param {string} dirName
|
|
147
|
+
* @returns {boolean}
|
|
148
|
+
*/
|
|
149
|
+
export function legacyExternalDocuments(cwd: string, dirName: string): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Whether a legacy docs package keeps `dirName` over these owners, each of which
|
|
152
|
+
* holds it only as an export a doc records.
|
|
153
|
+
* @param {string} cwd
|
|
154
|
+
* @param {string} dirName
|
|
155
|
+
* @param {Array<{hold?: string, docPath?: string | null}>} owners
|
|
156
|
+
* @returns {boolean}
|
|
157
|
+
*/
|
|
158
|
+
export function legacyExternalKeeps(cwd: string, dirName: string, owners: Array<{
|
|
159
|
+
hold?: string;
|
|
160
|
+
docPath?: string | null;
|
|
161
|
+
}>): boolean;
|
|
141
162
|
/**
|
|
142
163
|
* The core source file for `dirName` (the no-scope `--source` path reads core
|
|
143
164
|
* directly — it does NOT fall back to externals or fuzzy search).
|
|
@@ -210,7 +231,20 @@ export function scopeSubComponent(docs: LoadedComponentDoc, dirName: string, cor
|
|
|
210
231
|
};
|
|
211
232
|
matchingComponent: any;
|
|
212
233
|
} | null;
|
|
213
|
-
|
|
234
|
+
/**
|
|
235
|
+
* The doc an integration owner shows for `dirName`: when `dirName` is a member
|
|
236
|
+
* its family doc lists under its own name (`AcmeSlide` in an `AcmeCarousel`
|
|
237
|
+
* doc), the doc scoped to that member as {@link scopeSubComponent} scopes
|
|
238
|
+
* Core's, keeping the import the family doc states; otherwise `docs` itself.
|
|
239
|
+
* @param {LoadedComponentDoc} docs
|
|
240
|
+
* @param {OwnershipSubject} owner
|
|
241
|
+
* @param {string} dirName
|
|
242
|
+
* @returns {LoadedComponentDoc & {parentDoc?: string, import?: string}}
|
|
243
|
+
*/
|
|
244
|
+
export function scopeIntegrationMember(docs: LoadedComponentDoc, owner: OwnershipSubject, dirName: string): LoadedComponentDoc & {
|
|
245
|
+
parentDoc?: string;
|
|
246
|
+
import?: string;
|
|
247
|
+
};
|
|
214
248
|
/**
|
|
215
249
|
* Internal ambiguity marker. Single-component callers still receive the same
|
|
216
250
|
* AstryxError code, message, and suggestions; batch callers can additionally
|
|
@@ -261,6 +295,10 @@ export type ComponentOwner = {
|
|
|
261
295
|
sourcePath: string | null;
|
|
262
296
|
issuesUrl: string | undefined;
|
|
263
297
|
integration: import("../../foundation/integrations/integrations.mjs").LoadedIntegration | null;
|
|
298
|
+
/**
|
|
299
|
+
* how the owner holds the name, for the owner rule
|
|
300
|
+
*/
|
|
301
|
+
hold: import("../../foundation/discovery/component-discovery.mjs").NameHold;
|
|
264
302
|
};
|
|
265
303
|
/**
|
|
266
304
|
* What ownership shaping needs from an owner. The core and legacy-external
|
|
@@ -303,4 +341,6 @@ export type ResolvedUnscopedDoc = {
|
|
|
303
341
|
resolvedSourcePath: string | null;
|
|
304
342
|
};
|
|
305
343
|
import { CORE_PACKAGE } from '../../foundation/discovery/component-discovery.mjs';
|
|
344
|
+
import { unscopedComponentOwners } from '../../foundation/discovery/component-discovery.mjs';
|
|
306
345
|
import { AstryxError } from '../error.mjs';
|
|
346
|
+
export { CORE_PACKAGE, unscopedComponentOwners };
|
|
@@ -28,13 +28,17 @@ import {
|
|
|
28
28
|
import {
|
|
29
29
|
CORE_PACKAGE,
|
|
30
30
|
discoverComponents,
|
|
31
|
+
docStem,
|
|
31
32
|
findComponentReadme,
|
|
32
33
|
findComponentSource,
|
|
33
34
|
findExternalComponentDoc,
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
findIntegrationComponent,
|
|
36
|
+
integrationMemberEntry,
|
|
37
|
+
isIntegrationMember,
|
|
38
|
+
recordedDocName,
|
|
36
39
|
resolveImportPath,
|
|
37
40
|
resolveIntegrationImportPath as resolveIntegrationImport,
|
|
41
|
+
unscopedComponentOwners,
|
|
38
42
|
} from '../../foundation/discovery/component-discovery.mjs';
|
|
39
43
|
import {Project} from '../../foundation/config/project.mjs';
|
|
40
44
|
import {loadComponentDoc as loadValidatedComponentDoc} from '../../foundation/discovery/component-loader.mjs';
|
|
@@ -42,7 +46,7 @@ import {resolveComponentReplacements} from '../../foundation/discovery/component
|
|
|
42
46
|
import {searchComponents} from '../../foundation/text/string-utils.mjs';
|
|
43
47
|
import {AstryxError} from '../error.mjs';
|
|
44
48
|
|
|
45
|
-
export {CORE_PACKAGE};
|
|
49
|
+
export {CORE_PACKAGE, unscopedComponentOwners};
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
52
|
* A loaded component doc. The shared validated loader accepts stamped and legacy
|
|
@@ -71,6 +75,8 @@ export {CORE_PACKAGE};
|
|
|
71
75
|
* @property {string|null} sourcePath
|
|
72
76
|
* @property {string|undefined} issuesUrl
|
|
73
77
|
* @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration|null} integration
|
|
78
|
+
* @property {import('../../foundation/discovery/component-discovery.mjs').NameHold} hold
|
|
79
|
+
* how the owner holds the name, for the owner rule
|
|
74
80
|
*/
|
|
75
81
|
|
|
76
82
|
/**
|
|
@@ -240,17 +246,19 @@ export function resolveOwners(coreDir, dirName, loadedIntegrations) {
|
|
|
240
246
|
sourcePath: findComponentSource(coreDir, dirName),
|
|
241
247
|
issuesUrl: undefined,
|
|
242
248
|
integration: null,
|
|
249
|
+
hold: 'core',
|
|
243
250
|
});
|
|
244
251
|
}
|
|
245
252
|
for (const integration of loadedIntegrations) {
|
|
246
|
-
const
|
|
247
|
-
if (!
|
|
253
|
+
const found = findIntegrationComponent(integration, dirName);
|
|
254
|
+
if (!found) continue;
|
|
248
255
|
owners.push({
|
|
249
256
|
package: integration.name,
|
|
250
|
-
docPath,
|
|
251
|
-
sourcePath:
|
|
257
|
+
docPath: found.docPath,
|
|
258
|
+
sourcePath: found.sourcePath,
|
|
252
259
|
issuesUrl: integration.issuesUrl,
|
|
253
260
|
integration,
|
|
261
|
+
hold: found.hold,
|
|
254
262
|
});
|
|
255
263
|
}
|
|
256
264
|
return owners;
|
|
@@ -361,6 +369,39 @@ export function resolveLegacyExternalDoc(ext, dirName) {
|
|
|
361
369
|
return extDocPath && extDocPath.endsWith('.doc.mjs') ? extDocPath : null;
|
|
362
370
|
}
|
|
363
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Whether a legacy external package documents `dirName`.
|
|
374
|
+
* @param {string} cwd
|
|
375
|
+
* @param {string} dirName
|
|
376
|
+
* @returns {boolean}
|
|
377
|
+
*/
|
|
378
|
+
export function legacyExternalDocuments(cwd, dirName) {
|
|
379
|
+
return discoverExternalPackages(cwd).some(
|
|
380
|
+
ext => resolveLegacyExternalDoc(ext, dirName) != null,
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Whether a legacy docs package keeps `dirName` over these owners, each of which
|
|
386
|
+
* holds it only as an export a doc records.
|
|
387
|
+
* @param {string} cwd
|
|
388
|
+
* @param {string} dirName
|
|
389
|
+
* @param {Array<{hold?: string, docPath?: string | null}>} owners
|
|
390
|
+
* @returns {boolean}
|
|
391
|
+
*/
|
|
392
|
+
export function legacyExternalKeeps(cwd, dirName, owners) {
|
|
393
|
+
return (
|
|
394
|
+
owners.length > 0 &&
|
|
395
|
+
owners.every(
|
|
396
|
+
owner =>
|
|
397
|
+
owner.hold === 'doc' &&
|
|
398
|
+
owner.docPath != null &&
|
|
399
|
+
docStem(owner.docPath).toLowerCase() !== dirName.toLowerCase(),
|
|
400
|
+
) &&
|
|
401
|
+
legacyExternalDocuments(cwd, dirName)
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
364
405
|
/**
|
|
365
406
|
* The core source file for `dirName` (the no-scope `--source` path reads core
|
|
366
407
|
* directly — it does NOT fall back to externals or fuzzy search).
|
|
@@ -583,3 +624,48 @@ export function scopeSubComponent(docs, dirName, coreDir) {
|
|
|
583
624
|
|
|
584
625
|
return {scoped, matchingComponent};
|
|
585
626
|
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* The doc an integration owner shows for `dirName`: when `dirName` is a member
|
|
630
|
+
* its family doc lists under its own name (`AcmeSlide` in an `AcmeCarousel`
|
|
631
|
+
* doc), the doc scoped to that member as {@link scopeSubComponent} scopes
|
|
632
|
+
* Core's, keeping the import the family doc states; otherwise `docs` itself.
|
|
633
|
+
* @param {LoadedComponentDoc} docs
|
|
634
|
+
* @param {OwnershipSubject} owner
|
|
635
|
+
* @param {string} dirName
|
|
636
|
+
* @returns {LoadedComponentDoc & {parentDoc?: string, import?: string}}
|
|
637
|
+
*/
|
|
638
|
+
export function scopeIntegrationMember(docs, owner, dirName) {
|
|
639
|
+
const record = {name: dirName, docPath: owner.docPath ?? null};
|
|
640
|
+
if (!isIntegrationMember(record)) return docs;
|
|
641
|
+
const entry = integrationMemberEntry(docs, record);
|
|
642
|
+
// The files list the member but the doc this process loaded has no entry
|
|
643
|
+
// for it (the doc changed after it loaded): never answer with the family.
|
|
644
|
+
if (entry == null) {
|
|
645
|
+
throw new AstryxError(
|
|
646
|
+
`No component named "${dirName}": its family doc changed after this process loaded it.`,
|
|
647
|
+
undefined,
|
|
648
|
+
ERROR_CODES.ERR_UNKNOWN_COMPONENT,
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
// Built from the entry, as scopeSubComponent scopes Core's, so a member that
|
|
652
|
+
// shares the doc's own `name` is scoped too.
|
|
653
|
+
/** @type {LoadedComponentDoc & {parentDoc?: string, import?: string}} */
|
|
654
|
+
const scoped = {
|
|
655
|
+
name: dirName,
|
|
656
|
+
description: entry.description,
|
|
657
|
+
props: entry.props,
|
|
658
|
+
components: [entry],
|
|
659
|
+
// The name the family doc opens under, for every member.
|
|
660
|
+
parentDoc:
|
|
661
|
+
owner.integration && record.docPath
|
|
662
|
+
? recordedDocName(owner.integration, record.docPath)
|
|
663
|
+
: docs.name === dirName && record.docPath
|
|
664
|
+
? docStem(record.docPath)
|
|
665
|
+
: docs.name,
|
|
666
|
+
};
|
|
667
|
+
if (docs.usage) scoped.usage = docs.usage;
|
|
668
|
+
if (docs.theming) scoped.theming = docs.theming;
|
|
669
|
+
if (docs.import) scoped.import = docs.import;
|
|
670
|
+
return scoped;
|
|
671
|
+
}
|
|
@@ -19,9 +19,11 @@ import {
|
|
|
19
19
|
requireCoreDir,
|
|
20
20
|
loadIntegrationsSafely,
|
|
21
21
|
resolveOwners,
|
|
22
|
+
scopeIntegrationMember,
|
|
22
23
|
classifyScope,
|
|
23
24
|
assertUnambiguousOwners,
|
|
24
25
|
resolveLegacyExternalDoc,
|
|
26
|
+
legacyExternalKeeps,
|
|
25
27
|
resolveCoreSourcePath,
|
|
26
28
|
resolveUnscopedDoc,
|
|
27
29
|
loadComponentDoc,
|
|
@@ -29,6 +31,7 @@ import {
|
|
|
29
31
|
ComponentAmbiguityError,
|
|
30
32
|
installedComponentPackageVersion,
|
|
31
33
|
resolveComponentReplacement,
|
|
34
|
+
unscopedComponentOwners,
|
|
32
35
|
} from './_adapter.mjs';
|
|
33
36
|
import {componentList} from './list/list.mjs';
|
|
34
37
|
import {componentDetail} from './detail/detail.mjs';
|
|
@@ -427,7 +430,13 @@ export async function component(name, options = {}) {
|
|
|
427
430
|
if (blocks) {
|
|
428
431
|
return componentDetailBlocks(dirName, cwd, owner.package);
|
|
429
432
|
}
|
|
430
|
-
const
|
|
433
|
+
const loaded = await loadComponentDoc(owner.docPath, docOpts);
|
|
434
|
+
// A family member an integration lists under its own name reads as that
|
|
435
|
+
// member, the way a Core sub-component does below.
|
|
436
|
+
const docs =
|
|
437
|
+
scoped.kind === 'integration'
|
|
438
|
+
? scopeIntegrationMember(loaded, owner, dirName)
|
|
439
|
+
: loaded;
|
|
431
440
|
if (props) return componentDetailProps(docs, owner.package);
|
|
432
441
|
return componentDetail(docs, owner, dirName, coreDir);
|
|
433
442
|
}
|
|
@@ -481,12 +490,14 @@ export async function component(name, options = {}) {
|
|
|
481
490
|
});
|
|
482
491
|
}
|
|
483
492
|
|
|
493
|
+
// The owner rule runs first, over valid and invalid owners alike.
|
|
494
|
+
const ruled = unscopedComponentOwners(owners);
|
|
484
495
|
// Invalid integration metadata does not create ambiguity against a valid
|
|
485
|
-
// owner. Keep
|
|
496
|
+
// owner. Keep ruled owners only when no doc owner is valid, so an integration-
|
|
486
497
|
// only component still exposes its source and returns ERR_INVALID_DOC for
|
|
487
498
|
// detail instead of degrading to an unrelated unknown-component error.
|
|
488
499
|
const validOwners = [];
|
|
489
|
-
for (const owner of
|
|
500
|
+
for (const owner of ruled) {
|
|
490
501
|
if (owner.package === CORE_PACKAGE) {
|
|
491
502
|
validOwners.push(owner);
|
|
492
503
|
continue;
|
|
@@ -498,7 +509,12 @@ export async function component(name, options = {}) {
|
|
|
498
509
|
// Project/Doctor report invalid metadata; it is not an effective owner.
|
|
499
510
|
}
|
|
500
511
|
}
|
|
501
|
-
const
|
|
512
|
+
const loadable = validOwners.length > 0 ? validOwners : ruled;
|
|
513
|
+
// A legacy docs package's exact doc keeps its name over an export name a doc
|
|
514
|
+
// records, as Core and file-named owners do.
|
|
515
|
+
const effectiveOwners = legacyExternalKeeps(cwd, dirName, loadable)
|
|
516
|
+
? []
|
|
517
|
+
: loadable;
|
|
502
518
|
|
|
503
519
|
// ── Ambiguity: owned by MORE THAN ONE valid package, no --package ──
|
|
504
520
|
assertUnambiguousOwners(effectiveOwners, dirName);
|
|
@@ -516,7 +532,8 @@ export async function component(name, options = {}) {
|
|
|
516
532
|
// Integration components don't carry showcases — fail without scanning.
|
|
517
533
|
return componentDetailShowcase(dirName, {cwd, name, resolve: false, ownerPackage: owner.package});
|
|
518
534
|
}
|
|
519
|
-
const
|
|
535
|
+
const loaded = await loadComponentDoc(owner.docPath, docOpts);
|
|
536
|
+
const docs = scopeIntegrationMember(loaded, owner, dirName);
|
|
520
537
|
if (props) return componentDetailProps(docs, owner.package);
|
|
521
538
|
return componentDetail(docs, owner, dirName, coreDir);
|
|
522
539
|
}
|