handoff-app 2.0.0-1 → 2.0.0-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -91
- package/config/docs/foundations/colors/guidelines.md +9 -0
- package/config/docs/foundations/effects/guidelines.md +9 -0
- package/config/docs/foundations/effects/resources.md +9 -0
- package/config/docs/foundations/grid.md +10 -0
- package/config/docs/foundations/icons/guidelines.md +9 -0
- package/config/docs/foundations/images/guidelines.md +9 -0
- package/config/docs/foundations/images/resources.md +9 -0
- package/config/docs/foundations/images.md +10 -0
- package/config/docs/foundations/logo/resources.md +9 -0
- package/config/docs/foundations/typography/guidelines.md +9 -0
- package/config/docs/foundations/typography/resources.md +9 -0
- package/config/docs/foundations.md +5 -3
- package/dist/app-builder/build.js +109 -49
- package/dist/app-builder/client-config.js +13 -12
- package/dist/app-builder/paths.js +7 -9
- package/dist/app-builder/static-export.js +6 -6
- package/dist/app-builder/vercel-output.js +2 -2
- package/dist/artifacts/url.d.ts +7 -7
- package/dist/artifacts/url.js +7 -7
- package/dist/cli/auth/browser.d.ts +2 -0
- package/dist/cli/auth/browser.js +33 -0
- package/dist/cli/auth/device.d.ts +11 -0
- package/dist/cli/auth/device.js +155 -0
- package/dist/cli/auth/store.d.ts +29 -0
- package/dist/cli/auth/store.js +146 -0
- package/dist/cli/create.js +48 -3
- package/dist/cli/scaffold.js +20 -154
- package/dist/commands/checkout/index.d.ts +6 -6
- package/dist/commands/checkout/index.js +8 -12
- package/dist/commands/index.js +4 -0
- package/dist/commands/login/index.d.ts +8 -0
- package/dist/commands/login/index.js +53 -0
- package/dist/commands/logout/index.d.ts +7 -0
- package/dist/commands/logout/index.js +54 -0
- package/dist/commands/publish/index.d.ts +6 -5
- package/dist/commands/publish/index.js +8 -11
- package/dist/commands/utils.d.ts +6 -0
- package/dist/commands/utils.js +9 -1
- package/dist/config/entries.d.ts +47 -0
- package/dist/config/entries.js +162 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +5 -1
- package/dist/config/runtime.d.ts +9 -9
- package/dist/config/runtime.js +15 -15
- package/dist/index.d.ts +12 -8
- package/dist/index.js +26 -10
- package/dist/registry/asset-storage/resolve.d.ts +1 -1
- package/dist/registry/asset-storage/resolve.js +1 -1
- package/dist/registry/auth/access-tokens.d.ts +46 -0
- package/dist/registry/auth/access-tokens.js +165 -0
- package/dist/registry/auth/action-tokens.d.ts +66 -0
- package/dist/registry/auth/action-tokens.js +178 -0
- package/dist/registry/auth/crypto.d.ts +4 -0
- package/dist/registry/auth/crypto.js +16 -0
- package/dist/registry/auth/database.d.ts +7 -0
- package/dist/registry/auth/database.js +22 -0
- package/dist/registry/auth/device-authorizations.d.ts +51 -0
- package/dist/registry/auth/device-authorizations.js +170 -0
- package/dist/registry/auth/gravatar.d.ts +1 -0
- package/dist/registry/auth/gravatar.js +8 -0
- package/dist/registry/auth/index.d.ts +11 -0
- package/dist/registry/auth/index.js +72 -0
- package/dist/registry/auth/installation.d.ts +42 -0
- package/dist/registry/auth/installation.js +105 -0
- package/dist/registry/auth/password.d.ts +12 -0
- package/dist/registry/auth/password.js +58 -0
- package/dist/registry/auth/rate-limits.d.ts +22 -0
- package/dist/registry/auth/rate-limits.js +75 -0
- package/dist/registry/auth/types.d.ts +26 -0
- package/dist/registry/auth/types.js +9 -0
- package/dist/registry/auth/user-record.d.ts +13 -0
- package/dist/registry/auth/user-record.js +16 -0
- package/dist/registry/auth/users.d.ts +31 -0
- package/dist/registry/auth/users.js +135 -0
- package/dist/registry/auth/validation.d.ts +3 -0
- package/dist/registry/auth/validation.js +28 -0
- package/dist/registry/checkout/assets.js +4 -2
- package/dist/registry/checkout/index.d.ts +11 -6
- package/dist/registry/checkout/index.js +159 -30
- package/dist/registry/checkout/tokens.js +4 -2
- package/dist/registry/client.d.ts +2 -1
- package/dist/registry/client.js +8 -0
- package/dist/registry/connection.d.ts +9 -0
- package/dist/registry/connection.js +29 -1
- package/dist/registry/db/client.d.ts +9 -9
- package/dist/registry/db/client.js +7 -7
- package/dist/registry/db/driver.d.ts +46 -0
- package/dist/registry/db/{adapter.js → driver.js} +22 -19
- package/dist/registry/db/index.d.ts +2 -2
- package/dist/registry/db/index.js +15 -9
- package/dist/registry/db/migrate.d.ts +1 -1
- package/dist/registry/db/migrate.js +5 -5
- package/dist/registry/db/schema.d.ts +2521 -750
- package/dist/registry/db/schema.js +126 -1
- package/dist/registry/publish/assets.js +1 -1
- package/dist/registry/publish/errors.js +3 -3
- package/dist/registry/publish/index.d.ts +9 -2
- package/dist/registry/publish/index.js +96 -10
- package/dist/registry/publish/tokens.js +1 -1
- package/dist/registry/transfer.d.ts +13 -0
- package/dist/types/config.d.ts +11 -4
- package/docs/cli.md +4 -0
- package/drizzle/0005_add_registry_auth.sql +95 -0
- package/drizzle/meta/0005_snapshot.json +1926 -0
- package/drizzle/meta/_journal.json +8 -1
- package/drizzle.config.ts +1 -1
- package/package.json +5 -4
- package/src/app/components/Auth/AccountLayout.tsx +87 -0
- package/src/app/components/Auth/AuthControls.tsx +99 -0
- package/src/app/components/Auth/AuthShell.tsx +73 -0
- package/src/app/components/Auth/RegistryInstallGate.tsx +23 -0
- package/src/app/components/Auth/RegistrySessionProvider.tsx +15 -0
- package/src/app/components/Auth/api.ts +20 -0
- package/src/app/components/Foundations/DisplayLogo.tsx +3 -3
- package/src/app/components/Layout/Header.tsx +2 -0
- package/src/app/components/Navigation/MobileNav.tsx +2 -0
- package/src/app/lib/auth/api.ts +113 -0
- package/src/app/lib/auth/config.ts +175 -0
- package/src/app/lib/auth/email.ts +34 -0
- package/src/app/lib/docs-api/runtime-config.ts +10 -24
- package/src/app/lib/registry-api/auth.ts +29 -46
- package/src/app/lib/registry-api/errors.ts +2 -2
- package/src/app/lib/registry-api/handler.ts +19 -14
- package/src/app/lib/registry-api/token-transfer.ts +1 -1
- package/src/app/lib/registry-api/transfer.ts +31 -2
- package/src/app/lib/registry-connection.ts +2 -2
- package/src/app/next.config.mjs +13 -4
- package/src/app/pages/_app.tsx +10 -4
- package/src/app/pages/account/index.tsx +153 -0
- package/src/app/pages/account/tokens.tsx +230 -0
- package/src/app/pages/account/users.tsx +310 -0
- package/src/app/pages/api/account/index.ts +26 -0
- package/src/app/pages/api/account/tokens/[id].ts +17 -0
- package/src/app/pages/api/account/tokens/index.ts +44 -0
- package/src/app/pages/api/admin/users/[id]/[action].ts +89 -0
- package/src/app/pages/api/admin/users/index.ts +53 -0
- package/src/app/pages/api/auth/[...nextauth].ts +4 -0
- package/src/app/pages/api/auth/request-reset.ts +53 -0
- package/src/app/pages/api/auth/reset-password.ts +29 -0
- package/src/app/pages/api/install.ts +102 -0
- package/src/app/pages/api/oauth/device/approve.ts +23 -0
- package/src/app/pages/api/oauth/device/index.ts +41 -0
- package/src/app/pages/api/oauth/revoke.ts +24 -0
- package/src/app/pages/api/oauth/token.ts +31 -0
- package/src/app/pages/api/registry/health.ts +4 -3
- package/src/app/pages/api/registry/transfer/[kind]/[id].ts +3 -3
- package/src/app/pages/api/registry/transfer/[kind]/index.ts +21 -0
- package/src/app/pages/api/registry/transfer/assets/[collection].ts +2 -1
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +2 -1
- package/src/app/pages/api/registry/transfer/tokens/[...setId].ts +2 -2
- package/src/app/pages/cli/device.tsx +143 -0
- package/src/app/pages/foundations/icons/index.tsx +2 -2
- package/src/app/pages/foundations/icons/{[name] → library/[name]}/index.tsx +6 -6
- package/src/app/pages/install.tsx +336 -0
- package/src/app/pages/login.tsx +117 -0
- package/src/app/pages/reset-password.tsx +159 -0
- package/src/app/types/next-auth.d.ts +27 -0
- package/src/app-builder/build.ts +96 -59
- package/src/app-builder/client-config.ts +12 -11
- package/src/app-builder/paths.ts +7 -9
- package/src/app-builder/static-export.ts +6 -6
- package/src/app-builder/vercel-output.ts +2 -2
- package/src/artifacts/url.ts +7 -7
- package/src/cli/auth/browser.ts +29 -0
- package/src/cli/auth/device.ts +181 -0
- package/src/cli/auth/store.ts +137 -0
- package/src/cli/create.ts +58 -3
- package/src/cli/scaffold.ts +20 -197
- package/src/commands/checkout/index.ts +10 -15
- package/src/commands/index.ts +4 -0
- package/src/commands/login/index.ts +48 -0
- package/src/commands/logout/index.ts +51 -0
- package/src/commands/publish/index.ts +10 -14
- package/src/commands/utils.ts +12 -0
- package/src/config/entries.ts +175 -0
- package/src/config/index.ts +4 -0
- package/src/config/runtime.ts +15 -14
- package/src/index.ts +26 -12
- package/src/registry/asset-storage/resolve.ts +1 -1
- package/src/registry/auth/access-tokens.ts +198 -0
- package/src/registry/auth/action-tokens.ts +225 -0
- package/src/registry/auth/crypto.ts +13 -0
- package/src/registry/auth/database.ts +15 -0
- package/src/registry/auth/device-authorizations.ts +223 -0
- package/src/registry/auth/gravatar.ts +6 -0
- package/src/registry/auth/index.ts +89 -0
- package/src/registry/auth/installation.ts +117 -0
- package/src/registry/auth/password.ts +46 -0
- package/src/registry/auth/rate-limits.ts +84 -0
- package/src/registry/auth/types.ts +34 -0
- package/src/registry/auth/user-record.ts +25 -0
- package/src/registry/auth/users.ts +145 -0
- package/src/registry/auth/validation.ts +24 -0
- package/src/registry/checkout/assets.ts +4 -2
- package/src/registry/checkout/index.ts +182 -30
- package/src/registry/checkout/tokens.ts +4 -2
- package/src/registry/client.ts +7 -1
- package/src/registry/connection.ts +23 -0
- package/src/registry/db/client.ts +12 -12
- package/src/registry/db/{adapter.ts → driver.ts} +24 -21
- package/src/registry/db/index.ts +16 -4
- package/src/registry/db/migrate.ts +5 -5
- package/src/registry/db/schema.ts +174 -1
- package/src/registry/publish/assets.ts +1 -1
- package/src/registry/publish/errors.ts +3 -3
- package/src/registry/publish/index.ts +108 -10
- package/src/registry/publish/tokens.ts +1 -1
- package/src/registry/transfer.ts +14 -0
- package/src/types/config.ts +11 -4
- package/templates/default/README.md.tpl +58 -1
- package/templates/default/gitignore.tpl +19 -3
- package/templates/default/handoff.config.js.tpl +13 -0
- package/templates/default/handoff.config.ts.tpl +13 -0
- package/templates/default/handoff.config.with-examples.js.tpl +13 -0
- package/templates/default/handoff.config.with-examples.ts.tpl +13 -0
- package/templates/default/package.json.tpl +2 -1
- package/templates/default/vercel.json.tpl +4 -0
- package/dist/registry/db/adapter.d.ts +0 -43
|
@@ -15,12 +15,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const __1 = __importDefault(require("../../"));
|
|
16
16
|
const logger_1 = require("../../utils/logger");
|
|
17
17
|
const utils_1 = require("../utils");
|
|
18
|
-
/** Entity kinds checkout-able from a connected workspace. */
|
|
19
|
-
const ENTITY_KINDS = ['component', 'pattern', 'page', 'tokens', 'assets'];
|
|
20
18
|
/**
|
|
21
|
-
* `handoff-app checkout <
|
|
22
|
-
* into this workspace
|
|
23
|
-
*
|
|
19
|
+
* `handoff-app checkout <components|patterns|pages> [id]` pulls entities from the connected registry
|
|
20
|
+
* into this workspace, writing their source files in standard authoring form and synthesizing local
|
|
21
|
+
* declarations. Pass an `id` to pull that one entity, or omit it to pull every published entity of
|
|
22
|
+
* that kind.
|
|
24
23
|
*
|
|
25
24
|
* `handoff-app checkout tokens [setId]` — pull every published token set (or only the named set) into
|
|
26
25
|
* this workspace: reconstruct `tokens.json` and restore the generated token files.
|
|
@@ -33,16 +32,16 @@ const ENTITY_KINDS = ['component', 'pattern', 'page', 'tokens', 'assets'];
|
|
|
33
32
|
*/
|
|
34
33
|
const command = {
|
|
35
34
|
command: 'checkout <type> [id]',
|
|
36
|
-
describe: 'Pull
|
|
35
|
+
describe: 'Pull components, patterns, pages, design tokens, or assets from the connected registry into this workspace',
|
|
37
36
|
builder: (yargs) => {
|
|
38
37
|
return (0, utils_1.getSharedOptions)(yargs)
|
|
39
38
|
.positional('type', {
|
|
40
39
|
describe: 'The kind of entity to checkout',
|
|
41
|
-
choices:
|
|
40
|
+
choices: utils_1.REGISTRY_ENTITY_KINDS,
|
|
42
41
|
type: 'string',
|
|
43
42
|
})
|
|
44
43
|
.positional('id', {
|
|
45
|
-
describe: 'The stable id of the entity (component/pattern/page id, token set id, or asset collection);
|
|
44
|
+
describe: 'The stable id of the entity (component/pattern/page id, token set id, or asset collection); omit to checkout all of that kind',
|
|
46
45
|
type: 'string',
|
|
47
46
|
});
|
|
48
47
|
},
|
|
@@ -57,10 +56,7 @@ const command = {
|
|
|
57
56
|
yield handoff.checkoutAssets(args.id);
|
|
58
57
|
return;
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
throw new Error(`An id is required to checkout a ${args.type} (e.g. "handoff-app checkout ${args.type} <id>").`);
|
|
62
|
-
}
|
|
63
|
-
yield handoff.checkout(args.type, args.id);
|
|
59
|
+
yield handoff.checkout(utils_1.ENTITY_WIRE_KIND[args.type], args.id);
|
|
64
60
|
}
|
|
65
61
|
catch (error) {
|
|
66
62
|
logger_1.Logger.error(error instanceof Error ? error.message : String(error));
|
package/dist/commands/index.js
CHANGED
|
@@ -15,6 +15,8 @@ const pages_1 = __importDefault(require("./eject/pages"));
|
|
|
15
15
|
const theme_1 = __importDefault(require("./eject/theme"));
|
|
16
16
|
const fetch_1 = __importDefault(require("./fetch"));
|
|
17
17
|
const init_1 = __importDefault(require("./init"));
|
|
18
|
+
const login_1 = __importDefault(require("./login"));
|
|
19
|
+
const logout_1 = __importDefault(require("./logout"));
|
|
18
20
|
const component_1 = __importDefault(require("./make/component"));
|
|
19
21
|
const page_1 = __importDefault(require("./make/page"));
|
|
20
22
|
const template_1 = __importDefault(require("./make/template"));
|
|
@@ -34,6 +36,8 @@ exports.commands = [
|
|
|
34
36
|
theme_1.default,
|
|
35
37
|
fetch_1.default,
|
|
36
38
|
init_1.default,
|
|
39
|
+
login_1.default,
|
|
40
|
+
logout_1.default,
|
|
37
41
|
page_1.default,
|
|
38
42
|
component_1.default,
|
|
39
43
|
template_1.default,
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const __1 = __importDefault(require("../../"));
|
|
16
|
+
const device_1 = require("../../cli/auth/device");
|
|
17
|
+
const store_1 = require("../../cli/auth/store");
|
|
18
|
+
const connection_1 = require("../../registry/connection");
|
|
19
|
+
const logger_1 = require("../../utils/logger");
|
|
20
|
+
const utils_1 = require("../utils");
|
|
21
|
+
const command = {
|
|
22
|
+
command: 'login',
|
|
23
|
+
describe: 'Sign in to a registry using browser device authorization',
|
|
24
|
+
builder: (yargs) => (0, utils_1.getSharedOptions)(yargs)
|
|
25
|
+
.option('url', {
|
|
26
|
+
type: 'string',
|
|
27
|
+
describe: 'Registry URL, including its base path when configured',
|
|
28
|
+
})
|
|
29
|
+
.option('browser', {
|
|
30
|
+
type: 'boolean',
|
|
31
|
+
default: true,
|
|
32
|
+
describe: 'Open the approval URL in the default browser (disable with --no-browser)',
|
|
33
|
+
}),
|
|
34
|
+
handler: (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
var _a;
|
|
36
|
+
const handoff = new __1.default(args.debug, args.force);
|
|
37
|
+
try {
|
|
38
|
+
const configured = (0, connection_1.resolveRegistryConnection)(handoff.config);
|
|
39
|
+
const remoteUrl = ((_a = args.url) === null || _a === void 0 ? void 0 : _a.trim()) || configured.url;
|
|
40
|
+
if (!remoteUrl) {
|
|
41
|
+
throw new Error(`Pass --url <registry-url>, configure runtime.registryConnection.url, or set "${configured.urlEnv}".`);
|
|
42
|
+
}
|
|
43
|
+
yield (0, device_1.loginWithDevice)(handoff.workingPath, remoteUrl, { openBrowser: args.browser !== false });
|
|
44
|
+
logger_1.Logger.success(`Logged in. Credentials saved to ${(0, store_1.cliAuthFilePath)(handoff.workingPath)}.`);
|
|
45
|
+
logger_1.Logger.info('Publish and checkout commands will use this login for the matching registry URL.');
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger_1.Logger.error(error instanceof Error ? error.message : String(error));
|
|
49
|
+
process.exitCode = 1;
|
|
50
|
+
}
|
|
51
|
+
}),
|
|
52
|
+
};
|
|
53
|
+
exports.default = command;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const __1 = __importDefault(require("../../"));
|
|
16
|
+
const device_1 = require("../../cli/auth/device");
|
|
17
|
+
const store_1 = require("../../cli/auth/store");
|
|
18
|
+
const logger_1 = require("../../utils/logger");
|
|
19
|
+
const utils_1 = require("../utils");
|
|
20
|
+
const command = {
|
|
21
|
+
command: 'logout',
|
|
22
|
+
describe: 'Revoke and remove saved registry credentials',
|
|
23
|
+
builder: (yargs) => (0, utils_1.getSharedOptions)(yargs).option('url', {
|
|
24
|
+
type: 'string',
|
|
25
|
+
describe: 'Revoke credentials only when they belong to this exact registry URL',
|
|
26
|
+
}),
|
|
27
|
+
handler: (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
const handoff = new __1.default(args.debug, args.force);
|
|
29
|
+
const auth = yield (0, store_1.readCliAuth)(handoff.workingPath);
|
|
30
|
+
if (args.url && auth && !(0, store_1.cliAuthMatchesRegistry)(auth, args.url)) {
|
|
31
|
+
logger_1.Logger.error(`The saved login belongs to ${auth.remoteUrl}, not ${(0, store_1.normalizeRegistryUrl)(args.url)}. No credentials were changed.`);
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (auth) {
|
|
36
|
+
try {
|
|
37
|
+
yield (0, device_1.revokeAccessToken)(auth);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
logger_1.Logger.warn(`Could not revoke the registry token remotely (${error instanceof Error ? error.message : String(error)}). ` +
|
|
41
|
+
'It will still be removed from this workspace.');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
yield (0, store_1.clearCliAuth)(handoff.workingPath);
|
|
46
|
+
logger_1.Logger.success(`Logged out. Removed ${(0, store_1.cliAuthFilePath)(handoff.workingPath)}.`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
logger_1.Logger.error(`Could not remove saved credentials: ${error instanceof Error ? error.message : String(error)}`);
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
}
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
exports.default = command;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { CommandModule } from 'yargs';
|
|
2
2
|
import { SharedArgs } from '../types';
|
|
3
|
-
|
|
4
|
-
declare const ENTITY_KINDS: readonly ["component", "pattern", "page", "tokens", "assets"];
|
|
3
|
+
import { RegistryEntityKind } from '../utils';
|
|
5
4
|
export interface PublishArgs extends SharedArgs {
|
|
6
|
-
type:
|
|
5
|
+
type: RegistryEntityKind;
|
|
7
6
|
id?: string;
|
|
8
7
|
}
|
|
9
8
|
/**
|
|
10
|
-
* `handoff-app publish <
|
|
11
|
-
*
|
|
9
|
+
* `handoff-app publish <components|patterns|pages> [id]` runs a fresh local build and uploads to the
|
|
10
|
+
* connected registry. Pass an `id` to build and upload that one entity, or omit it to build the kind
|
|
11
|
+
* once and upload every declared entity, skipping any whose content already matches the registry
|
|
12
|
+
* (pass `--force` to re-upload everything).
|
|
12
13
|
*
|
|
13
14
|
* `handoff-app publish tokens [setId]` — fresh token build + upload of every logical token set, or
|
|
14
15
|
* only the named set (`foundation/colors`, `component/button`).
|
|
@@ -15,11 +15,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const __1 = __importDefault(require("../../"));
|
|
16
16
|
const logger_1 = require("../../utils/logger");
|
|
17
17
|
const utils_1 = require("../utils");
|
|
18
|
-
/** Entity kinds publishable from a connected workspace. */
|
|
19
|
-
const ENTITY_KINDS = ['component', 'pattern', 'page', 'tokens', 'assets'];
|
|
20
18
|
/**
|
|
21
|
-
* `handoff-app publish <
|
|
22
|
-
*
|
|
19
|
+
* `handoff-app publish <components|patterns|pages> [id]` runs a fresh local build and uploads to the
|
|
20
|
+
* connected registry. Pass an `id` to build and upload that one entity, or omit it to build the kind
|
|
21
|
+
* once and upload every declared entity, skipping any whose content already matches the registry
|
|
22
|
+
* (pass `--force` to re-upload everything).
|
|
23
23
|
*
|
|
24
24
|
* `handoff-app publish tokens [setId]` — fresh token build + upload of every logical token set, or
|
|
25
25
|
* only the named set (`foundation/colors`, `component/button`).
|
|
@@ -30,16 +30,16 @@ const ENTITY_KINDS = ['component', 'pattern', 'page', 'tokens', 'assets'];
|
|
|
30
30
|
*/
|
|
31
31
|
const command = {
|
|
32
32
|
command: 'publish <type> [id]',
|
|
33
|
-
describe: 'Build and publish
|
|
33
|
+
describe: 'Build and publish components, patterns, pages, design tokens, or assets to the connected registry',
|
|
34
34
|
builder: (yargs) => {
|
|
35
35
|
return (0, utils_1.getSharedOptions)(yargs)
|
|
36
36
|
.positional('type', {
|
|
37
37
|
describe: 'The kind of entity to publish',
|
|
38
|
-
choices:
|
|
38
|
+
choices: utils_1.REGISTRY_ENTITY_KINDS,
|
|
39
39
|
type: 'string',
|
|
40
40
|
})
|
|
41
41
|
.positional('id', {
|
|
42
|
-
describe: 'The stable id of the entity (component/pattern/page id, token set id, or asset collection);
|
|
42
|
+
describe: 'The stable id of the entity (component/pattern/page id, token set id, or asset collection); omit to publish all of that kind',
|
|
43
43
|
type: 'string',
|
|
44
44
|
});
|
|
45
45
|
},
|
|
@@ -54,10 +54,7 @@ const command = {
|
|
|
54
54
|
yield handoff.publishAssets(args.id);
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
throw new Error(`An id is required to publish a ${args.type} (e.g. "handoff-app publish ${args.type} <id>").`);
|
|
59
|
-
}
|
|
60
|
-
yield handoff.publish(args.type, args.id);
|
|
57
|
+
yield handoff.publish(utils_1.ENTITY_WIRE_KIND[args.type], args.id);
|
|
61
58
|
}
|
|
62
59
|
catch (error) {
|
|
63
60
|
logger_1.Logger.error(error instanceof Error ? error.message : String(error));
|
package/dist/commands/utils.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { Argv } from 'yargs';
|
|
2
|
+
import type { TransferEntityKind } from '../registry/transfer';
|
|
3
|
+
/** Plural entity kinds accepted by the `publish`/`checkout` commands. */
|
|
4
|
+
export declare const REGISTRY_ENTITY_KINDS: readonly ["components", "patterns", "pages", "tokens", "assets"];
|
|
5
|
+
export type RegistryEntityKind = (typeof REGISTRY_ENTITY_KINDS)[number];
|
|
6
|
+
/** Map the plural CLI kind to the singular wire kind used by entity publish/checkout. */
|
|
7
|
+
export declare const ENTITY_WIRE_KIND: Record<'components' | 'patterns' | 'pages', TransferEntityKind>;
|
|
2
8
|
export declare const getSharedOptions: (yargs: Argv) => Argv<import("yargs").Omit<{}, "debug" | "config" | "force"> & import("yargs").InferredOptionTypes<{
|
|
3
9
|
config: {
|
|
4
10
|
alias: string;
|
package/dist/commands/utils.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSharedOptions = void 0;
|
|
3
|
+
exports.getSharedOptions = exports.ENTITY_WIRE_KIND = exports.REGISTRY_ENTITY_KINDS = void 0;
|
|
4
|
+
/** Plural entity kinds accepted by the `publish`/`checkout` commands. */
|
|
5
|
+
exports.REGISTRY_ENTITY_KINDS = ['components', 'patterns', 'pages', 'tokens', 'assets'];
|
|
6
|
+
/** Map the plural CLI kind to the singular wire kind used by entity publish/checkout. */
|
|
7
|
+
exports.ENTITY_WIRE_KIND = {
|
|
8
|
+
components: 'component',
|
|
9
|
+
patterns: 'pattern',
|
|
10
|
+
pages: 'page',
|
|
11
|
+
};
|
|
4
12
|
const getSharedOptions = (yargs) => {
|
|
5
13
|
return yargs.options({
|
|
6
14
|
config: {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registering directory-list entries (`entries.components` / `entries.patterns`) in the handoff
|
|
3
|
+
* config. Both scaffolding new component stubs and checking entities out of a registry need a
|
|
4
|
+
* freshly-written entity to be discoverable by the workspace build, so both have to handle every
|
|
5
|
+
* way a path can be declared:
|
|
6
|
+
*
|
|
7
|
+
* - a collection directory (e.g. `"components"`) whose subdirectories are entities: a new sibling
|
|
8
|
+
* is auto-discovered at runtime, so nothing needs writing to the config;
|
|
9
|
+
* - an individual entity directory (e.g. `"components/button"`): the entity stays invisible until
|
|
10
|
+
* its own path is added to the list.
|
|
11
|
+
*
|
|
12
|
+
* {@link isEntryCovered} answers "does this already load?" by reusing the runtime expansion
|
|
13
|
+
* ({@link getComponentsForPath}); {@link writeEntries} appends the paths that don't, across the
|
|
14
|
+
* `.json`, `.ts`, `.js`, and `.cjs` config formats.
|
|
15
|
+
*/
|
|
16
|
+
import { Config } from '../types/config';
|
|
17
|
+
/** The `entries` keys whose values are declared as a list of directory paths. */
|
|
18
|
+
export type EntryKind = 'components' | 'patterns';
|
|
19
|
+
/** Minimal handoff shape needed here; avoids importing the full Handoff class (circular dep). */
|
|
20
|
+
interface ConfigContext {
|
|
21
|
+
config?: Config;
|
|
22
|
+
workingPath: string;
|
|
23
|
+
}
|
|
24
|
+
/** Outcome of {@link writeEntries}: `added` on success, `unsupported` when the config couldn't be edited. */
|
|
25
|
+
export interface WriteEntriesResult {
|
|
26
|
+
status: 'added' | 'unsupported';
|
|
27
|
+
/** The config file written (or that would need editing); null only when none exists and creation failed. */
|
|
28
|
+
configPath: string | null;
|
|
29
|
+
/** Workspace-relative POSIX paths written into the config. */
|
|
30
|
+
added: string[];
|
|
31
|
+
/** Workspace-relative POSIX paths the caller must add manually (`status: 'unsupported'`). */
|
|
32
|
+
pending: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* True when `targetDir` already loads through an existing `entries[kind]` declaration: listed
|
|
36
|
+
* directly, or sitting under a declared collection directory that runtime discovery expands.
|
|
37
|
+
* Reuses the same expansion the runtime uses, so every declaration style is covered.
|
|
38
|
+
*/
|
|
39
|
+
export declare const isEntryCovered: (handoff: ConfigContext, kind: EntryKind, targetDir: string) => boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Add `targetDirs` to `entries[kind]` in the workspace config so the build discovers them. Callers
|
|
42
|
+
* should first drop already-loading dirs via {@link isEntryCovered}. Paths are stored workspace-
|
|
43
|
+
* relative; a `.json` config is edited losslessly, a code config best-effort. When no config file
|
|
44
|
+
* exists a minimal `handoff.config.json` is created.
|
|
45
|
+
*/
|
|
46
|
+
export declare const writeEntries: (handoff: ConfigContext, kind: EntryKind, targetDirs: string[]) => Promise<WriteEntriesResult>;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Registering directory-list entries (`entries.components` / `entries.patterns`) in the handoff
|
|
4
|
+
* config. Both scaffolding new component stubs and checking entities out of a registry need a
|
|
5
|
+
* freshly-written entity to be discoverable by the workspace build, so both have to handle every
|
|
6
|
+
* way a path can be declared:
|
|
7
|
+
*
|
|
8
|
+
* - a collection directory (e.g. `"components"`) whose subdirectories are entities: a new sibling
|
|
9
|
+
* is auto-discovered at runtime, so nothing needs writing to the config;
|
|
10
|
+
* - an individual entity directory (e.g. `"components/button"`): the entity stays invisible until
|
|
11
|
+
* its own path is added to the list.
|
|
12
|
+
*
|
|
13
|
+
* {@link isEntryCovered} answers "does this already load?" by reusing the runtime expansion
|
|
14
|
+
* ({@link getComponentsForPath}); {@link writeEntries} appends the paths that don't, across the
|
|
15
|
+
* `.json`, `.ts`, `.js`, and `.cjs` config formats.
|
|
16
|
+
*/
|
|
17
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.writeEntries = exports.isEntryCovered = void 0;
|
|
31
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
32
|
+
const path_1 = __importDefault(require("path"));
|
|
33
|
+
const path_2 = require("../utils/path");
|
|
34
|
+
const runtime_1 = require("./runtime");
|
|
35
|
+
/** Config files in precedence order; the first that exists is the one we mutate. */
|
|
36
|
+
const CONFIG_FILES = ['handoff.config.ts', 'handoff.config.js', 'handoff.config.cjs', 'handoff.config.json'];
|
|
37
|
+
/** Workspace-relative, POSIX-separated path used as a config entry value. */
|
|
38
|
+
const toEntryPath = (handoff, targetDir) => path_1.default.relative(handoff.workingPath, targetDir).split(path_1.default.sep).join('/');
|
|
39
|
+
/**
|
|
40
|
+
* True when `targetDir` already loads through an existing `entries[kind]` declaration: listed
|
|
41
|
+
* directly, or sitting under a declared collection directory that runtime discovery expands.
|
|
42
|
+
* Reuses the same expansion the runtime uses, so every declaration style is covered.
|
|
43
|
+
*/
|
|
44
|
+
const isEntryCovered = (handoff, kind, targetDir) => {
|
|
45
|
+
var _a, _b;
|
|
46
|
+
const configured = (_b = (_a = handoff.config) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b[kind];
|
|
47
|
+
if (!(configured === null || configured === void 0 ? void 0 : configured.length)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return configured
|
|
51
|
+
.flatMap((entry) => (0, runtime_1.getComponentsForPath)(path_1.default.resolve(handoff.workingPath, entry)))
|
|
52
|
+
.some((dir) => (0, path_2.arePathsEqual)(dir, targetDir));
|
|
53
|
+
};
|
|
54
|
+
exports.isEntryCovered = isEntryCovered;
|
|
55
|
+
/** Format an entry array as source, matching the surrounding indentation of a code config. */
|
|
56
|
+
const formatEntryArray = (paths, indent) => {
|
|
57
|
+
if (paths.length === 0)
|
|
58
|
+
return '[]';
|
|
59
|
+
if (paths.length === 1)
|
|
60
|
+
return `['${paths[0]}']`;
|
|
61
|
+
return `[\n${paths.map((entry) => `${indent}'${entry}',`).join('\n')}\n${indent.slice(2)}]`;
|
|
62
|
+
};
|
|
63
|
+
/** Append entry paths to a structured `.json` config (lossless read/modify/write). */
|
|
64
|
+
const addToJsonConfig = (configPath, kind, relPaths) => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
+
var _a;
|
|
66
|
+
try {
|
|
67
|
+
const config = yield fs_extra_1.default.readJSON(configPath);
|
|
68
|
+
config.entries = (_a = config.entries) !== null && _a !== void 0 ? _a : {};
|
|
69
|
+
const existing = Array.isArray(config.entries[kind]) ? config.entries[kind] : [];
|
|
70
|
+
const existingSet = new Set(existing);
|
|
71
|
+
for (const relPath of relPaths) {
|
|
72
|
+
if (!existingSet.has(relPath))
|
|
73
|
+
existing.push(relPath);
|
|
74
|
+
}
|
|
75
|
+
config.entries[kind] = existing;
|
|
76
|
+
yield fs_extra_1.default.writeJSON(configPath, config, { spaces: 2 });
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
catch (_b) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Best-effort splice of entry paths into an executable `.ts` / `.js` / `.cjs` config. These are
|
|
85
|
+
* modules, not data, so there's no lossless structured write; if a computed or spread `entries`
|
|
86
|
+
* array can't be edited textually, the caller falls back to printing the paths for the user to add.
|
|
87
|
+
*/
|
|
88
|
+
const addToCodeConfig = (configPath, kind, relPaths) => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
+
try {
|
|
90
|
+
let content = yield fs_extra_1.default.readFile(configPath, 'utf8');
|
|
91
|
+
const arrayBlock = formatEntryArray(relPaths, ' ');
|
|
92
|
+
// 1) An `entries: { ... <kind>: [ ... ] }` array already exists, so merge into it.
|
|
93
|
+
const hasKeyArray = new RegExp(`entries\\s*:\\s*\\{[\\s\\S]*?${kind}\\s*:`).test(content);
|
|
94
|
+
const arrayRegex = new RegExp(`(${kind}\\s*:\\s*\\[)([^\\]]*)(\\])`);
|
|
95
|
+
const match = hasKeyArray ? content.match(arrayRegex) : null;
|
|
96
|
+
if (match) {
|
|
97
|
+
const existing = match[2]
|
|
98
|
+
.split(',')
|
|
99
|
+
.map((s) => s.trim().replace(/['"]/g, ''))
|
|
100
|
+
.filter(Boolean);
|
|
101
|
+
const existingSet = new Set(existing);
|
|
102
|
+
const toAdd = relPaths.filter((relPath) => !existingSet.has(relPath));
|
|
103
|
+
if (toAdd.length > 0) {
|
|
104
|
+
const indentMatch = content.match(new RegExp(`${kind}\\s*:\\s*\\[\\s*\\n(\\s*)`));
|
|
105
|
+
const indent = indentMatch ? indentMatch[1] : ' ';
|
|
106
|
+
content = content.replace(arrayRegex, `${kind}: ${formatEntryArray([...existing, ...toAdd], indent)}`);
|
|
107
|
+
yield fs_extra_1.default.writeFile(configPath, content, 'utf8');
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
// 2) An `entries` object exists but not this key, so add the key.
|
|
112
|
+
if (/entries\s*:\s*\{/.test(content)) {
|
|
113
|
+
content = content.replace(/(entries\s*:\s*\{)/, `$1\n ${kind}: ${arrayBlock},`);
|
|
114
|
+
yield fs_extra_1.default.writeFile(configPath, content, 'utf8');
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
// 3) No `entries` object, so insert one into the exported config object.
|
|
118
|
+
const entriesBlock = ` entries: {\n ${kind}: ${arrayBlock},\n },\n`;
|
|
119
|
+
for (const anchor of [/module\.exports\s*=\s*\{/, /export\s+default\s+\{/, /defineConfig\s*\(\s*\{/]) {
|
|
120
|
+
if (anchor.test(content)) {
|
|
121
|
+
content = content.replace(anchor, (matched) => `${matched}\n${entriesBlock}`);
|
|
122
|
+
yield fs_extra_1.default.writeFile(configPath, content, 'utf8');
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
catch (_a) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
/**
|
|
133
|
+
* Add `targetDirs` to `entries[kind]` in the workspace config so the build discovers them. Callers
|
|
134
|
+
* should first drop already-loading dirs via {@link isEntryCovered}. Paths are stored workspace-
|
|
135
|
+
* relative; a `.json` config is edited losslessly, a code config best-effort. When no config file
|
|
136
|
+
* exists a minimal `handoff.config.json` is created.
|
|
137
|
+
*/
|
|
138
|
+
const writeEntries = (handoff, kind, targetDirs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
139
|
+
const relPaths = [...new Set(targetDirs.map((dir) => toEntryPath(handoff, dir)))];
|
|
140
|
+
const configFile = CONFIG_FILES.find((file) => fs_extra_1.default.existsSync(path_1.default.resolve(handoff.workingPath, file)));
|
|
141
|
+
const configPath = configFile ? path_1.default.resolve(handoff.workingPath, configFile) : null;
|
|
142
|
+
if (relPaths.length === 0) {
|
|
143
|
+
return { status: 'added', configPath, added: [], pending: [] };
|
|
144
|
+
}
|
|
145
|
+
if (!configPath) {
|
|
146
|
+
const newConfigPath = path_1.default.resolve(handoff.workingPath, 'handoff.config.json');
|
|
147
|
+
try {
|
|
148
|
+
yield fs_extra_1.default.writeJSON(newConfigPath, { entries: { [kind]: relPaths } }, { spaces: 2 });
|
|
149
|
+
return { status: 'added', configPath: newConfigPath, added: relPaths, pending: [] };
|
|
150
|
+
}
|
|
151
|
+
catch (_a) {
|
|
152
|
+
return { status: 'unsupported', configPath: null, added: [], pending: relPaths };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const ok = configPath.endsWith('.json')
|
|
156
|
+
? yield addToJsonConfig(configPath, kind, relPaths)
|
|
157
|
+
: yield addToCodeConfig(configPath, kind, relPaths);
|
|
158
|
+
return ok
|
|
159
|
+
? { status: 'added', configPath, added: relPaths, pending: [] }
|
|
160
|
+
: { status: 'unsupported', configPath, added: [], pending: relPaths };
|
|
161
|
+
});
|
|
162
|
+
exports.writeEntries = writeEntries;
|
package/dist/config/index.d.ts
CHANGED
|
@@ -4,3 +4,5 @@ export { initConfig, initConfigWithMetadata } from './loader';
|
|
|
4
4
|
export { defineConfig } from './helpers';
|
|
5
5
|
export { initRuntimeConfig } from './runtime';
|
|
6
6
|
export { validateConfig } from './validator';
|
|
7
|
+
export { isEntryCovered, writeEntries } from './entries';
|
|
8
|
+
export type { EntryKind, WriteEntriesResult } from './entries';
|
package/dist/config/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateConfig = exports.initRuntimeConfig = exports.defineConfig = exports.initConfigWithMetadata = exports.initConfig = exports.getClientConfig = exports.defaultConfig = void 0;
|
|
3
|
+
exports.writeEntries = exports.isEntryCovered = exports.validateConfig = exports.initRuntimeConfig = exports.defineConfig = exports.initConfigWithMetadata = exports.initConfig = exports.getClientConfig = exports.defaultConfig = void 0;
|
|
4
4
|
// Config defaults and client config
|
|
5
5
|
var defaults_1 = require("./defaults");
|
|
6
6
|
Object.defineProperty(exports, "defaultConfig", { enumerable: true, get: function () { return defaults_1.defaultConfig; } });
|
|
@@ -18,3 +18,7 @@ Object.defineProperty(exports, "initRuntimeConfig", { enumerable: true, get: fun
|
|
|
18
18
|
// Config validation
|
|
19
19
|
var validator_1 = require("./validator");
|
|
20
20
|
Object.defineProperty(exports, "validateConfig", { enumerable: true, get: function () { return validator_1.validateConfig; } });
|
|
21
|
+
// Registering directory-list entries (components/patterns)
|
|
22
|
+
var entries_1 = require("./entries");
|
|
23
|
+
Object.defineProperty(exports, "isEntryCovered", { enumerable: true, get: function () { return entries_1.isEntryCovered; } });
|
|
24
|
+
Object.defineProperty(exports, "writeEntries", { enumerable: true, get: function () { return entries_1.writeEntries; } });
|
package/dist/config/runtime.d.ts
CHANGED
|
@@ -21,17 +21,17 @@ export declare const resolveComponentDeclaration: (componentDir: string, compone
|
|
|
21
21
|
*/
|
|
22
22
|
export declare const initRuntimeConfig: (handoff: HandoffContext) => [runtimeConfig: RuntimeConfig, configs: string[], configFileIndex: Map<string, ConfigFileEntry>];
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
*
|
|
24
|
+
* True when `searchPath` is itself a single component directory: it holds a declaration file named
|
|
25
|
+
* after the directory (`{dirname}.handoff.*`, or a legacy `{dirname}.{json,js,cjs}`). This is what
|
|
26
|
+
* separates a declared component from a collection directory.
|
|
27
|
+
*/
|
|
28
|
+
export declare const isComponentDirectory: (searchPath: string) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Returns the component directories for a given path. If `searchPath` is itself a component
|
|
31
|
+
* directory it's returned as-is; otherwise each subdirectory is treated as a potential component.
|
|
32
32
|
*
|
|
33
33
|
* @param searchPath - The absolute path to check for components.
|
|
34
|
-
* @returns
|
|
34
|
+
* @returns Paths to the component directories.
|
|
35
35
|
*/
|
|
36
36
|
export declare const getComponentsForPath: (searchPath: string) => string[];
|
|
37
37
|
/**
|
package/dist/config/runtime.js
CHANGED
|
@@ -3,7 +3,7 @@ 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.toLowerCaseKeysAndValues = exports.getItemsForPath = exports.getComponentsForPath = exports.initRuntimeConfig = exports.resolveComponentDeclaration = void 0;
|
|
6
|
+
exports.toLowerCaseKeysAndValues = exports.getItemsForPath = exports.getComponentsForPath = exports.isComponentDirectory = exports.initRuntimeConfig = exports.resolveComponentDeclaration = void 0;
|
|
7
7
|
const esbuild_1 = __importDefault(require("esbuild"));
|
|
8
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
9
|
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
@@ -283,24 +283,24 @@ const collectPageMarkdownPaths = (rootDir, relativeParts = []) => {
|
|
|
283
283
|
return results;
|
|
284
284
|
};
|
|
285
285
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
*
|
|
286
|
+
* True when `searchPath` is itself a single component directory: it holds a declaration file named
|
|
287
|
+
* after the directory (`{dirname}.handoff.*`, or a legacy `{dirname}.{json,js,cjs}`). This is what
|
|
288
|
+
* separates a declared component from a collection directory.
|
|
289
|
+
*/
|
|
290
|
+
const isComponentDirectory = (searchPath) => !!(0, exports.resolveComponentDeclaration)(searchPath, path_1.default.basename(searchPath));
|
|
291
|
+
exports.isComponentDirectory = isComponentDirectory;
|
|
292
|
+
/**
|
|
293
|
+
* Returns the component directories for a given path. If `searchPath` is itself a component
|
|
294
|
+
* directory it's returned as-is; otherwise each subdirectory is treated as a potential component.
|
|
294
295
|
*
|
|
295
296
|
* @param searchPath - The absolute path to check for components.
|
|
296
|
-
* @returns
|
|
297
|
+
* @returns Paths to the component directories.
|
|
297
298
|
*/
|
|
298
299
|
const getComponentsForPath = (searchPath) => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (
|
|
303
|
-
// This directory is a single component
|
|
300
|
+
if ((0, exports.isComponentDirectory)(searchPath)) {
|
|
301
|
+
return [searchPath];
|
|
302
|
+
}
|
|
303
|
+
if (!fs_extra_1.default.existsSync(searchPath)) {
|
|
304
304
|
return [searchPath];
|
|
305
305
|
}
|
|
306
306
|
// Otherwise, treat each subdirectory as a potential component
|