handoff-app 2.0.0-3 → 2.0.0-5
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/AGENTS.md +7 -0
- package/CLAUDE.md +7 -0
- package/README.md +302 -378
- package/dist/app-builder/build.js +2 -2
- package/dist/app-builder/nav-shell.js +8 -15
- package/dist/app-builder/vercel-output.js +4 -4
- package/dist/cli/make.js +2 -2
- package/dist/cli.js +39 -7
- package/dist/commands/build/app.js +1 -5
- package/dist/commands/build/components.js +1 -5
- package/dist/commands/build/index.js +1 -5
- package/dist/commands/checkout/index.d.ts +15 -12
- package/dist/commands/checkout/index.js +15 -54
- package/dist/commands/compat/deprecations.d.ts +46 -0
- package/dist/commands/compat/deprecations.js +62 -0
- package/dist/commands/compat/push-args.d.ts +48 -0
- package/dist/commands/compat/push-args.js +73 -0
- package/dist/commands/db/migrate.js +1 -5
- package/dist/commands/dev/index.js +1 -5
- package/dist/commands/eject/config.js +1 -5
- package/dist/commands/eject/pages.js +1 -5
- package/dist/commands/eject/theme.js +1 -5
- package/dist/commands/fetch/index.js +1 -5
- package/dist/commands/index.js +4 -0
- package/dist/commands/login/index.js +1 -5
- package/dist/commands/logout/index.js +1 -5
- package/dist/commands/make/component.js +1 -5
- package/dist/commands/make/page.js +3 -7
- package/dist/commands/make/template.js +1 -5
- package/dist/commands/publish/index.d.ts +18 -12
- package/dist/commands/publish/index.js +18 -54
- package/dist/commands/pull/index.d.ts +13 -0
- package/dist/commands/pull/index.js +20 -0
- package/dist/commands/push/index.d.ts +23 -0
- package/dist/commands/push/index.js +58 -0
- package/dist/commands/scaffold/index.js +1 -5
- package/dist/commands/start/index.js +1 -5
- package/dist/commands/types.d.ts +10 -0
- package/dist/commands/utils.d.ts +74 -6
- package/dist/commands/utils.js +89 -10
- package/dist/commands/validate/components.js +1 -5
- package/dist/config/index.d.ts +2 -1
- package/dist/config/index.js +2 -1
- package/dist/config/loader.d.ts +19 -6
- package/dist/config/loader.js +43 -13
- package/dist/config/normalizers/page.d.ts +4 -4
- package/dist/config/normalizers/page.js +2 -2
- package/dist/config/runtime.js +9 -25
- package/dist/index.d.ts +69 -22
- package/dist/index.js +148 -35
- package/dist/nav/resolver.js +3 -1
- package/dist/nav/workspace.js +2 -2
- package/dist/registry/auth/access-tokens.d.ts +11 -3
- package/dist/registry/auth/access-tokens.js +29 -3
- package/dist/registry/auth/index.d.ts +4 -3
- package/dist/registry/auth/index.js +10 -2
- package/dist/registry/auth/sync-secret.d.ts +27 -0
- package/dist/registry/auth/sync-secret.js +65 -0
- package/dist/registry/auth/types.d.ts +20 -1
- package/dist/registry/auth/types.js +3 -1
- package/dist/registry/auth/validation.d.ts +11 -0
- package/dist/registry/auth/validation.js +18 -1
- package/dist/registry/checkout/assets.d.ts +1 -1
- package/dist/registry/checkout/assets.js +21 -6
- package/dist/registry/checkout/index.d.ts +8 -1
- package/dist/registry/checkout/index.js +39 -6
- package/dist/registry/checkout/tokens.d.ts +1 -1
- package/dist/registry/checkout/tokens.js +12 -5
- package/dist/registry/connection.d.ts +10 -0
- package/dist/registry/connection.js +52 -7
- package/dist/registry/content-kinds.d.ts +27 -0
- package/dist/registry/content-kinds.js +33 -0
- package/dist/registry/db/client.d.ts +6 -1
- package/dist/registry/db/client.js +16 -3
- package/dist/registry/db/schema.d.ts +37 -3
- package/dist/registry/db/schema.js +9 -7
- package/dist/registry/publish/assets.d.ts +2 -2
- package/dist/registry/publish/assets.js +46 -35
- package/dist/registry/publish/index.d.ts +29 -5
- package/dist/registry/publish/index.js +87 -34
- package/dist/registry/publish/tokens.d.ts +2 -2
- package/dist/registry/publish/tokens.js +30 -24
- package/dist/registry/selection.d.ts +12 -0
- package/dist/registry/selection.js +22 -0
- package/dist/store/registry.d.ts +48 -0
- package/dist/store/registry.js +75 -12
- package/dist/transformers/preview/types.d.ts +2 -2
- package/dist/utils/markdown.d.ts +10 -0
- package/dist/utils/markdown.js +17 -0
- package/dist/utils/menu-shell.js +14 -7
- package/dist/utils/pages.d.ts +22 -0
- package/dist/utils/pages.js +73 -0
- package/dist/utils/path.d.ts +5 -0
- package/dist/utils/path.js +9 -0
- package/docs/api.md +1 -3
- package/docs/cli.md +1 -1
- package/drizzle/0002_add_pages.sql +5 -3
- package/drizzle/meta/0002_snapshot.json +17 -8
- package/drizzle/meta/0003_snapshot.json +17 -8
- package/drizzle/meta/0004_snapshot.json +17 -8
- package/drizzle/meta/0005_snapshot.json +17 -8
- package/package.json +1 -1
- package/src/app/components/util/index.ts +5 -23
- package/src/app/lib/docs-api/backend.ts +11 -0
- package/src/app/lib/docs-api/errors.ts +8 -7
- package/src/app/lib/docs-api/handler.ts +2 -3
- package/src/app/lib/docs-api/index.ts +2 -0
- package/src/app/lib/docs-api/page-discovery.ts +126 -0
- package/src/app/lib/docs-api/page-rendering.ts +17 -0
- package/src/app/lib/docs-api/page-search.ts +191 -0
- package/src/app/lib/docs-api/records.ts +11 -19
- package/src/app/lib/docs-api/registry.ts +90 -11
- package/src/app/lib/docs-api/search.ts +115 -0
- package/src/app/lib/registry-api/allowlist.ts +7 -5
- package/src/app/lib/registry-api/asset-transfer.ts +58 -31
- package/src/app/lib/registry-api/auth.ts +89 -9
- package/src/app/lib/registry-api/entity-routes.ts +17 -7
- package/src/app/lib/registry-api/errors.ts +10 -4
- package/src/app/lib/registry-api/handler.ts +13 -15
- package/src/app/lib/registry-api/meta.ts +4 -0
- package/src/app/lib/registry-api/revalidate.ts +31 -12
- package/src/app/lib/registry-api/store.ts +89 -26
- package/src/app/lib/registry-api/sync-compat.ts +166 -0
- package/src/app/lib/registry-api/token-transfer.ts +44 -12
- package/src/app/lib/registry-api/transfer-batch.ts +116 -0
- package/src/app/lib/registry-api/transfer.ts +62 -35
- package/src/app/lib/registry-api/validation.ts +33 -1
- package/src/app/lib/registry-connection.ts +1 -1
- package/src/app/next.config.mjs +6 -0
- package/src/app/pages/[...slug]/index.tsx +37 -22
- package/src/app/pages/api/account/tokens/index.ts +4 -13
- package/src/app/pages/api/docs/search/pages.json.ts +25 -0
- package/src/app/pages/api/oauth/revoke.ts +14 -7
- package/src/app/pages/api/registry/components/[id]/files/[...filePath].ts +1 -1
- package/src/app/pages/api/registry/components/[id].ts +2 -2
- package/src/app/pages/api/registry/components/index.ts +1 -1
- package/src/app/pages/api/registry/pages/[...id].ts +20 -0
- package/src/app/pages/api/registry/pages/index.ts +19 -0
- package/src/app/pages/api/registry/patterns/[id]/files/[...filePath].ts +1 -1
- package/src/app/pages/api/registry/patterns/[id].ts +2 -2
- package/src/app/pages/api/registry/patterns/index.ts +1 -1
- package/src/app/pages/api/registry/transfer/assets/blobs/have.ts +2 -2
- package/src/app/pages/api/sync/upload.ts +21 -0
- package/src/app/pages/index/index.tsx +14 -0
- package/src/app/pages/index.tsx +30 -5
- package/src/app-builder/build.ts +2 -2
- package/src/app-builder/nav-shell.ts +8 -13
- package/src/app-builder/vercel-output.ts +4 -4
- package/src/cli/make.ts +2 -2
- package/src/cli.ts +31 -7
- package/src/commands/build/app.ts +2 -3
- package/src/commands/build/components.ts +2 -3
- package/src/commands/build/index.ts +2 -3
- package/src/commands/checkout/index.ts +18 -44
- package/src/commands/compat/deprecations.ts +79 -0
- package/src/commands/compat/push-args.ts +106 -0
- package/src/commands/db/migrate.ts +2 -3
- package/src/commands/dev/index.ts +2 -3
- package/src/commands/eject/config.ts +2 -3
- package/src/commands/eject/pages.ts +2 -3
- package/src/commands/eject/theme.ts +2 -3
- package/src/commands/fetch/index.ts +2 -3
- package/src/commands/index.ts +4 -0
- package/src/commands/login/index.ts +2 -3
- package/src/commands/logout/index.ts +2 -3
- package/src/commands/make/component.ts +2 -3
- package/src/commands/make/page.ts +4 -5
- package/src/commands/make/template.ts +2 -3
- package/src/commands/publish/index.ts +21 -44
- package/src/commands/pull/index.ts +32 -0
- package/src/commands/push/index.ts +115 -0
- package/src/commands/scaffold/index.ts +2 -3
- package/src/commands/start/index.ts +2 -3
- package/src/commands/types.ts +11 -1
- package/src/commands/utils.ts +80 -11
- package/src/commands/validate/components.ts +2 -3
- package/src/config/index.ts +2 -1
- package/src/config/loader.ts +57 -12
- package/src/config/normalizers/page.ts +4 -4
- package/src/config/runtime.ts +9 -24
- package/src/index.ts +183 -42
- package/src/nav/resolver.ts +3 -1
- package/src/nav/workspace.ts +2 -2
- package/src/registry/auth/access-tokens.ts +29 -5
- package/src/registry/auth/index.ts +7 -1
- package/src/registry/auth/sync-secret.ts +67 -0
- package/src/registry/auth/types.ts +24 -1
- package/src/registry/auth/validation.ts +18 -0
- package/src/registry/checkout/assets.ts +24 -7
- package/src/registry/checkout/index.ts +41 -5
- package/src/registry/checkout/tokens.ts +12 -6
- package/src/registry/connection.ts +53 -5
- package/src/registry/content-kinds.ts +39 -0
- package/src/registry/db/client.ts +22 -2
- package/src/registry/db/schema.ts +9 -7
- package/src/registry/publish/assets.ts +47 -37
- package/src/registry/publish/index.ts +102 -38
- package/src/registry/publish/tokens.ts +35 -26
- package/src/registry/selection.ts +19 -0
- package/src/store/registry.ts +118 -13
- package/src/transformers/preview/types.ts +2 -2
- package/src/utils/README.md +1 -0
- package/src/utils/markdown.ts +11 -0
- package/src/utils/menu-shell.ts +14 -7
- package/src/utils/pages.ts +52 -0
- package/src/utils/path.ts +15 -6
- package/templates/default/package.json.tpl +4 -0
- package/config/docs/foundations/logos.md +0 -7
- package/src/app/lib/api/redact.ts +0 -46
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Connected-workspace asset publish orchestration.
|
|
3
3
|
*
|
|
4
|
-
* `publish assets [collection]` runs a fresh build (`handoff.fetch()`), discovers the collections, and
|
|
4
|
+
* `publish assets [collection...]` runs a fresh build (`handoff.fetch()`), discovers the collections, and
|
|
5
5
|
* uploads each changed one. A collection is skipped when its deterministic `sourceHash` is unchanged;
|
|
6
6
|
* content transfers blob-by-blob (only hashes the registry lacks, since content-addressed dedup is the
|
|
7
7
|
* per-blob skip-unchanged), and the manifest is finalized atomically only after its blobs exist.
|
|
@@ -13,4 +13,4 @@ import Handoff from '../../index';
|
|
|
13
13
|
* blobs, and finalizes each manifest atomically. Reports published/unchanged/uploaded/failed counts;
|
|
14
14
|
* throws at the end if any collection failed.
|
|
15
15
|
*/
|
|
16
|
-
export declare const publishAssets: (handoff: Handoff,
|
|
16
|
+
export declare const publishAssets: (handoff: Handoff, selection?: string[]) => Promise<void>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Connected-workspace asset publish orchestration.
|
|
4
4
|
*
|
|
5
|
-
* `publish assets [collection]` runs a fresh build (`handoff.fetch()`), discovers the collections, and
|
|
5
|
+
* `publish assets [collection...]` runs a fresh build (`handoff.fetch()`), discovers the collections, and
|
|
6
6
|
* uploads each changed one. A collection is skipped when its deterministic `sourceHash` is unchanged;
|
|
7
7
|
* content transfers blob-by-blob (only hashes the registry lacks, since content-addressed dedup is the
|
|
8
8
|
* per-blob skip-unchanged), and the manifest is finalized atomically only after its blobs exist.
|
|
@@ -20,7 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
20
20
|
exports.publishAssets = void 0;
|
|
21
21
|
const logger_1 = require("../../utils/logger");
|
|
22
22
|
const sets_1 = require("../assets/sets");
|
|
23
|
-
const
|
|
23
|
+
const selection_1 = require("../selection");
|
|
24
24
|
const errors_1 = require("./errors");
|
|
25
25
|
const index_1 = require("./index");
|
|
26
26
|
const publish_build_1 = require("./publish-build");
|
|
@@ -49,22 +49,29 @@ const toManifestEntry = (asset) => {
|
|
|
49
49
|
* blobs, and finalizes each manifest atomically. Reports published/unchanged/uploaded/failed counts;
|
|
50
50
|
* throws at the end if any collection failed.
|
|
51
51
|
*/
|
|
52
|
-
const publishAssets = (handoff,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const publishAssets = (handoff, selection) => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
|
+
var _a;
|
|
54
|
+
const { client, url } = yield (0, index_1.resolveTransport)(handoff);
|
|
55
|
+
const unsupported = (_a = selection === null || selection === void 0 ? void 0 : selection.filter((collection) => !(0, sets_1.isAssetCollection)(collection))) !== null && _a !== void 0 ? _a : [];
|
|
56
|
+
if (unsupported.length > 0) {
|
|
57
|
+
throw new index_1.PublishError(`Unknown asset collection ${unsupported.map((name) => `"${name}"`).join(', ')}. ` +
|
|
58
|
+
`Supported collections: ${sets_1.ASSET_COLLECTIONS.join(', ')}.`);
|
|
56
59
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const targets = collection && (0, sets_1.isAssetCollection)(collection) ? [collection] : available.filter(sets_1.isAssetCollection);
|
|
61
|
-
const client = (0, client_1.createRegistryClient)({ baseUrl: connection.url, accessToken: connection.accessToken });
|
|
62
|
-
let remote = [];
|
|
63
|
-
try {
|
|
64
|
-
remote = yield client.listAssetCollections();
|
|
60
|
+
if (!handoff.skipBuild) {
|
|
61
|
+
logger_1.Logger.info(selection ? `Building assets to publish ${selection.join(', ')}…` : 'Building assets for publish…');
|
|
62
|
+
yield handoff.fetch();
|
|
65
63
|
}
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
const available = (yield handoff.store.assets.listCollections()).filter(sets_1.isAssetCollection);
|
|
65
|
+
const targets = (0, selection_1.selectIds)(available, selection).selected;
|
|
66
|
+
// Without a registry there is nothing to compare against, so a dry run reports every collection.
|
|
67
|
+
let remote = [];
|
|
68
|
+
if (client) {
|
|
69
|
+
try {
|
|
70
|
+
remote = yield client.listAssetCollections();
|
|
71
|
+
}
|
|
72
|
+
catch (_b) {
|
|
73
|
+
logger_1.Logger.info('Could not read current registry asset collections; publishing all selected collections.');
|
|
74
|
+
}
|
|
68
75
|
}
|
|
69
76
|
const remoteHashByCollection = new Map(remote.map((entry) => [entry.collection, entry.sourceHash]));
|
|
70
77
|
let published = 0;
|
|
@@ -90,35 +97,39 @@ const publishAssets = (handoff, collection) => __awaiter(void 0, void 0, void 0,
|
|
|
90
97
|
if (!byHash.has(asset.contentHash))
|
|
91
98
|
byHash.set(asset.contentHash, asset);
|
|
92
99
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
// A dry run has no registry to ask, so every deduped blob counts as one that would upload.
|
|
101
|
+
const missing = client ? yield client.assetBlobHaveCheck(Array.from(byHash.keys())) : Array.from(byHash.keys());
|
|
102
|
+
if (client) {
|
|
103
|
+
for (const hash of missing) {
|
|
104
|
+
const asset = byHash.get(hash);
|
|
105
|
+
if (!asset)
|
|
106
|
+
continue;
|
|
107
|
+
const content = yield handoff.store.assets.getAssetContent(col, asset.path);
|
|
108
|
+
if (!(content === null || content === void 0 ? void 0 : content.body)) {
|
|
109
|
+
throw new Error(`Could not read bytes for asset "${asset.path}" in collection "${col}".`);
|
|
110
|
+
}
|
|
111
|
+
yield client.uploadAssetBlob(hash, content.contentType, content.body);
|
|
112
|
+
uploaded += 1;
|
|
101
113
|
}
|
|
102
|
-
|
|
103
|
-
|
|
114
|
+
const pkg = {
|
|
115
|
+
collection: col,
|
|
116
|
+
build: (0, publish_build_1.createCurrentBuild)({ sourceHash }),
|
|
117
|
+
assets: manifest.map(toManifestEntry),
|
|
118
|
+
};
|
|
119
|
+
yield client.publishAssetManifest(pkg);
|
|
104
120
|
}
|
|
105
|
-
const pkg = {
|
|
106
|
-
collection: col,
|
|
107
|
-
build: (0, publish_build_1.createCurrentBuild)({ sourceHash }),
|
|
108
|
-
assets: manifest.map(toManifestEntry),
|
|
109
|
-
};
|
|
110
|
-
yield client.publishAssetManifest(pkg);
|
|
111
121
|
published += 1;
|
|
112
|
-
logger_1.Logger.info(
|
|
122
|
+
logger_1.Logger.info(`${(0, index_1.publishedLabel)(handoff)}: ${col} (${manifest.length} asset(s), ${missing.length} new blob(s))`);
|
|
113
123
|
}
|
|
114
124
|
catch (error) {
|
|
115
125
|
failed.push({
|
|
116
126
|
collection: col,
|
|
117
|
-
message: (0, errors_1.describePublishError)(error,
|
|
127
|
+
message: (0, errors_1.describePublishError)(error, url, 'asset collection'),
|
|
118
128
|
});
|
|
119
129
|
}
|
|
120
130
|
}
|
|
121
|
-
logger_1.Logger.success(`Assets publish complete: ${published}
|
|
131
|
+
logger_1.Logger.success(`Assets publish complete: ${published} ${handoff.dryRun ? 'would be published' : 'published'}, ` +
|
|
132
|
+
`${unchanged} unchanged, ${uploaded} blob(s) uploaded${failed.length ? `, ${failed.length} failed` : ''}.`);
|
|
122
133
|
if (failed.length > 0) {
|
|
123
134
|
for (const failure of failed) {
|
|
124
135
|
logger_1.Logger.error(` - ${failure.collection}: ${failure.message}`);
|
|
@@ -9,26 +9,50 @@
|
|
|
9
9
|
* that still guarantees the entity's artifacts (and the shared artifacts they reference) are current.
|
|
10
10
|
*/
|
|
11
11
|
import Handoff from '../../index';
|
|
12
|
+
import { type RegistryClient } from '../client';
|
|
12
13
|
import type { TransferEntityKind } from '../transfer';
|
|
13
14
|
/** A connected-workspace configuration or precondition failure surfaced to the CLI. */
|
|
14
15
|
export declare class PublishError extends Error {
|
|
15
16
|
constructor(message: string);
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Ensure this project may publish at all: a registry host stores and serves what was published to it,
|
|
20
|
+
* so only a workspace runtime can be the source. Kept apart from the connection lookup because a dry
|
|
21
|
+
* run still has to be refused on a registry host while needing no URL or token itself.
|
|
22
|
+
*/
|
|
23
|
+
export declare const assertPublishableWorkspace: (handoff: Handoff) => void;
|
|
17
24
|
/**
|
|
18
25
|
* Ensure the workspace is a connected workspace able to publish: workspace runtime mode (registry
|
|
19
26
|
* hosts do not publish) and a resolved registry URL + access token. Throws an actionable
|
|
20
27
|
* {@link PublishError} naming the exact misconfiguration.
|
|
21
28
|
*/
|
|
22
29
|
export declare const resolveConnectionOrThrow: (handoff: Handoff) => Promise<import("../connection").ResolvedRegistryConnection>;
|
|
30
|
+
/**
|
|
31
|
+
* How a publish run reaches the registry. `client` is `null` on a dry run: the documented dry run
|
|
32
|
+
* needs no registry URL or token, so it stops at the workspace guard and contacts nothing.
|
|
33
|
+
*/
|
|
34
|
+
export interface PublishTransport {
|
|
35
|
+
client: RegistryClient | null;
|
|
36
|
+
/** The registry URL, or a placeholder on a dry run. Used only in log lines and error messages. */
|
|
37
|
+
url: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the transport for a publish run. Shared by the entity, token and asset paths so the dry-run
|
|
41
|
+
* short-circuit lives in one place instead of four call sites.
|
|
42
|
+
*/
|
|
43
|
+
export declare const resolveTransport: (handoff: Handoff) => Promise<PublishTransport>;
|
|
44
|
+
/** Prefix for a per-item progress line: `Published:` normally, `Would publish:` on a dry run. */
|
|
45
|
+
export declare const publishedLabel: (handoff: Handoff) => string;
|
|
23
46
|
/**
|
|
24
47
|
* Publish a single component, pattern, or page from a connected workspace. Components and patterns
|
|
25
48
|
* receive a targeted build, while pages are packaged directly from their source.
|
|
26
49
|
*/
|
|
27
50
|
export declare const publishEntity: (handoff: Handoff, kind: TransferEntityKind, id: string) => Promise<void>;
|
|
28
51
|
/**
|
|
29
|
-
* Publish
|
|
30
|
-
* once, assembles each entity's package, skips
|
|
31
|
-
* registry (unless `--force`), and reports
|
|
32
|
-
* collected and never aborts the rest; the
|
|
52
|
+
* Publish the components, patterns or pages declared in this connected workspace: every one of the
|
|
53
|
+
* kind, or only `ids` when given. Builds the kind once, assembles each entity's package, skips
|
|
54
|
+
* entities whose content hash already matches the registry (unless `--force`), and reports
|
|
55
|
+
* published/unchanged/failed counts. A per-entity failure is collected and never aborts the rest; the
|
|
56
|
+
* run throws at the end if any entity failed.
|
|
33
57
|
*/
|
|
34
|
-
export declare const publishEntities: (handoff: Handoff, kind: TransferEntityKind) => Promise<void>;
|
|
58
|
+
export declare const publishEntities: (handoff: Handoff, kind: TransferEntityKind, ids?: string[]) => Promise<void>;
|
|
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
22
22
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.publishEntities = exports.publishEntity = exports.resolveConnectionOrThrow = exports.PublishError = void 0;
|
|
25
|
+
exports.publishEntities = exports.publishEntity = exports.publishedLabel = exports.resolveTransport = exports.resolveConnectionOrThrow = exports.assertPublishableWorkspace = exports.PublishError = void 0;
|
|
26
26
|
const css_1 = require("../../transformers/preview/component/css");
|
|
27
27
|
const javascript_1 = require("../../transformers/preview/component/javascript");
|
|
28
28
|
const builder_1 = __importDefault(require("../../transformers/preview/component/builder"));
|
|
@@ -30,6 +30,7 @@ const builder_2 = require("../../transformers/preview/pattern/builder");
|
|
|
30
30
|
const logger_1 = require("../../utils/logger");
|
|
31
31
|
const client_1 = require("../client");
|
|
32
32
|
const connection_1 = require("../connection");
|
|
33
|
+
const selection_1 = require("../selection");
|
|
33
34
|
const errors_1 = require("./errors");
|
|
34
35
|
const package_1 = require("./package");
|
|
35
36
|
/** A connected-workspace configuration or precondition failure surfaced to the CLI. */
|
|
@@ -41,17 +42,26 @@ class PublishError extends Error {
|
|
|
41
42
|
}
|
|
42
43
|
exports.PublishError = PublishError;
|
|
43
44
|
/**
|
|
44
|
-
* Ensure
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* Ensure this project may publish at all: a registry host stores and serves what was published to it,
|
|
46
|
+
* so only a workspace runtime can be the source. Kept apart from the connection lookup because a dry
|
|
47
|
+
* run still has to be refused on a registry host while needing no URL or token itself.
|
|
47
48
|
*/
|
|
48
|
-
const
|
|
49
|
+
const assertPublishableWorkspace = (handoff) => {
|
|
49
50
|
var _a, _b, _c;
|
|
50
51
|
const mode = (_c = (_b = (_a = handoff.config) === null || _a === void 0 ? void 0 : _a.runtime) === null || _b === void 0 ? void 0 : _b.mode) !== null && _c !== void 0 ? _c : 'workspace';
|
|
51
52
|
if (mode !== 'workspace') {
|
|
52
53
|
throw new PublishError(`publish is only available from a connected workspace (runtime.mode: "workspace"); this project is "${mode}". ` +
|
|
53
54
|
'A registry host stores and serves what was published to it; it does not publish.');
|
|
54
55
|
}
|
|
56
|
+
};
|
|
57
|
+
exports.assertPublishableWorkspace = assertPublishableWorkspace;
|
|
58
|
+
/**
|
|
59
|
+
* Ensure the workspace is a connected workspace able to publish: workspace runtime mode (registry
|
|
60
|
+
* hosts do not publish) and a resolved registry URL + access token. Throws an actionable
|
|
61
|
+
* {@link PublishError} naming the exact misconfiguration.
|
|
62
|
+
*/
|
|
63
|
+
const resolveConnectionOrThrow = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
+
(0, exports.assertPublishableWorkspace)(handoff);
|
|
55
65
|
const connection = yield (0, connection_1.resolveAuthenticatedRegistryConnection)(handoff.config, handoff.workingPath);
|
|
56
66
|
if (!connection.url) {
|
|
57
67
|
throw new PublishError(`No registry is configured. Run \`handoff-app login --url <registry-url>\`, set runtime.registryConnection.url, ` +
|
|
@@ -64,6 +74,25 @@ const resolveConnectionOrThrow = (handoff) => __awaiter(void 0, void 0, void 0,
|
|
|
64
74
|
return connection;
|
|
65
75
|
});
|
|
66
76
|
exports.resolveConnectionOrThrow = resolveConnectionOrThrow;
|
|
77
|
+
/**
|
|
78
|
+
* Resolve the transport for a publish run. Shared by the entity, token and asset paths so the dry-run
|
|
79
|
+
* short-circuit lives in one place instead of four call sites.
|
|
80
|
+
*/
|
|
81
|
+
const resolveTransport = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
|
+
if (handoff.dryRun) {
|
|
83
|
+
(0, exports.assertPublishableWorkspace)(handoff);
|
|
84
|
+
return { client: null, url: '(dry run)' };
|
|
85
|
+
}
|
|
86
|
+
const connection = yield (0, exports.resolveConnectionOrThrow)(handoff);
|
|
87
|
+
return {
|
|
88
|
+
client: (0, client_1.createRegistryClient)({ baseUrl: connection.url, accessToken: connection.accessToken }),
|
|
89
|
+
url: connection.url,
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
exports.resolveTransport = resolveTransport;
|
|
93
|
+
/** Prefix for a per-item progress line: `Published:` normally, `Would publish:` on a dry run. */
|
|
94
|
+
const publishedLabel = (handoff) => (handoff.dryRun ? 'Would publish' : 'Published');
|
|
95
|
+
exports.publishedLabel = publishedLabel;
|
|
67
96
|
/** Run the smallest build that guarantees the selected entity's artifacts are current. */
|
|
68
97
|
const runTargetedBuild = (handoff, kind, id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
98
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
@@ -105,19 +134,26 @@ const runTargetedBuild = (handoff, kind, id) => __awaiter(void 0, void 0, void 0
|
|
|
105
134
|
* receive a targeted build, while pages are packaged directly from their source.
|
|
106
135
|
*/
|
|
107
136
|
const publishEntity = (handoff, kind, id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
137
|
+
const { client, url } = yield (0, exports.resolveTransport)(handoff);
|
|
138
|
+
if (!handoff.skipBuild) {
|
|
139
|
+
logger_1.Logger.info(kind === 'page' ? `Preparing page "${id}" for publish…` : `Building ${kind} "${id}" for publish…`);
|
|
140
|
+
yield runTargetedBuild(handoff, kind, id);
|
|
141
|
+
}
|
|
111
142
|
const pkg = yield (0, package_1.buildPublishPackage)(handoff, kind, id);
|
|
112
143
|
(0, package_1.assertRequiredArtifactsPresent)(pkg);
|
|
113
|
-
|
|
114
|
-
|
|
144
|
+
const contents = `${pkg.artifacts.length} artifact(s), ${pkg.files.length} source file(s)`;
|
|
145
|
+
if (!client) {
|
|
146
|
+
logger_1.Logger.info(`Would publish ${kind} "${id}" (${contents}).`);
|
|
147
|
+
logger_1.Logger.success(`Dry run: ${kind} "${id}" would be published.`);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
logger_1.Logger.info(`Uploading ${kind} "${id}" to ${url} (${contents})…`);
|
|
115
151
|
try {
|
|
116
152
|
yield client.publish(kind, id, pkg);
|
|
117
153
|
}
|
|
118
154
|
catch (error) {
|
|
119
155
|
if (error instanceof client_1.RegistryClientError) {
|
|
120
|
-
throw new PublishError((0, errors_1.describeUploadFailure)(error,
|
|
156
|
+
throw new PublishError((0, errors_1.describeUploadFailure)(error, url, 'package'));
|
|
121
157
|
}
|
|
122
158
|
throw error;
|
|
123
159
|
}
|
|
@@ -144,27 +180,46 @@ const runBulkBuild = (handoff, kind) => __awaiter(void 0, void 0, void 0, functi
|
|
|
144
180
|
});
|
|
145
181
|
/** List every declared entity id of the kind from the workspace store. */
|
|
146
182
|
const listWorkspaceEntityIds = (handoff, kind) => __awaiter(void 0, void 0, void 0, function* () {
|
|
147
|
-
const
|
|
183
|
+
const stores = { component: handoff.store.components, pattern: handoff.store.patterns, page: handoff.store.pages };
|
|
184
|
+
const store = stores[kind];
|
|
185
|
+
if (!store) {
|
|
186
|
+
throw new PublishError(`Unknown entity kind "${kind}".`);
|
|
187
|
+
}
|
|
148
188
|
return (yield store.list()).map((entity) => entity.id);
|
|
149
189
|
});
|
|
150
190
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* registry (unless `--force`), and reports published/unchanged/failed counts. A per-entity failure is
|
|
154
|
-
* collected and never aborts the rest; the run throws at the end if any entity failed.
|
|
191
|
+
* Narrow the workspace's declared ids to the requested subset, naming any id that is not declared
|
|
192
|
+
* here instead of silently publishing fewer entities than asked for.
|
|
155
193
|
*/
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
194
|
+
const selectEntityIds = (available, requested, kind) => {
|
|
195
|
+
const { selected, unknown } = (0, selection_1.selectIds)(available, requested);
|
|
196
|
+
if (unknown.length > 0) {
|
|
197
|
+
throw new PublishError(`No ${kind} named ${unknown.map((id) => `"${id}"`).join(', ')} is declared in this workspace. ` +
|
|
198
|
+
`Declared ${kind}s: ${available.join(', ') || '(none)'}.`);
|
|
199
|
+
}
|
|
200
|
+
return selected;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Publish the components, patterns or pages declared in this connected workspace: every one of the
|
|
204
|
+
* kind, or only `ids` when given. Builds the kind once, assembles each entity's package, skips
|
|
205
|
+
* entities whose content hash already matches the registry (unless `--force`), and reports
|
|
206
|
+
* published/unchanged/failed counts. A per-entity failure is collected and never aborts the rest; the
|
|
207
|
+
* run throws at the end if any entity failed.
|
|
208
|
+
*/
|
|
209
|
+
const publishEntities = (handoff, kind, ids) => __awaiter(void 0, void 0, void 0, function* () {
|
|
210
|
+
const { client, url } = yield (0, exports.resolveTransport)(handoff);
|
|
211
|
+
if (!handoff.skipBuild) {
|
|
212
|
+
logger_1.Logger.info(`Building ${kind}s for publish…`);
|
|
213
|
+
yield runBulkBuild(handoff, kind);
|
|
214
|
+
}
|
|
215
|
+
const targets = selectEntityIds(yield listWorkspaceEntityIds(handoff, kind), ids, kind);
|
|
216
|
+
if (targets.length === 0) {
|
|
162
217
|
logger_1.Logger.success(`No ${kind}s are declared in this workspace; nothing to publish.`);
|
|
163
218
|
return;
|
|
164
219
|
}
|
|
165
|
-
|
|
220
|
+
// Without a registry there is nothing to compare against, so a dry run reports every target.
|
|
166
221
|
let remote = [];
|
|
167
|
-
if (!handoff.force) {
|
|
222
|
+
if (client && !handoff.force) {
|
|
168
223
|
try {
|
|
169
224
|
remote = yield client.listEntities(kind);
|
|
170
225
|
}
|
|
@@ -177,7 +232,7 @@ const publishEntities = (handoff, kind) => __awaiter(void 0, void 0, void 0, fun
|
|
|
177
232
|
let published = 0;
|
|
178
233
|
let unchanged = 0;
|
|
179
234
|
const failed = [];
|
|
180
|
-
for (const id of
|
|
235
|
+
for (const id of targets) {
|
|
181
236
|
try {
|
|
182
237
|
const pkg = yield (0, package_1.buildPublishPackage)(handoff, kind, id);
|
|
183
238
|
(0, package_1.assertRequiredArtifactsPresent)(pkg);
|
|
@@ -188,20 +243,18 @@ const publishEntities = (handoff, kind) => __awaiter(void 0, void 0, void 0, fun
|
|
|
188
243
|
logger_1.Logger.info(`Unchanged: ${id}`);
|
|
189
244
|
continue;
|
|
190
245
|
}
|
|
191
|
-
|
|
246
|
+
if (client) {
|
|
247
|
+
yield client.publish(kind, id, pkg);
|
|
248
|
+
}
|
|
192
249
|
published += 1;
|
|
193
|
-
logger_1.Logger.info(
|
|
250
|
+
logger_1.Logger.info(`${(0, exports.publishedLabel)(handoff)}: ${id} (${pkg.artifacts.length} artifact(s), ${pkg.files.length} source file(s))`);
|
|
194
251
|
}
|
|
195
252
|
catch (error) {
|
|
196
|
-
|
|
197
|
-
? (0, errors_1.describeUploadFailure)(error, connection.url, 'package')
|
|
198
|
-
: error instanceof Error
|
|
199
|
-
? error.message
|
|
200
|
-
: String(error);
|
|
201
|
-
failed.push({ id, message });
|
|
253
|
+
failed.push({ id, message: (0, errors_1.describePublishError)(error, url, 'package') });
|
|
202
254
|
}
|
|
203
255
|
}
|
|
204
|
-
logger_1.Logger.success(`${kind[0].toUpperCase()}${kind.slice(1)}s publish complete — ${published}
|
|
256
|
+
logger_1.Logger.success(`${kind[0].toUpperCase()}${kind.slice(1)}s publish complete — ${published} ${handoff.dryRun ? 'would be published' : 'published'}, ` +
|
|
257
|
+
`${unchanged} unchanged${failed.length ? `, ${failed.length} failed` : ''}.`);
|
|
205
258
|
if (failed.length > 0) {
|
|
206
259
|
for (const failure of failed) {
|
|
207
260
|
logger_1.Logger.error(` - ${failure.id}: ${failure.message}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Connected-workspace token publish orchestration.
|
|
3
3
|
*
|
|
4
|
-
* `publish tokens [setId]` runs a **fresh token build** (`handoff.fetch()` — Figma extract +
|
|
4
|
+
* `publish tokens [setId...]` runs a **fresh token build** (`handoff.fetch()` — Figma extract +
|
|
5
5
|
* `buildStyles`) so the local `tokens.json` and generated token outputs are current, discovers the
|
|
6
6
|
* logical sets from that document, then uploads each selected set (its extracted record + generated
|
|
7
7
|
* artifacts) to the connected registry. Each set is one atomic upsert; a set whose deterministic
|
|
@@ -15,4 +15,4 @@ import Handoff from '../../index';
|
|
|
15
15
|
* counts. A per-set upload failure is collected and never leaves a partially written set (each set is
|
|
16
16
|
* committed atomically server-side); the run throws at the end if any set failed.
|
|
17
17
|
*/
|
|
18
|
-
export declare const publishTokens: (handoff: Handoff,
|
|
18
|
+
export declare const publishTokens: (handoff: Handoff, selection?: string[]) => Promise<void>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Connected-workspace token publish orchestration.
|
|
4
4
|
*
|
|
5
|
-
* `publish tokens [setId]` runs a **fresh token build** (`handoff.fetch()` — Figma extract +
|
|
5
|
+
* `publish tokens [setId...]` runs a **fresh token build** (`handoff.fetch()` — Figma extract +
|
|
6
6
|
* `buildStyles`) so the local `tokens.json` and generated token outputs are current, discovers the
|
|
7
7
|
* logical sets from that document, then uploads each selected set (its extracted record + generated
|
|
8
8
|
* artifacts) to the connected registry. Each set is one atomic upsert; a set whose deterministic
|
|
@@ -22,7 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
22
22
|
exports.publishTokens = void 0;
|
|
23
23
|
const logger_1 = require("../../utils/logger");
|
|
24
24
|
const stable_stringify_1 = require("../../utils/stable-stringify");
|
|
25
|
-
const
|
|
25
|
+
const selection_1 = require("../selection");
|
|
26
26
|
const errors_1 = require("./errors");
|
|
27
27
|
const index_1 = require("./index");
|
|
28
28
|
const publish_build_1 = require("./publish-build");
|
|
@@ -58,28 +58,31 @@ const buildTokenSetPackage = (handoff, set) => __awaiter(void 0, void 0, void 0,
|
|
|
58
58
|
* counts. A per-set upload failure is collected and never leaves a partially written set (each set is
|
|
59
59
|
* committed atomically server-side); the run throws at the end if any set failed.
|
|
60
60
|
*/
|
|
61
|
-
const publishTokens = (handoff,
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
const publishTokens = (handoff, selection) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
const { client, url } = yield (0, index_1.resolveTransport)(handoff);
|
|
63
|
+
if (!handoff.skipBuild) {
|
|
64
|
+
logger_1.Logger.info(selection ? `Building tokens to publish ${selection.map((id) => `"${id}"`).join(', ')}…` : 'Building tokens for publish…');
|
|
65
|
+
yield handoff.fetch();
|
|
66
|
+
}
|
|
65
67
|
const allSets = yield handoff.store.tokens.listSets();
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
throw new index_1.PublishError(`Token set "${setId}" was not found in the generated tokens. Discovered sets: ${allSets.map((set) => set.id).join(', ') || '(none)'}.`);
|
|
71
|
-
}
|
|
72
|
-
targetSets = [found];
|
|
68
|
+
const { selected, unknown } = (0, selection_1.selectIds)(allSets.map((set) => set.id), selection);
|
|
69
|
+
if (unknown.length > 0) {
|
|
70
|
+
throw new index_1.PublishError(`Token set ${unknown.map((id) => `"${id}"`).join(', ')} was not found in the generated tokens. ` +
|
|
71
|
+
`Discovered sets: ${allSets.map((set) => set.id).join(', ') || '(none)'}.`);
|
|
73
72
|
}
|
|
73
|
+
const selectedIds = new Set(selected);
|
|
74
|
+
const targetSets = allSets.filter((set) => selectedIds.has(set.id));
|
|
74
75
|
const packages = yield Promise.all(targetSets.map((set) => buildTokenSetPackage(handoff, set)));
|
|
75
|
-
|
|
76
|
+
// Without a registry there is nothing to compare against, so a dry run reports every set.
|
|
76
77
|
let remote = [];
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
if (client) {
|
|
79
|
+
try {
|
|
80
|
+
remote = yield client.listTokenSets();
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
// If the summary listing fails we simply publish everything (the server still no-ops unchanged sets).
|
|
84
|
+
logger_1.Logger.info('Could not read current registry token sets; publishing all selected sets.');
|
|
85
|
+
}
|
|
83
86
|
}
|
|
84
87
|
const remoteHashById = new Map(remote.map((entry) => [entry.id, entry.sourceHash]));
|
|
85
88
|
let published = 0;
|
|
@@ -93,15 +96,18 @@ const publishTokens = (handoff, setId) => __awaiter(void 0, void 0, void 0, func
|
|
|
93
96
|
continue;
|
|
94
97
|
}
|
|
95
98
|
try {
|
|
96
|
-
|
|
99
|
+
if (client) {
|
|
100
|
+
yield client.publishTokens(pkg);
|
|
101
|
+
}
|
|
97
102
|
published += 1;
|
|
98
|
-
logger_1.Logger.info(
|
|
103
|
+
logger_1.Logger.info(`${(0, index_1.publishedLabel)(handoff)}: ${pkg.id} (${pkg.artifacts.length} artifact(s))`);
|
|
99
104
|
}
|
|
100
105
|
catch (error) {
|
|
101
|
-
failed.push({ id: pkg.id, message: (0, errors_1.describePublishError)(error,
|
|
106
|
+
failed.push({ id: pkg.id, message: (0, errors_1.describePublishError)(error, url, 'token set') });
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
|
-
logger_1.Logger.success(`Tokens publish complete — ${published}
|
|
109
|
+
logger_1.Logger.success(`Tokens publish complete — ${published} ${handoff.dryRun ? 'would be published' : 'published'}, ` +
|
|
110
|
+
`${unchanged} unchanged${failed.length ? `, ${failed.length} failed` : ''}.`);
|
|
105
111
|
if (failed.length > 0) {
|
|
106
112
|
for (const failure of failed) {
|
|
107
113
|
logger_1.Logger.error(` - ${failure.id}: ${failure.message}`);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Selection narrowing shared by the publish and checkout orchestration.
|
|
3
|
+
*
|
|
4
|
+
* Every bulk operation discovers what is available (declared locally or published remotely) and may
|
|
5
|
+
* be asked for only part of it. Splitting the request into what exists and what does not lets each
|
|
6
|
+
* caller build its own actionable error while the matching lives in one place.
|
|
7
|
+
*/
|
|
8
|
+
/** Narrow an available list to the requested subset, separating out ids that do not exist. */
|
|
9
|
+
export declare const selectIds: (available: string[], requested?: string[]) => {
|
|
10
|
+
selected: string[];
|
|
11
|
+
unknown: string[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Selection narrowing shared by the publish and checkout orchestration.
|
|
4
|
+
*
|
|
5
|
+
* Every bulk operation discovers what is available (declared locally or published remotely) and may
|
|
6
|
+
* be asked for only part of it. Splitting the request into what exists and what does not lets each
|
|
7
|
+
* caller build its own actionable error while the matching lives in one place.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.selectIds = void 0;
|
|
11
|
+
/** Narrow an available list to the requested subset, separating out ids that do not exist. */
|
|
12
|
+
const selectIds = (available, requested) => {
|
|
13
|
+
if (!requested) {
|
|
14
|
+
return { selected: available, unknown: [] };
|
|
15
|
+
}
|
|
16
|
+
const availableIds = new Set(available);
|
|
17
|
+
return {
|
|
18
|
+
selected: requested.filter((id) => availableIds.has(id)),
|
|
19
|
+
unknown: requested.filter((id) => !availableIds.has(id)),
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
exports.selectIds = selectIds;
|
package/dist/store/registry.d.ts
CHANGED
|
@@ -57,6 +57,54 @@ export declare class RegistryPageStore implements PageStore {
|
|
|
57
57
|
getSource(_ref: SourceReference): Promise<TextFileResource | null>;
|
|
58
58
|
getRelatedSourceFiles(id: string): Promise<TextFileResource[]>;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* The page fields that search reads. The query cuts the stored parsed body to `bodyLength`.
|
|
62
|
+
* The body is empty for an external-link page and for a page with no stored markdown.
|
|
63
|
+
*/
|
|
64
|
+
export interface PageSearchCandidate {
|
|
65
|
+
record: PageListObject;
|
|
66
|
+
body: string;
|
|
67
|
+
}
|
|
68
|
+
export interface PageSearchCandidateQuery {
|
|
69
|
+
/** Normalized terms. A page is a candidate when any term occurs in any searchable column. */
|
|
70
|
+
terms: string[];
|
|
71
|
+
/** Optional group filter, matched case-insensitively. */
|
|
72
|
+
group?: string;
|
|
73
|
+
/** Maximum rows returned to the server for one search. */
|
|
74
|
+
limit: number;
|
|
75
|
+
/**
|
|
76
|
+
* Code points of each returned body, and the prefix the body filter reads, so one search costs at most
|
|
77
|
+
* `limit × bodyLength`. The query cuts with `left`, which counts code points. Workspace search must count the same
|
|
78
|
+
* unit, or the modes match different text.
|
|
79
|
+
*/
|
|
80
|
+
bodyLength: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Candidate pages for a search, filtered and capped in SQL.
|
|
84
|
+
*
|
|
85
|
+
* `enabled` and `menuTitle` are fields in the `record` JSON, so the query uses JSON operators. An
|
|
86
|
+
* absent `enabled` field means enabled. The body filter excludes frontmatter, so an excluded field
|
|
87
|
+
* such as `metaTitle` cannot consume a candidate slot.
|
|
88
|
+
*
|
|
89
|
+
* The filter and the projection share one body expression, so every term SQL matched is inside the text that the
|
|
90
|
+
* server ranks.
|
|
91
|
+
*
|
|
92
|
+
* The body expression is empty for an external-link page. Search reads such a page by title, menu title, and
|
|
93
|
+
* description only. The exclusion must happen in SQL. An external body otherwise satisfies the filter and takes one
|
|
94
|
+
* of the `limit` rows. It pushes a real candidate past the cap before the server can drop it.
|
|
95
|
+
*
|
|
96
|
+
* `C` collation orders IDs by code point, as the merge in registry search does. Both orders must
|
|
97
|
+
* agree, or the cap can keep different pages in each runtime mode.
|
|
98
|
+
*/
|
|
99
|
+
export declare const searchPageCandidates: (db: RegistryDatabase, query: PageSearchCandidateQuery) => Promise<PageSearchCandidate[]>;
|
|
100
|
+
/**
|
|
101
|
+
* The candidate IDs that have a published page. Search asks only about packaged default IDs, because
|
|
102
|
+
* no other ID can replace a default. This keeps the query bounded as the registry grows.
|
|
103
|
+
*
|
|
104
|
+
* A published page replaces the default with the same ID even when it does not match the search
|
|
105
|
+
* terms, so this query ignores the term filter.
|
|
106
|
+
*/
|
|
107
|
+
export declare const filterPublishedPageIds: (db: RegistryDatabase, candidateIds: string[]) => Promise<string[]>;
|
|
60
108
|
export declare class RegistryTokenStore implements TokenStore {
|
|
61
109
|
private readonly context;
|
|
62
110
|
constructor(context: RegistryStoreContext);
|