handoff-app 1.1.0-0 → 1.1.0-experimental.1
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 +5 -0
- package/config/docs/playground.md +14 -0
- package/config/docs/system.md +2 -0
- package/dist/app/components/Component/Cards.js +17 -0
- package/dist/app-builder/build.d.ts +6 -1
- package/dist/app-builder/build.js +43 -14
- package/dist/app-builder/index.d.ts +1 -0
- package/dist/app-builder/index.js +9 -1
- package/dist/app-builder/isr-paths.d.ts +44 -0
- package/dist/app-builder/isr-paths.js +187 -0
- package/dist/app-builder/watchers.d.ts +5 -1
- package/dist/app-builder/watchers.js +59 -1
- package/dist/commands/index.js +16 -2
- package/dist/commands/isr/component.d.ts +10 -0
- package/dist/commands/isr/component.js +63 -0
- package/dist/commands/isr/pages.d.ts +11 -0
- package/dist/commands/isr/pages.js +64 -0
- package/dist/commands/platform/init.d.ts +6 -0
- package/dist/commands/platform/init.js +231 -0
- package/dist/commands/platform/login.d.ts +6 -0
- package/dist/commands/platform/login.js +108 -0
- package/dist/commands/platform/logout.d.ts +6 -0
- package/dist/commands/platform/logout.js +88 -0
- package/dist/commands/platform/pull.d.ts +8 -0
- package/dist/commands/platform/pull.js +112 -0
- package/dist/commands/platform/push.d.ts +8 -0
- package/dist/commands/platform/push.js +428 -0
- package/dist/config/runtime.d.ts +5 -0
- package/dist/config/runtime.js +67 -4
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -2
- package/dist/pipeline/index.d.ts +1 -0
- package/dist/pipeline/index.js +3 -1
- package/dist/pipeline/pages.d.ts +6 -0
- package/dist/pipeline/pages.js +21 -0
- package/dist/platform/client.d.ts +122 -0
- package/dist/platform/client.js +228 -0
- package/dist/platform/credentials.d.ts +40 -0
- package/dist/platform/credentials.js +91 -0
- package/dist/platform/sync.d.ts +68 -0
- package/dist/platform/sync.js +349 -0
- package/dist/transformers/plugins/csf-render.js +18 -1
- package/dist/transformers/plugins/ssr-render.js +14 -0
- package/dist/transformers/preview/page/api.d.ts +8 -0
- package/dist/transformers/preview/page/api.js +74 -0
- package/dist/transformers/preview/page/builder.d.ts +7 -0
- package/dist/transformers/preview/page/builder.js +173 -0
- package/dist/transformers/preview/page/types.d.ts +38 -0
- package/dist/transformers/preview/page/types.js +2 -0
- package/dist/transformers/utils/build.d.ts +18 -0
- package/dist/transformers/utils/build.js +108 -0
- package/dist/types/config.d.ts +19 -0
- package/docs/cli.md +66 -52
- package/docs/components.md +107 -0
- package/docs/isr.md +113 -0
- package/docs/pages.md +152 -0
- package/docs/rest.yml +590 -0
- package/docs/rest_api.md +78 -0
- package/eslint.config.mjs +18 -0
- package/handoff.config.js +90 -0
- package/package.json +10 -6
- package/src/app/components/Page/PageLists.tsx +218 -0
- package/src/app/components/Page/types.ts +19 -0
- package/src/app/components/Playground/ComponentCard.tsx +78 -0
- package/src/app/components/Playground/ComponentLibrary.tsx +99 -0
- package/src/app/components/Playground/EditContext.tsx +159 -0
- package/src/app/components/Playground/EditSheet.tsx +80 -0
- package/src/app/components/Playground/MediaBrowser.tsx +56 -0
- package/src/app/components/Playground/PlaygroundBuilder.tsx +160 -0
- package/src/app/components/Playground/PlaygroundContext.tsx +276 -0
- package/src/app/components/Playground/Preview.tsx +174 -0
- package/src/app/components/Playground/SortableItem.tsx +45 -0
- package/src/app/components/Playground/TemplateManager.tsx +81 -0
- package/src/app/components/Playground/Wizard/ApiKeySettings.tsx +125 -0
- package/src/app/components/Playground/Wizard/WizardDialog.tsx +228 -0
- package/src/app/components/Playground/Wizard/llm-client.ts +87 -0
- package/src/app/components/Playground/Wizard/prompt-builder.ts +78 -0
- package/src/app/components/Playground/Wizard/response-parser.ts +81 -0
- package/src/app/components/Playground/fields/ButtonField.tsx +24 -0
- package/src/app/components/Playground/fields/Field.tsx +112 -0
- package/src/app/components/Playground/fields/FieldLabel.tsx +20 -0
- package/src/app/components/Playground/fields/ImageField.tsx +92 -0
- package/src/app/components/Playground/fields/LinkField.tsx +24 -0
- package/src/app/components/Playground/fields/RichTextField.tsx +34 -0
- package/src/app/components/Playground/fields/TextField.tsx +13 -0
- package/src/app/components/Playground/types.ts +30 -0
- package/src/app/components/ui/dialog.tsx +80 -0
- package/src/app/components/ui/textarea.tsx +19 -0
- package/src/app/components/util/index.ts +61 -8
- package/src/app/next.config.mjs +2 -10
- package/src/app/pages/playground/index.tsx +30 -0
- package/src/app/pages/system/page/[page]/index.tsx +300 -0
- package/src/app/pages/system/page/index.tsx +124 -0
- package/src/app/tsconfig.json +1 -1
- package/src/app-builder/build.ts +59 -16
- package/src/app-builder/index.ts +9 -0
- package/src/app-builder/isr-paths.ts +183 -0
- package/src/app-builder/watchers.ts +59 -0
- package/src/commands/index.ts +14 -0
- package/src/commands/isr/component.ts +68 -0
- package/src/commands/isr/pages.ts +68 -0
- package/src/commands/platform/init.ts +229 -0
- package/src/commands/platform/login.ts +96 -0
- package/src/commands/platform/logout.ts +63 -0
- package/src/commands/platform/pull.ts +98 -0
- package/src/commands/platform/push.ts +469 -0
- package/src/config/runtime.ts +76 -0
- package/src/index.ts +3 -3
- package/src/pipeline/index.ts +1 -0
- package/src/pipeline/pages.ts +10 -0
- package/src/platform/client.ts +335 -0
- package/src/platform/credentials.ts +106 -0
- package/src/platform/sync.ts +428 -0
- package/src/transformers/plugins/csf-render.ts +17 -0
- package/src/transformers/plugins/ssr-render.ts +17 -8
- package/src/transformers/preview/page/api.ts +65 -0
- package/src/transformers/preview/page/builder.ts +200 -0
- package/src/transformers/preview/page/types.ts +37 -0
- package/src/transformers/utils/build.ts +112 -0
- package/src/types/config.ts +21 -0
- package/test_components/example/example.js +110 -0
- package/test_components/example/style.scss +56 -0
- package/test_components/example/template.hbs +19 -0
- package/test_components/example-csf/example-csf.js +16 -0
- package/test_components/example-csf/style.scss +52 -0
- package/test_components/example-csf/template.stories.tsx +97 -0
- package/test_components/example-react/example-react.js +69 -0
- package/test_components/example-react/style.scss +56 -0
- package/test_components/example-react/template.tsx +49 -0
- package/test_pages/boilerplate/boilerplate.json +73 -0
- package/tsconfig.json +1 -1
- package/dist/app/components/Component/Cards.jsx +0 -32
- package/docs/api.md +0 -279
- package/docs/api_spec.yml +0 -0
- package/docs/props.md +0 -34
package/Changelog.md
CHANGED
|
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
and this project adheres to
|
|
7
7
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
+
## \[1.2.0]
|
|
10
|
+
|
|
11
|
+
* Upgrade to Next16
|
|
12
|
+
* Add pagination data structure to arrays
|
|
13
|
+
|
|
9
14
|
## \[1.1.0] - 2026-03-05
|
|
10
15
|
|
|
11
16
|
This release introduces two major new features. First, handoff now can do automatic
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Playground
|
|
3
|
+
description: Build pages from design system components. Select, arrange, edit, and preview components in a live builder.
|
|
4
|
+
weight: 50
|
|
5
|
+
menuTitle: 'Playground'
|
|
6
|
+
metaTitle: 'Playground | Handoff Design System'
|
|
7
|
+
metaDescription: 'Interactive playground for building pages from design system components.'
|
|
8
|
+
enabled: true
|
|
9
|
+
menu:
|
|
10
|
+
- title: Playground
|
|
11
|
+
menu:
|
|
12
|
+
- path: playground
|
|
13
|
+
title: Builder
|
|
14
|
+
---
|
package/config/docs/system.md
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const lucide_react_1 = require("lucide-react");
|
|
5
|
+
const PracticeLine = ({ line, type }) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex items-start gap-3", children: [type === 'positive' ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "mt-[5px] h-3 w-3 shrink-0 text-emerald-600", strokeWidth: 3 })) : type === 'negative' ? ((0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "mt-[5px] h-3 w-3 shrink-0 text-gray-400", strokeWidth: 3 })) : ((0, jsx_runtime_1.jsx)("span", { className: "mt-[5px] h-3 w-3 shrink-0" })), (0, jsx_runtime_1.jsx)("p", { className: "text-sm", children: line })] }));
|
|
6
|
+
const CardItem = ({ card }) => {
|
|
7
|
+
// Split content by newlines and render each line as a separate item
|
|
8
|
+
const lines = card.content.split('\n').filter((line) => line.trim());
|
|
9
|
+
return ((0, jsx_runtime_1.jsx)("ul", { className: "space-y-3 text-emerald-800", children: lines.map((line, index) => ((0, jsx_runtime_1.jsx)(PracticeLine, { line: line, type: card.type }, `do-rule-${index}`))) }));
|
|
10
|
+
};
|
|
11
|
+
const Cards = ({ cards, maxCardsPerRow = 2, className = '' }) => {
|
|
12
|
+
if (!cards || cards.length === 0) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "grid grid-cols-[repeat(auto-fit,minmax(100%,1fr))] gap-6 sm:grid-cols-[repeat(auto-fit,minmax(300px,1fr))]", children: cards.map((card, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "relative rounded-lg border bg-gray-50 p-8 text-gray-600 dark:bg-gray-800", children: [(0, jsx_runtime_1.jsx)("h2", { className: "mb-3 font-normal text-gray-700", children: card.title }), (0, jsx_runtime_1.jsx)(CardItem, { card: card })] }, `card-${index}`))) }));
|
|
16
|
+
};
|
|
17
|
+
exports.default = Cards;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import Handoff from '..';
|
|
2
2
|
/**
|
|
3
3
|
* Build the Next.js documentation application.
|
|
4
|
+
* @param copyOnlyPaths - If set, do not remove output dir; copy only these paths (relative to out/) into existing output (merge).
|
|
5
|
+
* @param deployDir - If set, copy output to this directory instead of default (workingPath/sitesDirectory/projectId).
|
|
4
6
|
*/
|
|
5
|
-
declare const buildApp: (handoff: Handoff, skipComponents?: boolean
|
|
7
|
+
declare const buildApp: (handoff: Handoff, skipComponents?: boolean, options?: {
|
|
8
|
+
copyOnlyPaths?: string[];
|
|
9
|
+
deployDir?: string;
|
|
10
|
+
}) => Promise<void>;
|
|
6
11
|
/**
|
|
7
12
|
* Watch the Next.js application.
|
|
8
13
|
* Starts a custom dev server with Handoff-specific watchers and hot-reloading.
|
|
@@ -17,12 +17,14 @@ const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
|
|
17
17
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
18
18
|
const path_1 = __importDefault(require("path"));
|
|
19
19
|
const components_1 = require("../pipeline/components");
|
|
20
|
+
const pages_1 = require("../pipeline/pages");
|
|
21
|
+
const builder_1 = __importDefault(require("../transformers/preview/component/builder"));
|
|
20
22
|
const css_1 = require("../transformers/preview/component/css");
|
|
21
23
|
const javascript_1 = require("../transformers/preview/component/javascript");
|
|
22
|
-
const builder_1 = __importDefault(require("../transformers/preview/component/builder"));
|
|
23
24
|
const logger_1 = require("../utils/logger");
|
|
24
25
|
const client_config_1 = require("./client-config");
|
|
25
26
|
const paths_1 = require("./paths");
|
|
27
|
+
const builder_2 = require("../transformers/preview/page/builder");
|
|
26
28
|
const watchers_1 = require("./watchers");
|
|
27
29
|
const websocket_1 = require("./websocket");
|
|
28
30
|
/**
|
|
@@ -81,19 +83,24 @@ const initializeProjectApp = (handoff) => __awaiter(void 0, void 0, void 0, func
|
|
|
81
83
|
});
|
|
82
84
|
/**
|
|
83
85
|
* Build the Next.js documentation application.
|
|
86
|
+
* @param copyOnlyPaths - If set, do not remove output dir; copy only these paths (relative to out/) into existing output (merge).
|
|
87
|
+
* @param deployDir - If set, copy output to this directory instead of default (workingPath/sitesDirectory/projectId).
|
|
84
88
|
*/
|
|
85
|
-
const buildApp = (handoff, skipComponents) => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
+
const buildApp = (handoff, skipComponents, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
86
90
|
skipComponents = skipComponents !== null && skipComponents !== void 0 ? skipComponents : false;
|
|
91
|
+
const copyOnlyPaths = options === null || options === void 0 ? void 0 : options.copyOnlyPaths;
|
|
92
|
+
const deployDir = options === null || options === void 0 ? void 0 : options.deployDir;
|
|
87
93
|
// Perform cleanup
|
|
88
94
|
yield cleanupAppDirectory(handoff);
|
|
89
95
|
// Build components
|
|
90
96
|
if (!skipComponents) {
|
|
91
97
|
yield (0, components_1.buildComponents)(handoff);
|
|
92
98
|
}
|
|
99
|
+
// Build pages (must run after components so rendered outputs exist)
|
|
100
|
+
yield (0, pages_1.buildPages)(handoff);
|
|
93
101
|
// Prepare app
|
|
94
102
|
const appPath = yield initializeProjectApp(handoff);
|
|
95
103
|
yield (0, client_config_1.persistClientConfig)(handoff);
|
|
96
|
-
// Build app
|
|
97
104
|
const buildResult = cross_spawn_1.default.sync('npx', ['next', 'build'], {
|
|
98
105
|
cwd: appPath,
|
|
99
106
|
stdio: 'inherit',
|
|
@@ -106,16 +113,35 @@ const buildApp = (handoff, skipComponents) => __awaiter(void 0, void 0, void 0,
|
|
|
106
113
|
}
|
|
107
114
|
throw new Error(errorMsg);
|
|
108
115
|
}
|
|
109
|
-
//
|
|
110
|
-
const outputRoot =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const output = path_1.default.resolve(outputRoot, handoff.getProjectId());
|
|
114
|
-
if (
|
|
115
|
-
yield fs_extra_1.default.
|
|
116
|
+
// Resolve output directory: explicit deployDir or default under working path
|
|
117
|
+
const outputRoot = deployDir
|
|
118
|
+
? path_1.default.resolve(deployDir)
|
|
119
|
+
: path_1.default.resolve(handoff.workingPath, handoff.sitesDirectory);
|
|
120
|
+
const output = deployDir ? outputRoot : path_1.default.resolve(outputRoot, handoff.getProjectId());
|
|
121
|
+
if (!deployDir) {
|
|
122
|
+
yield fs_extra_1.default.ensureDir(path_1.default.resolve(handoff.workingPath, handoff.sitesDirectory));
|
|
123
|
+
}
|
|
124
|
+
if (copyOnlyPaths && copyOnlyPaths.length > 0) {
|
|
125
|
+
// Partial deploy: merge only the listed paths into existing output
|
|
126
|
+
yield fs_extra_1.default.ensureDir(output);
|
|
127
|
+
const outDir = path_1.default.resolve(appPath, 'out');
|
|
128
|
+
for (const relativePath of copyOnlyPaths) {
|
|
129
|
+
const src = path_1.default.join(outDir, relativePath);
|
|
130
|
+
const dest = path_1.default.join(output, relativePath);
|
|
131
|
+
if (fs_extra_1.default.existsSync(src)) {
|
|
132
|
+
yield fs_extra_1.default.ensureDir(path_1.default.dirname(dest));
|
|
133
|
+
yield fs_extra_1.default.copy(src, dest, { overwrite: true });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Full deploy: replace output with full out
|
|
139
|
+
if (fs_extra_1.default.existsSync(output)) {
|
|
140
|
+
yield fs_extra_1.default.remove(output);
|
|
141
|
+
}
|
|
142
|
+
yield fs_extra_1.default.ensureDir(output);
|
|
143
|
+
yield fs_extra_1.default.copy(path_1.default.resolve(appPath, 'out'), output);
|
|
116
144
|
}
|
|
117
|
-
// Copy the build files into the project output directory
|
|
118
|
-
yield fs_extra_1.default.copy(path_1.default.resolve(appPath, 'out'), output);
|
|
119
145
|
});
|
|
120
146
|
/**
|
|
121
147
|
* Watch the Next.js application.
|
|
@@ -128,6 +154,8 @@ const watchApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
128
154
|
yield (0, builder_1.default)(handoff, undefined, undefined, { useCache: true });
|
|
129
155
|
yield (0, javascript_1.buildMainJS)(handoff);
|
|
130
156
|
yield (0, css_1.buildMainCss)(handoff);
|
|
157
|
+
// Build pages after components
|
|
158
|
+
yield (0, builder_2.processPages)(handoff);
|
|
131
159
|
const appPath = yield initializeProjectApp(handoff);
|
|
132
160
|
// Persist client configuration
|
|
133
161
|
yield (0, client_config_1.persistClientConfig)(handoff);
|
|
@@ -142,7 +170,7 @@ const watchApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
142
170
|
// create empty directory
|
|
143
171
|
yield fs_extra_1.default.ensureDir(moduleOutput);
|
|
144
172
|
}
|
|
145
|
-
const nextProcess = (0, cross_spawn_1.default)('npx', ['next', 'dev', '--
|
|
173
|
+
const nextProcess = (0, cross_spawn_1.default)('npx', ['next', 'dev', '--port', String(port)], {
|
|
146
174
|
cwd: appPath,
|
|
147
175
|
stdio: 'inherit',
|
|
148
176
|
env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'development' }),
|
|
@@ -172,6 +200,7 @@ const watchApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
172
200
|
(0, watchers_1.watchRuntimeConfiguration)(handoff, state);
|
|
173
201
|
(0, watchers_1.watchGlobalEntries)(handoff, state, chokidarConfig);
|
|
174
202
|
(0, watchers_1.watchPages)(handoff, chokidarConfig);
|
|
203
|
+
(0, watchers_1.watchRuntimePages)(handoff, state);
|
|
175
204
|
});
|
|
176
205
|
exports.watchApp = watchApp;
|
|
177
206
|
/**
|
|
@@ -190,7 +219,7 @@ const devApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
190
219
|
// Persist client configuration
|
|
191
220
|
yield (0, client_config_1.persistClientConfig)(handoff);
|
|
192
221
|
// Run
|
|
193
|
-
const devResult = cross_spawn_1.default.sync('npx', ['next', 'dev', '--
|
|
222
|
+
const devResult = cross_spawn_1.default.sync('npx', ['next', 'dev', '--port', String((_b = (_a = handoff.config.app.ports) === null || _a === void 0 ? void 0 : _a.app) !== null && _b !== void 0 ? _b : 3000)], {
|
|
194
223
|
cwd: appPath,
|
|
195
224
|
stdio: 'inherit',
|
|
196
225
|
env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'development' }),
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { buildComponents } from '../pipeline/components';
|
|
2
2
|
export { default, devApp, watchApp } from './build';
|
|
3
|
+
export { getL1StaticPathSegments, getL2StaticPathSegments, normalizeRoutePath, resolveAffectedOutputPaths, resolveComponentAffectedOutputPaths, resolveComponentAffectedOutputPathsBatch, routePathToOutputPaths, } from './isr-paths';
|
|
@@ -3,10 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.watchApp = exports.devApp = exports.default = exports.buildComponents = void 0;
|
|
6
|
+
exports.routePathToOutputPaths = exports.resolveComponentAffectedOutputPathsBatch = exports.resolveComponentAffectedOutputPaths = exports.resolveAffectedOutputPaths = exports.normalizeRoutePath = exports.getL2StaticPathSegments = exports.getL1StaticPathSegments = exports.watchApp = exports.devApp = exports.default = exports.buildComponents = void 0;
|
|
7
7
|
var components_1 = require("../pipeline/components");
|
|
8
8
|
Object.defineProperty(exports, "buildComponents", { enumerable: true, get: function () { return components_1.buildComponents; } });
|
|
9
9
|
var build_1 = require("./build");
|
|
10
10
|
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(build_1).default; } });
|
|
11
11
|
Object.defineProperty(exports, "devApp", { enumerable: true, get: function () { return build_1.devApp; } });
|
|
12
12
|
Object.defineProperty(exports, "watchApp", { enumerable: true, get: function () { return build_1.watchApp; } });
|
|
13
|
+
var isr_paths_1 = require("./isr-paths");
|
|
14
|
+
Object.defineProperty(exports, "getL1StaticPathSegments", { enumerable: true, get: function () { return isr_paths_1.getL1StaticPathSegments; } });
|
|
15
|
+
Object.defineProperty(exports, "getL2StaticPathSegments", { enumerable: true, get: function () { return isr_paths_1.getL2StaticPathSegments; } });
|
|
16
|
+
Object.defineProperty(exports, "normalizeRoutePath", { enumerable: true, get: function () { return isr_paths_1.normalizeRoutePath; } });
|
|
17
|
+
Object.defineProperty(exports, "resolveAffectedOutputPaths", { enumerable: true, get: function () { return isr_paths_1.resolveAffectedOutputPaths; } });
|
|
18
|
+
Object.defineProperty(exports, "resolveComponentAffectedOutputPaths", { enumerable: true, get: function () { return isr_paths_1.resolveComponentAffectedOutputPaths; } });
|
|
19
|
+
Object.defineProperty(exports, "resolveComponentAffectedOutputPathsBatch", { enumerable: true, get: function () { return isr_paths_1.resolveComponentAffectedOutputPathsBatch; } });
|
|
20
|
+
Object.defineProperty(exports, "routePathToOutputPaths", { enumerable: true, get: function () { return isr_paths_1.routePathToOutputPaths; } });
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Handoff from '..';
|
|
2
|
+
/**
|
|
3
|
+
* Returns level-1 path segments (one segment, e.g. "guidelines") for doc/pages.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getL1StaticPathSegments(modulePath: string, workingPath: string): string[];
|
|
6
|
+
/**
|
|
7
|
+
* Returns level-2 path segments { level1, level2 } for doc/pages.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getL2StaticPathSegments(modulePath: string, workingPath: string): Array<{
|
|
10
|
+
level1: string;
|
|
11
|
+
level2: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Normalize a route path (e.g. "/guidelines" or "foundations/colors") to a segment path without leading slash.
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeRoutePath(routePath: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a single route path to the corresponding static output file path(s) under out/.
|
|
19
|
+
* Next.js static export with trailingSlash produces path/index.html for each route.
|
|
20
|
+
*/
|
|
21
|
+
export declare function routePathToOutputPaths(routePath: string): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Resolve affected static output file paths (relative to out/) for ISR.
|
|
24
|
+
*
|
|
25
|
+
* @param handoff - Handoff instance (used for modulePath, workingPath)
|
|
26
|
+
* @param options.path - Single route path to invalidate (e.g. "/guidelines", "foundations/colors")
|
|
27
|
+
* @param options.paths - Multiple route paths to invalidate
|
|
28
|
+
* @param options.menuChanged - If true, return all menu-linked routes (all doc pages + system index pages)
|
|
29
|
+
* @returns Relative paths under out/, e.g. ["index.html", "guidelines/index.html"]
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveAffectedOutputPaths(handoff: Handoff, options: {
|
|
32
|
+
path?: string;
|
|
33
|
+
paths?: string[];
|
|
34
|
+
menuChanged?: boolean;
|
|
35
|
+
}): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Resolve affected static output file paths for a component ISR update.
|
|
38
|
+
* Returns paths under out/ for the component route, component list, and API JSON files.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveComponentAffectedOutputPaths(componentId: string): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Resolve affected output paths for multiple components (union).
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveComponentAffectedOutputPathsBatch(componentIds: string[]): string[];
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getL1StaticPathSegments = getL1StaticPathSegments;
|
|
7
|
+
exports.getL2StaticPathSegments = getL2StaticPathSegments;
|
|
8
|
+
exports.normalizeRoutePath = normalizeRoutePath;
|
|
9
|
+
exports.routePathToOutputPaths = routePathToOutputPaths;
|
|
10
|
+
exports.resolveAffectedOutputPaths = resolveAffectedOutputPaths;
|
|
11
|
+
exports.resolveComponentAffectedOutputPaths = resolveComponentAffectedOutputPaths;
|
|
12
|
+
exports.resolveComponentAffectedOutputPathsBatch = resolveComponentAffectedOutputPathsBatch;
|
|
13
|
+
/**
|
|
14
|
+
* ISR path resolver: computes which static output files (under out/) are affected
|
|
15
|
+
* for a given page path or "menu changed", for use with partial deploy.
|
|
16
|
+
*
|
|
17
|
+
* Mirrors the route structure from buildL1StaticPaths / buildL2StaticPaths (see app/components/util)
|
|
18
|
+
* but runs in CLI context using handoff paths instead of process.env.
|
|
19
|
+
*/
|
|
20
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
21
|
+
const path_1 = __importDefault(require("path"));
|
|
22
|
+
/** Route segments excluded from doc/page path generation (same as knownPaths in util) */
|
|
23
|
+
const KNOWN_PATHS = [
|
|
24
|
+
'assets',
|
|
25
|
+
'assets/fonts',
|
|
26
|
+
'assets/icons',
|
|
27
|
+
'assets/logos',
|
|
28
|
+
'foundations',
|
|
29
|
+
'foundations/colors',
|
|
30
|
+
'foundations/icons',
|
|
31
|
+
'foundations/effects',
|
|
32
|
+
'foundations/logos',
|
|
33
|
+
'foundations/logo',
|
|
34
|
+
'foundations/typography',
|
|
35
|
+
'system',
|
|
36
|
+
'system/component',
|
|
37
|
+
'playground',
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Returns level-1 path segments (one segment, e.g. "guidelines") for doc/pages.
|
|
41
|
+
*/
|
|
42
|
+
function getL1StaticPathSegments(modulePath, workingPath) {
|
|
43
|
+
const docRoot = path_1.default.resolve(modulePath, 'config/docs');
|
|
44
|
+
const pageRoot = path_1.default.resolve(workingPath, 'pages');
|
|
45
|
+
if (!fs_extra_1.default.existsSync(docRoot)) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
let files = fs_extra_1.default.readdirSync(docRoot);
|
|
49
|
+
if (fs_extra_1.default.existsSync(pageRoot)) {
|
|
50
|
+
// ES5-compatible way to merge and deduplicate both arrays
|
|
51
|
+
var moreFiles = fs_extra_1.default.readdirSync(pageRoot);
|
|
52
|
+
for (var i = 0; i < moreFiles.length; i++) {
|
|
53
|
+
if (files.indexOf(moreFiles[i]) === -1) {
|
|
54
|
+
files.push(moreFiles[i]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return files
|
|
59
|
+
.filter((fileName) => {
|
|
60
|
+
const inDoc = path_1.default.join(docRoot, fileName);
|
|
61
|
+
const inPages = path_1.default.join(pageRoot, fileName);
|
|
62
|
+
if (fs_extra_1.default.existsSync(inDoc))
|
|
63
|
+
return !fs_extra_1.default.lstatSync(inDoc).isDirectory();
|
|
64
|
+
if (fs_extra_1.default.existsSync(inPages))
|
|
65
|
+
return !fs_extra_1.default.lstatSync(inPages).isDirectory();
|
|
66
|
+
return false;
|
|
67
|
+
})
|
|
68
|
+
.filter((fileName) => fileName.endsWith('.md'))
|
|
69
|
+
.map((fileName) => fileName.replace('.md', ''))
|
|
70
|
+
.filter((segment) => !KNOWN_PATHS.includes(segment));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns level-2 path segments { level1, level2 } for doc/pages.
|
|
74
|
+
*/
|
|
75
|
+
function getL2StaticPathSegments(modulePath, workingPath) {
|
|
76
|
+
const docRoot = path_1.default.resolve(modulePath, 'config/docs');
|
|
77
|
+
const pageRoot = path_1.default.resolve(workingPath, 'pages');
|
|
78
|
+
if (!fs_extra_1.default.existsSync(docRoot)) {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
let list = fs_extra_1.default.readdirSync(docRoot);
|
|
82
|
+
if (fs_extra_1.default.existsSync(pageRoot)) {
|
|
83
|
+
list = [...new Set([...list, ...fs_extra_1.default.readdirSync(pageRoot)])];
|
|
84
|
+
}
|
|
85
|
+
const result = [];
|
|
86
|
+
for (const fileName of list) {
|
|
87
|
+
let dirPath;
|
|
88
|
+
if (fs_extra_1.default.existsSync(path_1.default.join(pageRoot, fileName))) {
|
|
89
|
+
dirPath = path_1.default.join(pageRoot, fileName);
|
|
90
|
+
}
|
|
91
|
+
else if (fs_extra_1.default.existsSync(path_1.default.join(docRoot, fileName))) {
|
|
92
|
+
dirPath = path_1.default.join(docRoot, fileName);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (!fs_extra_1.default.lstatSync(dirPath).isDirectory())
|
|
98
|
+
continue;
|
|
99
|
+
const subFiles = fs_extra_1.default.readdirSync(dirPath);
|
|
100
|
+
for (const subFile of subFiles) {
|
|
101
|
+
if (!subFile.endsWith('.md'))
|
|
102
|
+
continue;
|
|
103
|
+
const level2 = subFile.replace('.md', '');
|
|
104
|
+
const fullKey = `${fileName}/${level2}`;
|
|
105
|
+
if (KNOWN_PATHS.includes(fullKey))
|
|
106
|
+
continue;
|
|
107
|
+
result.push({ level1: fileName, level2 });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Normalize a route path (e.g. "/guidelines" or "foundations/colors") to a segment path without leading slash.
|
|
114
|
+
*/
|
|
115
|
+
function normalizeRoutePath(routePath) {
|
|
116
|
+
return routePath.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Resolve a single route path to the corresponding static output file path(s) under out/.
|
|
120
|
+
* Next.js static export with trailingSlash produces path/index.html for each route.
|
|
121
|
+
*/
|
|
122
|
+
function routePathToOutputPaths(routePath) {
|
|
123
|
+
const segment = normalizeRoutePath(routePath);
|
|
124
|
+
if (!segment)
|
|
125
|
+
return ['index.html'];
|
|
126
|
+
return [`${segment}/index.html`];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Resolve affected static output file paths (relative to out/) for ISR.
|
|
130
|
+
*
|
|
131
|
+
* @param handoff - Handoff instance (used for modulePath, workingPath)
|
|
132
|
+
* @param options.path - Single route path to invalidate (e.g. "/guidelines", "foundations/colors")
|
|
133
|
+
* @param options.paths - Multiple route paths to invalidate
|
|
134
|
+
* @param options.menuChanged - If true, return all menu-linked routes (all doc pages + system index pages)
|
|
135
|
+
* @returns Relative paths under out/, e.g. ["index.html", "guidelines/index.html"]
|
|
136
|
+
*/
|
|
137
|
+
function resolveAffectedOutputPaths(handoff, options) {
|
|
138
|
+
const { path: singlePath, paths: pathList, menuChanged } = options;
|
|
139
|
+
const modulePath = handoff.modulePath;
|
|
140
|
+
const workingPath = handoff.workingPath;
|
|
141
|
+
if (menuChanged) {
|
|
142
|
+
const l1 = getL1StaticPathSegments(modulePath, workingPath);
|
|
143
|
+
const l2 = getL2StaticPathSegments(modulePath, workingPath);
|
|
144
|
+
const out = ['index.html'];
|
|
145
|
+
for (const segment of l1) {
|
|
146
|
+
out.push(`${segment}/index.html`);
|
|
147
|
+
}
|
|
148
|
+
for (const { level1, level2 } of l2) {
|
|
149
|
+
out.push(`${level1}/${level2}/index.html`);
|
|
150
|
+
}
|
|
151
|
+
out.push('system/index.html', 'system/component/index.html');
|
|
152
|
+
return [...new Set(out)];
|
|
153
|
+
}
|
|
154
|
+
if (singlePath) {
|
|
155
|
+
return routePathToOutputPaths(singlePath);
|
|
156
|
+
}
|
|
157
|
+
if (pathList && pathList.length > 0) {
|
|
158
|
+
const out = [];
|
|
159
|
+
for (const p of pathList) {
|
|
160
|
+
out.push(...routePathToOutputPaths(p));
|
|
161
|
+
}
|
|
162
|
+
return [...new Set(out)];
|
|
163
|
+
}
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolve affected static output file paths for a component ISR update.
|
|
168
|
+
* Returns paths under out/ for the component route, component list, and API JSON files.
|
|
169
|
+
*/
|
|
170
|
+
function resolveComponentAffectedOutputPaths(componentId) {
|
|
171
|
+
return [
|
|
172
|
+
`system/component/${componentId}/index.html`,
|
|
173
|
+
'system/component/index.html',
|
|
174
|
+
`api/component/${componentId}.json`,
|
|
175
|
+
'api/components.json',
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Resolve affected output paths for multiple components (union).
|
|
180
|
+
*/
|
|
181
|
+
function resolveComponentAffectedOutputPathsBatch(componentIds) {
|
|
182
|
+
const out = ['system/component/index.html', 'api/components.json'];
|
|
183
|
+
for (const id of componentIds) {
|
|
184
|
+
out.push(`system/component/${id}/index.html`, `api/component/${id}.json`);
|
|
185
|
+
}
|
|
186
|
+
return [...new Set(out)];
|
|
187
|
+
}
|
|
@@ -34,11 +34,15 @@ export declare const mapEntryTypeToSegment: (type: keyof ComponentListObject["en
|
|
|
34
34
|
*
|
|
35
35
|
* @returns A Map of paths to watch and their entry types
|
|
36
36
|
*/
|
|
37
|
-
export declare const getRuntimeComponentsPathsToWatch: (handoff: Handoff) => Map<string, "
|
|
37
|
+
export declare const getRuntimeComponentsPathsToWatch: (handoff: Handoff) => Map<string, "js" | "scss" | "template">;
|
|
38
38
|
/**
|
|
39
39
|
* Watches runtime components for changes.
|
|
40
40
|
*/
|
|
41
41
|
export declare const watchRuntimeComponents: (handoff: Handoff, state: WatcherState, runtimeComponentPathsToWatch: Map<string, keyof ComponentListObject["entries"]>) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Watches runtime page config files for changes and triggers page rebuilds.
|
|
44
|
+
*/
|
|
45
|
+
export declare const watchRuntimePages: (handoff: Handoff, state: WatcherState) => void;
|
|
42
46
|
/**
|
|
43
47
|
* Watches the runtime configuration for changes.
|
|
44
48
|
*/
|
|
@@ -35,13 +35,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.watchRuntimeConfiguration = exports.watchRuntimeComponents = exports.getRuntimeComponentsPathsToWatch = exports.mapEntryTypeToSegment = exports.watchGlobalEntries = exports.watchPages = exports.watchAppSource = exports.watchPublicDirectory = void 0;
|
|
38
|
+
exports.watchRuntimeConfiguration = exports.watchRuntimePages = exports.watchRuntimeComponents = exports.getRuntimeComponentsPathsToWatch = exports.mapEntryTypeToSegment = exports.watchGlobalEntries = exports.watchPages = exports.watchAppSource = exports.watchPublicDirectory = void 0;
|
|
39
39
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
40
40
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
41
41
|
const path_1 = __importDefault(require("path"));
|
|
42
42
|
const css_1 = require("../transformers/preview/component/css");
|
|
43
43
|
const javascript_1 = require("../transformers/preview/component/javascript");
|
|
44
44
|
const builder_1 = __importStar(require("../transformers/preview/component/builder"));
|
|
45
|
+
const builder_2 = require("../transformers/preview/page/builder");
|
|
45
46
|
const logger_1 = require("../utils/logger");
|
|
46
47
|
const client_config_1 = require("./client-config");
|
|
47
48
|
const paths_1 = require("./paths");
|
|
@@ -260,6 +261,63 @@ const watchRuntimeComponents = (handoff, state, runtimeComponentPathsToWatch) =>
|
|
|
260
261
|
}
|
|
261
262
|
};
|
|
262
263
|
exports.watchRuntimeComponents = watchRuntimeComponents;
|
|
264
|
+
/**
|
|
265
|
+
* Watches runtime page config files for changes and triggers page rebuilds.
|
|
266
|
+
*/
|
|
267
|
+
const watchRuntimePages = (handoff, state) => {
|
|
268
|
+
var _a, _b, _c, _d, _e;
|
|
269
|
+
const runtimePages = (_c = (_b = (_a = handoff.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b.pages) !== null && _c !== void 0 ? _c : {};
|
|
270
|
+
const pageConfigPaths = handoff.getConfigFilePaths().filter((configPath) => {
|
|
271
|
+
const dirName = path_1.default.basename(path_1.default.dirname(configPath));
|
|
272
|
+
return dirName in runtimePages;
|
|
273
|
+
});
|
|
274
|
+
// Also watch page directories directly
|
|
275
|
+
const pageIds = Object.keys(runtimePages);
|
|
276
|
+
if (pageIds.length === 0 && pageConfigPaths.length === 0)
|
|
277
|
+
return;
|
|
278
|
+
const pathsToWatch = pageConfigPaths.length > 0 ? pageConfigPaths : [];
|
|
279
|
+
// Add page config entry paths from the config
|
|
280
|
+
for (const pageId of pageIds) {
|
|
281
|
+
const page = runtimePages[pageId];
|
|
282
|
+
if (page.path && fs_extra_1.default.existsSync(page.path)) {
|
|
283
|
+
pathsToWatch.push(page.path);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Watch the page entry directories from config
|
|
287
|
+
if ((_e = (_d = handoff.config.entries) === null || _d === void 0 ? void 0 : _d.pages) === null || _e === void 0 ? void 0 : _e.length) {
|
|
288
|
+
for (const pagePath of handoff.config.entries.pages) {
|
|
289
|
+
const resolvedPath = path_1.default.resolve(handoff.workingPath, pagePath);
|
|
290
|
+
if (fs_extra_1.default.existsSync(resolvedPath)) {
|
|
291
|
+
pathsToWatch.push(resolvedPath);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (pathsToWatch.length === 0)
|
|
296
|
+
return;
|
|
297
|
+
chokidar_1.default.watch(pathsToWatch, { ignoreInitial: true }).on('all', (event, file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
298
|
+
switch (event) {
|
|
299
|
+
case 'add':
|
|
300
|
+
case 'change':
|
|
301
|
+
case 'unlink':
|
|
302
|
+
if (!state.debounce) {
|
|
303
|
+
state.debounce = true;
|
|
304
|
+
try {
|
|
305
|
+
logger_1.Logger.warn('Page config changed. Rebuilding pages...');
|
|
306
|
+
handoff.reload();
|
|
307
|
+
yield (0, builder_2.processPages)(handoff);
|
|
308
|
+
}
|
|
309
|
+
catch (e) {
|
|
310
|
+
logger_1.Logger.error('Error processing pages:', e);
|
|
311
|
+
}
|
|
312
|
+
finally {
|
|
313
|
+
state.debounce = false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}));
|
|
319
|
+
};
|
|
320
|
+
exports.watchRuntimePages = watchRuntimePages;
|
|
263
321
|
/**
|
|
264
322
|
* Watches the runtime configuration for changes.
|
|
265
323
|
*/
|
package/dist/commands/index.js
CHANGED
|
@@ -12,9 +12,16 @@ const pages_1 = __importDefault(require("./eject/pages"));
|
|
|
12
12
|
const theme_1 = __importDefault(require("./eject/theme"));
|
|
13
13
|
const fetch_1 = __importDefault(require("./fetch"));
|
|
14
14
|
const init_1 = __importDefault(require("./init"));
|
|
15
|
-
const component_1 = __importDefault(require("./
|
|
15
|
+
const component_1 = __importDefault(require("./isr/component"));
|
|
16
|
+
const pages_2 = __importDefault(require("./isr/pages"));
|
|
17
|
+
const component_2 = __importDefault(require("./make/component"));
|
|
16
18
|
const page_1 = __importDefault(require("./make/page"));
|
|
17
19
|
const template_1 = __importDefault(require("./make/template"));
|
|
20
|
+
const init_2 = __importDefault(require("./platform/init"));
|
|
21
|
+
const login_1 = __importDefault(require("./platform/login"));
|
|
22
|
+
const logout_1 = __importDefault(require("./platform/logout"));
|
|
23
|
+
const pull_1 = __importDefault(require("./platform/pull"));
|
|
24
|
+
const push_1 = __importDefault(require("./platform/push"));
|
|
18
25
|
const scaffold_1 = __importDefault(require("./scaffold"));
|
|
19
26
|
const start_1 = __importDefault(require("./start"));
|
|
20
27
|
const components_2 = __importDefault(require("./validate/components"));
|
|
@@ -27,9 +34,16 @@ exports.commands = [
|
|
|
27
34
|
theme_1.default,
|
|
28
35
|
fetch_1.default,
|
|
29
36
|
init_1.default,
|
|
30
|
-
|
|
37
|
+
pages_2.default,
|
|
31
38
|
component_1.default,
|
|
39
|
+
page_1.default,
|
|
40
|
+
component_2.default,
|
|
32
41
|
template_1.default,
|
|
42
|
+
login_1.default,
|
|
43
|
+
init_2.default,
|
|
44
|
+
pull_1.default,
|
|
45
|
+
push_1.default,
|
|
46
|
+
logout_1.default,
|
|
33
47
|
scaffold_1.default,
|
|
34
48
|
start_1.default,
|
|
35
49
|
components_2.default,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CommandModule } from 'yargs';
|
|
2
|
+
import { SharedArgs } from '../types';
|
|
3
|
+
export interface IsrComponentArgs extends SharedArgs {
|
|
4
|
+
id?: string;
|
|
5
|
+
ids?: string[];
|
|
6
|
+
partial?: boolean;
|
|
7
|
+
deployDir?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const command: CommandModule<{}, IsrComponentArgs>;
|
|
10
|
+
export default command;
|