@forumone/create-throughline 0.2.1 → 0.3.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.
- package/CHANGELOG.md +14 -0
- package/dist/generator.d.ts +2 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +21 -4
- package/dist/generator.js.map +1 -1
- package/dist/templates/base/apps/web/package.json.template +2 -1
- package/dist/templates/base/apps/web/src/app/api/inngest/route.ts.template +2 -2
- package/dist/templates/base/apps/web/src/payload.config.ts.template +7 -5
- package/dist/templates/base/apps/web/tsconfig.json +2 -1
- package/dist/templates/base/gitignore +15 -0
- package/dist/templates/base/package.json.template +4 -1
- package/dist/templates/base/pnpm-workspace.yaml +1 -0
- package/dist/templates/base/turbo.json +11 -0
- package/dist/templates/with-reference-ds/design-system/.storybook/main.ts +21 -0
- package/dist/templates/with-reference-ds/design-system/.storybook/preview.ts +19 -0
- package/dist/templates/with-reference-ds/design-system/README.md +33 -0
- package/dist/templates/with-reference-ds/design-system/gitignore +5 -0
- package/dist/templates/with-reference-ds/design-system/package.json.template +62 -0
- package/dist/templates/with-reference-ds/design-system/scripts/build-manifest.ts +89 -0
- package/dist/templates/with-reference-ds/design-system/scripts/build-styles.ts +28 -0
- package/dist/templates/with-reference-ds/design-system/scripts/build-tokens-css.ts +43 -0
- package/dist/templates/with-reference-ds/design-system/scripts/validate.ts +58 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.contract.ts +128 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.module.css +83 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.stories.tsx +39 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.test.tsx +27 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CTASection/CTASection.tsx +41 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CTASection/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.contract.ts +122 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.module.css +64 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.stories.tsx +45 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.test.tsx +37 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Card/Card.tsx +39 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Card/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.contract.ts +78 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.module.css +34 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.stories.tsx +36 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.test.tsx +25 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/CardGrid.tsx +19 -0
- package/dist/templates/with-reference-ds/design-system/src/components/CardGrid/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.contract.ts +87 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.module.css +18 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.stories.tsx +35 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.test.tsx +20 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Divider/Divider.tsx +17 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Divider/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.contract.ts +104 -0
- package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.module.css +66 -0
- package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.stories.tsx +61 -0
- package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.test.tsx +30 -0
- package/dist/templates/with-reference-ds/design-system/src/components/FAQ/FAQ.tsx +41 -0
- package/dist/templates/with-reference-ds/design-system/src/components/FAQ/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.contract.ts +182 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.module.css +124 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.stories.tsx +58 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.test.tsx +49 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Hero/Hero.tsx +67 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Hero/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.contract.ts +94 -0
- package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.module.css +49 -0
- package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.stories.tsx +37 -0
- package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.test.tsx +35 -0
- package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/MediaBlock.tsx +49 -0
- package/dist/templates/with-reference-ds/design-system/src/components/MediaBlock/index.ts +7 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.contract.ts +107 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.module.css +72 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.stories.tsx +39 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.test.tsx +26 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Prose/Prose.tsx +15 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Prose/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.contract.ts +101 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.module.css +59 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.stories.tsx +44 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.test.tsx +37 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Quote/Quote.tsx +40 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Quote/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.contract.ts +108 -0
- package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.module.css +36 -0
- package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.stories.tsx +33 -0
- package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.test.tsx +28 -0
- package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/SectionIntro.tsx +28 -0
- package/dist/templates/with-reference-ds/design-system/src/components/SectionIntro/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.contract.ts +76 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.module.css +23 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.stories.tsx +25 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.test.tsx +17 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Spacer/Spacer.tsx +19 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Spacer/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.contract.ts +103 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.module.css +88 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.stories.tsx +44 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.test.tsx +44 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Stats/Stats.tsx +39 -0
- package/dist/templates/with-reference-ds/design-system/src/components/Stats/index.ts +2 -0
- package/dist/templates/with-reference-ds/design-system/src/css-modules.d.ts +5 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/Colors.stories.tsx +46 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/Elevation.stories.tsx +37 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/LayoutContainers.stories.tsx +86 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/Radii.stories.tsx +38 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/Spacing.stories.tsx +33 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/Typography.stories.tsx +55 -0
- package/dist/templates/with-reference-ds/design-system/src/foundations/_helpers.tsx +82 -0
- package/dist/templates/with-reference-ds/design-system/src/index.ts +14 -0
- package/dist/templates/with-reference-ds/design-system/src/styles/base.css +55 -0
- package/dist/templates/with-reference-ds/design-system/src/styles/reset.css +48 -0
- package/dist/templates/with-reference-ds/design-system/src/styles/tokens.css +116 -0
- package/dist/templates/with-reference-ds/design-system/src/tokens/colors.ts +54 -0
- package/dist/templates/with-reference-ds/design-system/src/tokens/index.ts +32 -0
- package/dist/templates/with-reference-ds/design-system/src/tokens/layout.ts +26 -0
- package/dist/templates/with-reference-ds/design-system/src/tokens/radii.ts +11 -0
- package/dist/templates/with-reference-ds/design-system/src/tokens/spacing.ts +26 -0
- package/dist/templates/with-reference-ds/design-system/src/tokens/typography.ts +32 -0
- package/dist/templates/with-reference-ds/design-system/tsconfig.json +24 -0
- package/dist/templates/with-reference-ds/design-system/vitest.config.ts +15 -0
- package/dist/templates/with-reference-ds/design-system/vitest.setup.ts +7 -0
- package/dist/templates/without-reference-ds/design-system/.storybook/main.ts +21 -0
- package/dist/templates/without-reference-ds/design-system/.storybook/preview.ts +16 -0
- package/dist/templates/without-reference-ds/design-system/README.md +20 -0
- package/dist/templates/without-reference-ds/design-system/gitignore +5 -0
- package/dist/templates/without-reference-ds/design-system/package.json.template +33 -0
- package/dist/templates/without-reference-ds/design-system/src/foundations/Welcome.stories.tsx +24 -0
- package/dist/templates/without-reference-ds/design-system/src/index.ts +9 -0
- package/dist/templates/without-reference-ds/design-system/tsconfig.json +11 -0
- package/package.json +3 -1
- package/dist/templates/with-reference-ds/packages/design-system/package.json.template +0 -18
- package/dist/templates/with-reference-ds/packages/design-system/src/index.ts +0 -6
- package/dist/templates/with-reference-ds/packages/design-system/src/manifest.ts +0 -6
- package/dist/templates/with-reference-ds/packages/design-system/tsconfig.json +0 -9
- package/dist/templates/without-reference-ds/packages/design-system/README.md +0 -19
- package/dist/templates/without-reference-ds/packages/design-system/package.json.template +0 -14
- package/dist/templates/without-reference-ds/packages/design-system/src/index.ts +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @forumone/create-throughline
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e994176: Scaffold a real Storybook authoring environment for the design system.
|
|
8
|
+
|
|
9
|
+
When you scaffold with the reference design system, the generator now creates a top-level `design-system/` workspace (a sibling of `apps/`, matching the Forum One `forumone.com-2026` layout) that vendors the reference DS's **editable source** — 12 components with `.stories.tsx`, `.contract.ts`, tokens, and a Storybook instance — instead of re-exporting the compiled npm package. New projects can run `pnpm storybook` immediately, author components, and `pnpm validate` to cross-check every contract `storyId` against the built Storybook.
|
|
10
|
+
|
|
11
|
+
Also:
|
|
12
|
+
- The web app now imports the workspace design system's built manifest (`<scope>/design-system/manifest`) instead of the npm reference-ds manifest, and the root `pnpm dev` builds the design system first so the manifest exists.
|
|
13
|
+
- Root scripts `storybook`, `build-storybook`, and `validate`; turbo tasks to match; `design-system` added to the workspace globs.
|
|
14
|
+
- Fix: template `.gitignore` files are now authored as `gitignore` and restored on output, so they survive npm publish (previously the generated project shipped without a root `.gitignore`).
|
|
15
|
+
- Fix: the generated web app now typechecks clean. Adds the `@payload-config` tsconfig path; corrects drifted plugin APIs in `route.ts` (`publishingApiKey`, `createPayloadReachableCheck()`) and `payload.config.ts` (`auditQueryPlugin({})`, `buildActionUrl` async `{ approvalId, action, approverId }`, manifest typed as `Manifest`).
|
|
16
|
+
|
|
3
17
|
## 0.2.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/dist/generator.d.ts
CHANGED
|
@@ -37,9 +37,11 @@ interface RenderArgs {
|
|
|
37
37
|
*/
|
|
38
38
|
declare function renderDirectory({ source, target, data }: RenderArgs): Promise<void>;
|
|
39
39
|
declare function isBinary(filename: string): boolean;
|
|
40
|
+
declare function applyDotfileRename(name: string): string;
|
|
40
41
|
export declare const __testing: {
|
|
41
42
|
renderDirectory: typeof renderDirectory;
|
|
42
43
|
isBinary: typeof isBinary;
|
|
44
|
+
applyDotfileRename: typeof applyDotfileRename;
|
|
43
45
|
rename: typeof rename;
|
|
44
46
|
rm: typeof rm;
|
|
45
47
|
stat: typeof stat;
|
package/dist/generator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAa,MAAM,kBAAkB,CAAA;AAI5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAa,MAAM,kBAAkB,CAAA;AAI5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAK3C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC7F;AAED,UAAU,UAAU;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED;;;;;;;;;GASG;AACH,iBAAe,eAAe,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClF;AAiBD,iBAAS,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI3C;AAUD,iBAAS,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AA6BD,eAAO,MAAM,SAAS;;;;;;;CAAsE,CAAA"}
|
package/dist/generator.js
CHANGED
|
@@ -19,19 +19,26 @@ const DEFAULT_TEMPLATES_DIR = resolve(__dirname, 'templates');
|
|
|
19
19
|
export async function generate(answers, options = {}) {
|
|
20
20
|
const templatesDir = options.templatesDir ?? DEFAULT_TEMPLATES_DIR;
|
|
21
21
|
const onProgress = options.onProgress ?? (() => { });
|
|
22
|
+
// Precompute the design-system package name. The renderer has no nesting, so
|
|
23
|
+
// we can't put `{{#if packageScope}}...{{/if}}` inside another `{{#if}}`
|
|
24
|
+
// block (e.g. inside `{{#if useReferenceDs}}` in payload.config).
|
|
25
|
+
const designSystemName = answers.packageScope
|
|
26
|
+
? `@${answers.packageScope}/design-system`
|
|
27
|
+
: `${answers.projectName}-design-system`;
|
|
28
|
+
const data = { ...answers, designSystemName };
|
|
22
29
|
onProgress('Creating project structure');
|
|
23
30
|
await mkdir(answers.targetDir, { recursive: true });
|
|
24
31
|
await renderDirectory({
|
|
25
32
|
source: join(templatesDir, 'base'),
|
|
26
33
|
target: answers.targetDir,
|
|
27
|
-
data
|
|
34
|
+
data,
|
|
28
35
|
});
|
|
29
36
|
onProgress(answers.useReferenceDs ? 'Wiring reference design system' : 'Preparing design system placeholder');
|
|
30
37
|
const overlay = answers.useReferenceDs ? 'with-reference-ds' : 'without-reference-ds';
|
|
31
38
|
await renderDirectory({
|
|
32
39
|
source: join(templatesDir, overlay),
|
|
33
40
|
target: answers.targetDir,
|
|
34
|
-
data
|
|
41
|
+
data,
|
|
35
42
|
});
|
|
36
43
|
if (answers.initializeGit && !options.skipSideEffects) {
|
|
37
44
|
onProgress('Initializing git');
|
|
@@ -64,7 +71,7 @@ async function renderDirectory({ source, target, data }) {
|
|
|
64
71
|
}
|
|
65
72
|
await mkdir(target, { recursive: true });
|
|
66
73
|
for (const entry of entries) {
|
|
67
|
-
const renderedName = renderTemplate(entry.name, data);
|
|
74
|
+
const renderedName = applyDotfileRename(renderTemplate(entry.name, data));
|
|
68
75
|
const sourcePath = join(source, entry.name);
|
|
69
76
|
const targetPath = join(target, renderedName);
|
|
70
77
|
if (entry.isDirectory()) {
|
|
@@ -105,6 +112,16 @@ function isBinary(filename) {
|
|
|
105
112
|
return false;
|
|
106
113
|
return BINARY_EXTENSIONS.has(filename.slice(dot).toLowerCase());
|
|
107
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* npm strips files literally named `.gitignore` from a published tarball, so
|
|
117
|
+
* we author them as `gitignore` in templates and restore the dot on output.
|
|
118
|
+
*/
|
|
119
|
+
const DOTFILE_RENAMES = {
|
|
120
|
+
gitignore: '.gitignore',
|
|
121
|
+
};
|
|
122
|
+
function applyDotfileRename(name) {
|
|
123
|
+
return DOTFILE_RENAMES[name] ?? name;
|
|
124
|
+
}
|
|
108
125
|
async function initGit(dir) {
|
|
109
126
|
await runCommand('git', ['init'], dir);
|
|
110
127
|
await runCommand('git', ['add', '.'], dir);
|
|
@@ -127,5 +144,5 @@ function runCommand(cmd, args, cwd) {
|
|
|
127
144
|
}
|
|
128
145
|
// Re-exports kept around so tests in adjacent packages can stub these without
|
|
129
146
|
// reaching into the implementation. Not part of the public API surface.
|
|
130
|
-
export const __testing = { renderDirectory, isBinary, rename, rm, stat };
|
|
147
|
+
export const __testing = { renderDirectory, isBinary, applyDotfileRename, rename, rm, stat };
|
|
131
148
|
//# sourceMappingURL=generator.js.map
|
package/dist/generator.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAGrD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,qBAAqB,GAAG,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;AAW7D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAgB,EAAE,UAA2B,EAAE;IAC5E,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,qBAAqB,CAAA;IAClE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IAEnD,UAAU,CAAC,4BAA4B,CAAC,CAAA;IACxC,MAAM,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACnD,MAAM,eAAe,CAAC;QACpB,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC;QAClC,MAAM,EAAE,OAAO,CAAC,SAAS;QACzB,IAAI
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"@forumone/throughline-integrations": "^0.2.0",
|
|
22
22
|
"@forumone/throughline-publishing": "^0.2.0",
|
|
23
23
|
"@forumone/throughline-workflows": "^0.2.0",
|
|
24
|
-
{{#if useReferenceDs}}"@forumone/throughline-
|
|
24
|
+
{{#if useReferenceDs}}"@forumone/throughline-design-contract": "^0.2.0",
|
|
25
|
+
"{{designSystemName}}": "workspace:*",
|
|
25
26
|
{{/if}}"@payloadcms/db-postgres": "^3.83.0",
|
|
26
27
|
"@payloadcms/next": "^3.83.0",
|
|
27
28
|
"@payloadcms/plugin-form-builder": "3.83.0",
|
|
@@ -40,14 +40,14 @@ export const { GET, POST, PUT } = serve({
|
|
|
40
40
|
payload,
|
|
41
41
|
collections: [{ slug: 'pages' }],
|
|
42
42
|
publishingServerUrl: process.env.NEXT_PUBLIC_SERVER_URL!,
|
|
43
|
-
|
|
43
|
+
publishingApiKey: process.env.PUBLISHING_SYSTEM_API_KEY!,
|
|
44
44
|
}),
|
|
45
45
|
createExpireStaleApprovalsFunction({ inngest, payload }),
|
|
46
46
|
createAuditEventEchoFunction({ inngest }),
|
|
47
47
|
createHealthcheckFunction({
|
|
48
48
|
inngest,
|
|
49
49
|
payload,
|
|
50
|
-
checks: [createPayloadReachableCheck(
|
|
50
|
+
checks: [createPayloadReachableCheck()],
|
|
51
51
|
}),
|
|
52
52
|
...emailFunctions,
|
|
53
53
|
...formsFunctions,
|
|
@@ -16,7 +16,8 @@ import { auditQueryPlugin } from '@forumone/throughline-audit'
|
|
|
16
16
|
import { integrationsPlugin } from '@forumone/throughline-integrations'
|
|
17
17
|
import { emailPlugin } from '@forumone/throughline-email'
|
|
18
18
|
import { formsPlugin } from '@forumone/throughline-forms'
|
|
19
|
-
{{#if useReferenceDs}}import
|
|
19
|
+
{{#if useReferenceDs}}import type { Manifest } from '@forumone/throughline-design-contract'
|
|
20
|
+
import designSystemManifest from '{{designSystemName}}/manifest' with { type: 'json' }
|
|
20
21
|
{{/if}}
|
|
21
22
|
|
|
22
23
|
const __filename = fileURLToPath(import.meta.url)
|
|
@@ -101,7 +102,7 @@ export default buildConfig({
|
|
|
101
102
|
auditPlugin({ inngest }),
|
|
102
103
|
|
|
103
104
|
componentsPlugin({
|
|
104
|
-
{{#if useReferenceDs}}manifest: { type: 'object', manifest:
|
|
105
|
+
{{#if useReferenceDs}}manifest: { type: 'object', manifest: designSystemManifest as unknown as Manifest },
|
|
105
106
|
{{else}}// TODO: point at your design system manifest
|
|
106
107
|
manifest: { type: 'url', url: 'https://your-design-system.example.com/manifest.json' },
|
|
107
108
|
{{/if}}matching: { strategy: 'tfidf' },
|
|
@@ -132,15 +133,16 @@ export default buildConfig({
|
|
|
132
133
|
},
|
|
133
134
|
}),
|
|
134
135
|
|
|
135
|
-
auditQueryPlugin(),
|
|
136
|
+
auditQueryPlugin({}),
|
|
136
137
|
|
|
137
138
|
emailPlugin({
|
|
138
139
|
inngest,
|
|
139
140
|
// TODO: replace with your real user lookups
|
|
140
141
|
resolveApprover: async (_userId) => null,
|
|
141
142
|
resolveRequester: async (_userId) => null,
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
// TODO: sign these URLs (HMAC) so an approval decision can't be forged.
|
|
144
|
+
buildActionUrl: async ({ approvalId, action, approverId }) =>
|
|
145
|
+
`${process.env.NEXT_PUBLIC_SERVER_URL}/api/approvals/decision?approval=${approvalId}&action=${action}&approver=${approverId}`,
|
|
144
146
|
tokens: { brandName: '{{projectName}}' },
|
|
145
147
|
}),
|
|
146
148
|
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "turbo run build",
|
|
7
|
-
"dev": "turbo run dev",
|
|
7
|
+
"dev": "{{#if useReferenceDs}}pnpm --filter \"./design-system\" build && {{/if}}turbo run dev",
|
|
8
|
+
"storybook": "turbo run storybook",
|
|
9
|
+
"build-storybook": "turbo run build-storybook",
|
|
10
|
+
"validate": "turbo run validate",
|
|
8
11
|
"lint": "turbo run lint",
|
|
9
12
|
"typecheck": "turbo run typecheck",
|
|
10
13
|
"test": "turbo run test",
|
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
|
8
8
|
"env": ["NODE_ENV"]
|
|
9
9
|
},
|
|
10
|
+
"build-storybook": {
|
|
11
|
+
"dependsOn": ["^build"],
|
|
12
|
+
"outputs": ["storybook-static/**"]
|
|
13
|
+
},
|
|
14
|
+
"storybook": {
|
|
15
|
+
"cache": false,
|
|
16
|
+
"persistent": true
|
|
17
|
+
},
|
|
18
|
+
"validate": {
|
|
19
|
+
"dependsOn": ["build"]
|
|
20
|
+
},
|
|
10
21
|
"dev": {
|
|
11
22
|
"cache": false,
|
|
12
23
|
"persistent": true
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StorybookConfig } from '@storybook/react-vite'
|
|
2
|
+
|
|
3
|
+
const config: StorybookConfig = {
|
|
4
|
+
stories: [
|
|
5
|
+
'../src/foundations/**/*.stories.@(ts|tsx)',
|
|
6
|
+
'../src/components/**/*.stories.@(ts|tsx)',
|
|
7
|
+
],
|
|
8
|
+
addons: ['@storybook/addon-a11y'],
|
|
9
|
+
framework: {
|
|
10
|
+
name: '@storybook/react-vite',
|
|
11
|
+
options: {},
|
|
12
|
+
},
|
|
13
|
+
typescript: {
|
|
14
|
+
reactDocgen: 'react-docgen-typescript',
|
|
15
|
+
},
|
|
16
|
+
docs: {
|
|
17
|
+
autodocs: true,
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default config
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Preview } from '@storybook/react-vite'
|
|
2
|
+
import '../src/styles/reset.css'
|
|
3
|
+
import '../src/styles/tokens.css'
|
|
4
|
+
import '../src/styles/base.css'
|
|
5
|
+
|
|
6
|
+
const preview: Preview = {
|
|
7
|
+
parameters: {
|
|
8
|
+
controls: {
|
|
9
|
+
matchers: { color: /(background|color)$/i, date: /Date$/i },
|
|
10
|
+
},
|
|
11
|
+
a11y: {
|
|
12
|
+
config: {},
|
|
13
|
+
options: {},
|
|
14
|
+
manual: false,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default preview
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Design system
|
|
2
|
+
|
|
3
|
+
Your project's design system and its Storybook authoring environment. It started as a vendored copy of the Throughline reference DS — a working, brand-neutral set of 12 components with contracts — so you can edit it directly and make it your own.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
src/
|
|
7
|
+
tokens/ Design tokens (colors, typography, spacing, radii, layout) → CSS custom properties
|
|
8
|
+
styles/ reset.css, generated tokens.css, base.css
|
|
9
|
+
foundations/ Storybook "Foundations" pages (Colors, Typography, Spacing, Radii, Elevation, Layout & Containers)
|
|
10
|
+
components/ One folder per component: .tsx, .module.css, .stories.tsx, .test.tsx, .contract.ts
|
|
11
|
+
scripts/ build-tokens-css, build-styles, build-manifest, validate
|
|
12
|
+
.storybook/ Storybook (react-vite) config
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm --filter "./design-system" storybook # author components at http://localhost:6006
|
|
19
|
+
pnpm --filter "./design-system" build # tokens → tsc → styles → dist/manifest.json
|
|
20
|
+
pnpm --filter "./design-system" build-storybook # static Storybook (produces storybook-static/index.json)
|
|
21
|
+
pnpm --filter "./design-system" validate # lint contracts + cross-check every storyId against the built Storybook
|
|
22
|
+
pnpm --filter "./design-system" test # component tests (vitest + testing-library)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The web app imports `./manifest` (the built `dist/manifest.json`) and feeds it to the Components MCP server. The root `pnpm dev` builds the design system first so the manifest exists.
|
|
26
|
+
|
|
27
|
+
## Branding
|
|
28
|
+
|
|
29
|
+
1. Edit `src/tokens/*` — components read tokens as CSS variables, so re-theming doesn't touch component code.
|
|
30
|
+
2. Edit or add components under `src/components/`. Keep each component's `.contract.ts` and `.stories.tsx` in sync; `storyId` must point at a real story (the `validate` script enforces this).
|
|
31
|
+
3. Update the **Foundations** pages in `src/foundations/` as your tokens change.
|
|
32
|
+
|
|
33
|
+
See the Throughline docs: `concepts/design-system-contracts.md` and `guides/authoring-component-contracts.md`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{designSystemName}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./manifest": "./dist/manifest.json",
|
|
14
|
+
"./styles.css": "./dist/styles/index.css",
|
|
15
|
+
"./styles/tokens.css": "./dist/styles/tokens.css",
|
|
16
|
+
"./styles/reset.css": "./dist/styles/reset.css",
|
|
17
|
+
"./styles/base.css": "./dist/styles/base.css",
|
|
18
|
+
"./tokens": {
|
|
19
|
+
"types": "./dist/tokens/index.d.ts",
|
|
20
|
+
"default": "./dist/tokens/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "pnpm build:tokens-css && tsc -b && pnpm build:styles && pnpm build:manifest",
|
|
25
|
+
"build:tokens-css": "tsx scripts/build-tokens-css.ts",
|
|
26
|
+
"build:styles": "tsx scripts/build-styles.ts",
|
|
27
|
+
"build:manifest": "tsx scripts/build-manifest.ts",
|
|
28
|
+
"build-storybook": "storybook build",
|
|
29
|
+
"storybook": "storybook dev -p 6006",
|
|
30
|
+
"dev": "tsc -b -w",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"validate": "tsx scripts/validate.ts",
|
|
34
|
+
"clean": "rm -rf dist .turbo storybook-static *.tsbuildinfo"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@forumone/throughline-design-contract": "^0.2.0",
|
|
38
|
+
"clsx": "^2.1.1"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
42
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@storybook/addon-a11y": "^10.3.5",
|
|
46
|
+
"@storybook/react-vite": "^10.3.5",
|
|
47
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
48
|
+
"@testing-library/react": "^16.3.2",
|
|
49
|
+
"@types/node": "^20.17.0",
|
|
50
|
+
"@types/react": "^19.2.0",
|
|
51
|
+
"@types/react-dom": "^19.2.0",
|
|
52
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
53
|
+
"jsdom": "^29.0.2",
|
|
54
|
+
"react": "^19.2.0",
|
|
55
|
+
"react-dom": "^19.2.0",
|
|
56
|
+
"storybook": "^10.3.5",
|
|
57
|
+
"tsx": "^4.21.0",
|
|
58
|
+
"typescript": "^5.6.0",
|
|
59
|
+
"vite": "^8.0.9",
|
|
60
|
+
"vitest": "^2.1.0"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { readFile, readdir, stat, writeFile, mkdir } from 'node:fs/promises'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'node:url'
|
|
4
|
+
import {
|
|
5
|
+
CONTRACT_VERSION,
|
|
6
|
+
ManifestSchema,
|
|
7
|
+
type ComponentContract,
|
|
8
|
+
} from '@forumone/throughline-design-contract'
|
|
9
|
+
import { getTokenList } from '../src/tokens/index.ts'
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
12
|
+
const packageRoot = resolve(__dirname, '..')
|
|
13
|
+
const componentsDir = resolve(packageRoot, 'src/components')
|
|
14
|
+
const outputDir = resolve(packageRoot, 'dist')
|
|
15
|
+
const outputFile = resolve(outputDir, 'manifest.json')
|
|
16
|
+
|
|
17
|
+
async function readPackageVersion(): Promise<string> {
|
|
18
|
+
const raw = await readFile(resolve(packageRoot, 'package.json'), 'utf8')
|
|
19
|
+
const parsed = JSON.parse(raw) as { version?: string }
|
|
20
|
+
return parsed.version ?? '0.0.0'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function collectContracts(): Promise<Record<string, ComponentContract>> {
|
|
24
|
+
const components: Record<string, ComponentContract> = {}
|
|
25
|
+
|
|
26
|
+
let entries: string[]
|
|
27
|
+
try {
|
|
28
|
+
entries = await readdir(componentsDir)
|
|
29
|
+
} catch {
|
|
30
|
+
return components
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (const name of entries) {
|
|
34
|
+
const dir = resolve(componentsDir, name)
|
|
35
|
+
const dirStat = await stat(dir).catch(() => null)
|
|
36
|
+
if (!dirStat?.isDirectory()) continue
|
|
37
|
+
|
|
38
|
+
const contractPath = join(dir, `${name}.contract.ts`)
|
|
39
|
+
const contractStat = await stat(contractPath).catch(() => null)
|
|
40
|
+
if (!contractStat?.isFile()) continue
|
|
41
|
+
|
|
42
|
+
const module = (await import(pathToFileURL(contractPath).href)) as {
|
|
43
|
+
contract?: ComponentContract
|
|
44
|
+
}
|
|
45
|
+
if (!module.contract) {
|
|
46
|
+
throw new Error(`${name}.contract.ts does not export "contract"`)
|
|
47
|
+
}
|
|
48
|
+
components[name] = module.contract
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return components
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function main() {
|
|
55
|
+
const components = await collectContracts()
|
|
56
|
+
|
|
57
|
+
const manifest = {
|
|
58
|
+
contractVersion: CONTRACT_VERSION,
|
|
59
|
+
designSystem: {
|
|
60
|
+
name: '@forumone/throughline-reference-ds',
|
|
61
|
+
version: await readPackageVersion(),
|
|
62
|
+
description:
|
|
63
|
+
'A brand-neutral reference design system demonstrating contract compliance for Throughline.',
|
|
64
|
+
},
|
|
65
|
+
tokens: getTokenList(),
|
|
66
|
+
components,
|
|
67
|
+
build: {
|
|
68
|
+
timestamp: new Date().toISOString(),
|
|
69
|
+
source: 'scripts/build-manifest.ts',
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const result = ManifestSchema.safeParse(manifest)
|
|
74
|
+
if (!result.success) {
|
|
75
|
+
console.error('Generated manifest failed validation:')
|
|
76
|
+
for (const issue of result.error.issues) {
|
|
77
|
+
console.error(` - ${issue.path.join('.') || '(root)'}: ${issue.message}`)
|
|
78
|
+
}
|
|
79
|
+
process.exit(1)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await mkdir(outputDir, { recursive: true })
|
|
83
|
+
await writeFile(outputFile, JSON.stringify(result.data, null, 2), 'utf8')
|
|
84
|
+
|
|
85
|
+
const componentCount = Object.keys(components).length
|
|
86
|
+
console.log(`Wrote ${outputFile} (${componentCount} components)`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
await main()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { copyFile, mkdir, readdir, readFile, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { basename, dirname, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
const stylesSrc = resolve(__dirname, '../src/styles')
|
|
7
|
+
const stylesDist = resolve(__dirname, '../dist/styles')
|
|
8
|
+
|
|
9
|
+
await mkdir(stylesDist, { recursive: true })
|
|
10
|
+
|
|
11
|
+
const entries = await readdir(stylesSrc)
|
|
12
|
+
const cssFiles = entries.filter((f) => f.endsWith('.css'))
|
|
13
|
+
|
|
14
|
+
for (const file of cssFiles) {
|
|
15
|
+
await copyFile(resolve(stylesSrc, file), resolve(stylesDist, file))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Also emit a combined bundle so consumers can import `@forumone/throughline-reference-ds/styles.css`.
|
|
19
|
+
const bundleParts: string[] = []
|
|
20
|
+
for (const file of ['reset.css', 'tokens.css', 'base.css']) {
|
|
21
|
+
if (cssFiles.includes(file)) {
|
|
22
|
+
const content = await readFile(resolve(stylesSrc, file), 'utf8')
|
|
23
|
+
bundleParts.push(`/* ${basename(file)} */\n${content.trim()}\n`)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
await writeFile(resolve(stylesDist, 'index.css'), bundleParts.join('\n'), 'utf8')
|
|
27
|
+
|
|
28
|
+
console.log(`Copied ${cssFiles.length} CSS files to dist/styles`)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { dirname, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { colors, darkOverrides } from '../src/tokens/colors.ts'
|
|
5
|
+
import { layout } from '../src/tokens/layout.ts'
|
|
6
|
+
import { radii } from '../src/tokens/radii.ts'
|
|
7
|
+
import { spacing } from '../src/tokens/spacing.ts'
|
|
8
|
+
import { typography } from '../src/tokens/typography.ts'
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
11
|
+
const outputPath = resolve(__dirname, '../src/styles/tokens.css')
|
|
12
|
+
|
|
13
|
+
/** Turns `color.brand.primaryHover` into `--color-brand-primary-hover`. */
|
|
14
|
+
function tokenToVariable(name: string): string {
|
|
15
|
+
const kebab = name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
|
|
16
|
+
return `--${kebab.replace(/\./g, '-')}`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function section(title: string, entries: Array<readonly [string, string]>): string {
|
|
20
|
+
const rules = entries.map(([name, value]) => ` ${tokenToVariable(name)}: ${value};`).join('\n')
|
|
21
|
+
return ` /* ${title} */\n${rules}`
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const light = [
|
|
25
|
+
section('Colors', Object.entries(colors)),
|
|
26
|
+
section('Typography', Object.entries(typography)),
|
|
27
|
+
section('Spacing', Object.entries(spacing)),
|
|
28
|
+
section('Radii', Object.entries(radii)),
|
|
29
|
+
section('Layout & Containers', Object.entries(layout)),
|
|
30
|
+
].join('\n\n')
|
|
31
|
+
|
|
32
|
+
const dark = Object.entries(darkOverrides)
|
|
33
|
+
.map(([name, value]) => ` ${tokenToVariable(name)}: ${value};`)
|
|
34
|
+
.join('\n')
|
|
35
|
+
|
|
36
|
+
const banner = '/* Auto-generated by scripts/build-tokens-css.ts. Do not edit by hand. */'
|
|
37
|
+
|
|
38
|
+
const output = `${banner}\n\n:root {\n${light}\n}\n\n@media (prefers-color-scheme: dark) {\n :root {\n${dark}\n }\n}\n`
|
|
39
|
+
|
|
40
|
+
await mkdir(dirname(outputPath), { recursive: true })
|
|
41
|
+
await writeFile(outputPath, output, 'utf8')
|
|
42
|
+
|
|
43
|
+
console.log(`Wrote ${outputPath}`)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { readFile, stat } from 'node:fs/promises'
|
|
2
|
+
import { dirname, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { loadManifest } from '@forumone/throughline-design-contract'
|
|
5
|
+
import { formatLintIssues, lintManifest } from '@forumone/throughline-design-contract/lint'
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const packageRoot = resolve(__dirname, '..')
|
|
9
|
+
const manifestPath = resolve(packageRoot, 'dist/manifest.json')
|
|
10
|
+
const storybookIndexPath = resolve(packageRoot, 'storybook-static/index.json')
|
|
11
|
+
|
|
12
|
+
async function readJson<T>(path: string): Promise<T> {
|
|
13
|
+
const raw = await readFile(path, 'utf8')
|
|
14
|
+
return JSON.parse(raw) as T
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function collectStoryIds(): Promise<Set<string> | undefined> {
|
|
18
|
+
const exists = await stat(storybookIndexPath).catch(() => null)
|
|
19
|
+
if (!exists) {
|
|
20
|
+
console.warn(
|
|
21
|
+
`No storybook-static/index.json found; skipping storyId lint. Run \`pnpm build-storybook\` first to enable it.`,
|
|
22
|
+
)
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
const index = await readJson<{ entries: Record<string, { id: string; type: string }> }>(
|
|
26
|
+
storybookIndexPath,
|
|
27
|
+
)
|
|
28
|
+
const ids = new Set<string>()
|
|
29
|
+
for (const entry of Object.values(index.entries)) {
|
|
30
|
+
if (entry.type === 'story') ids.add(entry.id)
|
|
31
|
+
}
|
|
32
|
+
return ids
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function main() {
|
|
36
|
+
const raw = await readJson<unknown>(manifestPath)
|
|
37
|
+
const loaded = loadManifest(raw)
|
|
38
|
+
|
|
39
|
+
const availableStoryIds = await collectStoryIds()
|
|
40
|
+
const lintOptions = availableStoryIds ? { availableStoryIds } : {}
|
|
41
|
+
|
|
42
|
+
const issues = lintManifest(loaded.raw, lintOptions)
|
|
43
|
+
const errors = issues.filter((i) => i.severity === 'error')
|
|
44
|
+
const warnings = issues.filter((i) => i.severity === 'warning')
|
|
45
|
+
|
|
46
|
+
if (errors.length > 0) {
|
|
47
|
+
console.error(formatLintIssues(errors))
|
|
48
|
+
process.exit(1)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (warnings.length > 0) {
|
|
52
|
+
console.warn(formatLintIssues(warnings))
|
|
53
|
+
} else {
|
|
54
|
+
console.log(`Manifest is clean (${loaded.listComponents().length} components).`)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await main()
|