@forumulate/cli 0.3.5 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +100 -21
  2. package/dist/api-base.d.ts +26 -7
  3. package/dist/api-base.d.ts.map +1 -1
  4. package/dist/api-base.js +38 -8
  5. package/dist/api-base.js.map +1 -1
  6. package/dist/cli.js +25 -1
  7. package/dist/cli.js.map +1 -1
  8. package/dist/credentials.d.ts +1 -1
  9. package/dist/doctor.d.ts +13 -0
  10. package/dist/doctor.d.ts.map +1 -1
  11. package/dist/doctor.js +113 -44
  12. package/dist/doctor.js.map +1 -1
  13. package/dist/publish/api.d.ts +95 -0
  14. package/dist/publish/api.d.ts.map +1 -0
  15. package/dist/publish/api.js +265 -0
  16. package/dist/publish/api.js.map +1 -0
  17. package/dist/publish/command.d.ts +44 -0
  18. package/dist/publish/command.d.ts.map +1 -0
  19. package/dist/publish/command.js +246 -0
  20. package/dist/publish/command.js.map +1 -0
  21. package/dist/publish/compare.d.ts +45 -0
  22. package/dist/publish/compare.d.ts.map +1 -0
  23. package/dist/publish/compare.js +124 -0
  24. package/dist/publish/compare.js.map +1 -0
  25. package/dist/publish/context.d.ts +46 -0
  26. package/dist/publish/context.d.ts.map +1 -0
  27. package/dist/publish/context.js +54 -0
  28. package/dist/publish/context.js.map +1 -0
  29. package/dist/publish/docs-apply.d.ts +39 -0
  30. package/dist/publish/docs-apply.d.ts.map +1 -0
  31. package/dist/publish/docs-apply.js +178 -0
  32. package/dist/publish/docs-apply.js.map +1 -0
  33. package/dist/publish/docs-plan.d.ts +40 -0
  34. package/dist/publish/docs-plan.d.ts.map +1 -0
  35. package/dist/publish/docs-plan.js +211 -0
  36. package/dist/publish/docs-plan.js.map +1 -0
  37. package/dist/publish/docs-reconcile.d.ts +26 -0
  38. package/dist/publish/docs-reconcile.d.ts.map +1 -0
  39. package/dist/publish/docs-reconcile.js +162 -0
  40. package/dist/publish/docs-reconcile.js.map +1 -0
  41. package/dist/publish/extras.d.ts +25 -0
  42. package/dist/publish/extras.d.ts.map +1 -0
  43. package/dist/publish/extras.js +218 -0
  44. package/dist/publish/extras.js.map +1 -0
  45. package/dist/publish/frontmatter.d.ts +45 -0
  46. package/dist/publish/frontmatter.d.ts.map +1 -0
  47. package/dist/publish/frontmatter.js +265 -0
  48. package/dist/publish/frontmatter.js.map +1 -0
  49. package/dist/publish/manifest.d.ts +5 -0
  50. package/dist/publish/manifest.d.ts.map +1 -0
  51. package/dist/publish/manifest.js +144 -0
  52. package/dist/publish/manifest.js.map +1 -0
  53. package/dist/publish/posts.d.ts +39 -0
  54. package/dist/publish/posts.d.ts.map +1 -0
  55. package/dist/publish/posts.js +350 -0
  56. package/dist/publish/posts.js.map +1 -0
  57. package/dist/publish/rewrite.d.ts +20 -0
  58. package/dist/publish/rewrite.d.ts.map +1 -0
  59. package/dist/publish/rewrite.js +82 -0
  60. package/dist/publish/rewrite.js.map +1 -0
  61. package/dist/publish/scan.d.ts +25 -0
  62. package/dist/publish/scan.d.ts.map +1 -0
  63. package/dist/publish/scan.js +351 -0
  64. package/dist/publish/scan.js.map +1 -0
  65. package/dist/publish/types.d.ts +155 -0
  66. package/dist/publish/types.d.ts.map +1 -0
  67. package/dist/publish/types.js +13 -0
  68. package/dist/publish/types.js.map +1 -0
  69. package/dist/run.d.ts +10 -1
  70. package/dist/run.d.ts.map +1 -1
  71. package/dist/run.js +71 -51
  72. package/dist/run.js.map +1 -1
  73. package/package.json +4 -3
  74. package/dist/publish-dir.d.ts +0 -54
  75. package/dist/publish-dir.d.ts.map +0 -1
  76. package/dist/publish-dir.js +0 -119
  77. package/dist/publish-dir.js.map +0 -1
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runPublish = runPublish;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const api_1 = require("./api");
7
+ const context_1 = require("./context");
8
+ const docs_plan_1 = require("./docs-plan");
9
+ const docs_apply_1 = require("./docs-apply");
10
+ const docs_reconcile_1 = require("./docs-reconcile");
11
+ const extras_1 = require("./extras");
12
+ const manifest_1 = require("./manifest");
13
+ const posts_1 = require("./posts");
14
+ const scan_1 = require("./scan");
15
+ const ACTION = ['create', 'update', 'meta', 'move', 'order', 'prune', 'patch'];
16
+ async function runPublish(opts, deps) {
17
+ const root = (0, node_path_1.resolve)(opts.folder);
18
+ if (!(0, node_fs_1.existsSync)(root) || !(0, node_fs_1.statSync)(root).isDirectory()) {
19
+ deps.err(`${opts.folder} is not a folder`);
20
+ return 1;
21
+ }
22
+ const manifest = (0, manifest_1.loadManifest)((0, manifest_1.findManifest)(root, opts.manifest));
23
+ const org = opts.org ?? manifest.org ?? (deps.env ?? process.env).FORUMULATE_ORG;
24
+ if (!org) {
25
+ deps.err('Which organization? Pass --org <id|slug>, set FORUMULATE_ORG, or put `org:` in forumulate.yaml.');
26
+ return 1;
27
+ }
28
+ if (opts.space) {
29
+ if (manifest.spaces.length > 1) {
30
+ deps.err('--space names one space; this manifest has several — narrow with --only <folder> instead.');
31
+ return 1;
32
+ }
33
+ manifest.spaces[0].space = opts.space;
34
+ }
35
+ const missing = manifest.spaces.find((s) => !s.space);
36
+ if (missing) {
37
+ deps.err(`Which space${missing.path ? ` for ${missing.path}/` : ''}? Pass --space <id|slug> or put \`space:\` in the manifest.`);
38
+ return 1;
39
+ }
40
+ if (!deps.authed && !opts.dryRun) {
41
+ deps.err('Publishing needs a token: `forumulate login`, or FORUMULATE_TOKEN in CI. `--dry-run` works without one against a public space.');
42
+ return 1;
43
+ }
44
+ const only = new context_1.Selector(opts.only);
45
+ const lines = [];
46
+ const errors = [];
47
+ const print = (space) => (l) => {
48
+ lines.push({ space, line: l });
49
+ if (!opts.json && (l.verb !== 'same' || process.env.VERBOSE))
50
+ deps.out(` ${l.verb.padEnd(7)} ${l.what}${l.detail ? ` ${l.detail}` : ''}`);
51
+ };
52
+ const api = (readOnly) => new api_1.PublishApi({
53
+ client: deps.client,
54
+ authed: deps.authed,
55
+ readOnly,
56
+ paceMs: opts.paceMs,
57
+ upload: deps.upload,
58
+ sleep: deps.sleep,
59
+ });
60
+ const writer = api(opts.dryRun);
61
+ let orgId;
62
+ try {
63
+ orgId = await writer.orgId(org);
64
+ }
65
+ catch (e) {
66
+ deps.err(e.message);
67
+ return 1;
68
+ }
69
+ const runAll = async (a, mode, sink) => {
70
+ for (const spec of manifest.spaces) {
71
+ if (!opts.json && mode !== 'verify')
72
+ deps.out(`\nspace ${spec.space} ← ${spec.path || '.'}/${mode === 'plan' ? ' (dry run)' : ''}`);
73
+ try {
74
+ await runSpace(a, mode, spec, {
75
+ ...opts,
76
+ root,
77
+ orgId,
78
+ only,
79
+ manifest,
80
+ errors,
81
+ line: sink(spec.space),
82
+ });
83
+ }
84
+ catch (e) {
85
+ const err = e;
86
+ errors.push(`${spec.space}: ${err.status ? `${err.status} ` : ''}${err.code ? `(${err.code}) ` : ''}${err.message ?? String(e)}`);
87
+ }
88
+ }
89
+ if (manifest.site && only.part('site')) {
90
+ try {
91
+ await (0, extras_1.syncSite)(a, orgId, manifest.site, mode === 'apply', sink('site'));
92
+ }
93
+ catch (e) {
94
+ errors.push(`site: ${e.message}`);
95
+ }
96
+ }
97
+ };
98
+ await runAll(writer, opts.dryRun ? 'plan' : 'apply', print);
99
+ // Read back: plan again against what is live now. Anything still to do failed.
100
+ let unverified = [];
101
+ if (!opts.dryRun && opts.verify && errors.length === 0) {
102
+ const again = [];
103
+ await runAll(api(true), 'verify', (space) => (l) => again.push({ space, line: l }));
104
+ unverified = again.filter((x) => ACTION.includes(x.line.verb));
105
+ }
106
+ const count = (v) => lines.filter((l) => l.line.verb === v).length;
107
+ if (opts.json) {
108
+ deps.out(JSON.stringify({ dryRun: opts.dryRun, lines, errors, unverified, writes: writer.writes }, null, 2));
109
+ }
110
+ else {
111
+ deps.out('');
112
+ const parts = ACTION.map((v) => [v, count(v)])
113
+ .filter(([, n]) => n)
114
+ .map(([v, n]) => `${n} ${v}`);
115
+ deps.out(parts.length ? parts.join(', ') : 'Nothing to change — the space already matches the folder.');
116
+ for (const e of errors)
117
+ deps.err(`error: ${e}`);
118
+ if (opts.dryRun)
119
+ deps.out(`--dry-run: nothing was written${deps.authed ? '' : ' (read anonymously: published content only)'}.`);
120
+ else if (!opts.verify)
121
+ deps.out(`${writer.writes} write(s); read-back skipped (--no-verify).`);
122
+ else if (errors.length)
123
+ deps.out(`${writer.writes} write(s); read-back skipped because of the errors above.`);
124
+ else if (unverified.length) {
125
+ deps.err(`Read-back: ${unverified.length} change(s) did not land:`);
126
+ for (const u of unverified)
127
+ deps.err(` ${u.space} ${u.line.verb} ${u.line.what}${u.line.detail ? ` ${u.line.detail}` : ''}`);
128
+ }
129
+ else
130
+ deps.out(`${writer.writes} write(s); read back from the API — everything matches.`);
131
+ }
132
+ return errors.length || unverified.length ? 1 : 0;
133
+ }
134
+ async function runSpace(api, mode, spec, run) {
135
+ const apply = mode === 'apply';
136
+ let live = await api.space(run.orgId, spec.space);
137
+ if (!live) {
138
+ if (!spec.create)
139
+ throw new Error(`no space "${spec.space}" — add \`create: { type: DOCS }\` to the manifest to make it`);
140
+ run.line({
141
+ verb: 'create',
142
+ what: `space ${spec.space}`,
143
+ detail: `${spec.create.type ?? 'DOCS'} "${spec.create.name ?? spec.space}"`,
144
+ });
145
+ if (!apply) {
146
+ // Nothing to read: everything in the folder is a create.
147
+ live = {
148
+ id: '00000000-0000-0000-0000-000000000000',
149
+ slug: spec.space,
150
+ type: spec.create.type ?? 'DOCS',
151
+ orgId: run.orgId,
152
+ };
153
+ }
154
+ else {
155
+ const { space } = await api.post(`/orgs/${run.orgId}/spaces`, {
156
+ name: spec.create.name ?? spec.space,
157
+ slug: spec.space,
158
+ type: spec.create.type ?? 'DOCS',
159
+ ...(spec.create.visibility ? { visibility: spec.create.visibility } : {}),
160
+ });
161
+ live = { ...space, orgId: run.orgId };
162
+ }
163
+ }
164
+ const isNew = live.id === '00000000-0000-0000-0000-000000000000';
165
+ const org = api.opts.authed ? run.orgId : live.orgId;
166
+ const backing = (await api.get(`/space-types/${live.type}`))
167
+ .spaceType.backing;
168
+ const empty = { collections: [], pages: [], publicRows: new Map() };
169
+ const docsLive = backing === 'page' && !isNew
170
+ ? await api.docs(org, live.id)
171
+ : { ...empty, fieldKeys: [] };
172
+ const kind = backing === 'page' ? 'docs' : 'posts';
173
+ const scan = (0, scan_1.scanSpace)(run.root, spec, kind, docsLive.fieldKeys);
174
+ const ctx = {
175
+ api,
176
+ org,
177
+ spaceId: live.id,
178
+ type: live.type,
179
+ spec,
180
+ scan,
181
+ root: run.root,
182
+ only: run.only,
183
+ force: run.force && mode !== 'verify',
184
+ prune: run.prune,
185
+ dryRun: !apply,
186
+ line: run.line,
187
+ errors: run.errors,
188
+ };
189
+ if (mode !== 'verify')
190
+ for (const w of scan.warnings)
191
+ run.line({ verb: 'warn', what: spec.path || '.', detail: w });
192
+ if (backing !== 'page' && backing !== 'topic' && (scan.posts.length || scan.collections.length))
193
+ run.line({
194
+ verb: 'warn',
195
+ what: spec.space,
196
+ detail: `a ${live.type} space does not take Markdown pieces — only its manifest settings are applied`,
197
+ });
198
+ if (!isNew) {
199
+ await (0, extras_1.syncSpace)(ctx, apply);
200
+ await (0, extras_1.syncTheme)(ctx, apply);
201
+ }
202
+ const existingAssets = isNew ? new Map() : await api.assets(org, live.id);
203
+ if (backing === 'topic' && !isNew)
204
+ await (0, posts_1.publishPosts)(ctx, apply, existingAssets);
205
+ else if (backing === 'topic')
206
+ for (const p of scan.posts)
207
+ run.line({ verb: 'create', what: `post ${p.slug}`, detail: `← ${p.file}` });
208
+ if (backing === 'page') {
209
+ const openapiCollections = new Set((spec.openapi ?? []).map((o) => o.collection.toLowerCase()));
210
+ let markdown = null;
211
+ const bodyOf = async (p) => {
212
+ if (!api.opts.authed)
213
+ return api.publicMarkdown(org, live.id, p.id);
214
+ markdown ??= await api.markdownById(org, live.id);
215
+ return markdown.get(p.id) ?? null;
216
+ };
217
+ const plan = await (0, docs_plan_1.planDocs)(ctx, docsLive, bodyOf, openapiCollections);
218
+ const metaOf = (id) => api.opts.authed ? api.pageMeta(org, live.id, id) : Promise.resolve(null);
219
+ const bulkOrder = { available: undefined };
220
+ if (!apply) {
221
+ if (mode === 'plan' && api.opts.authed && !isNew)
222
+ await (0, docs_apply_1.dryRunImports)(ctx, plan);
223
+ await (0, docs_reconcile_1.reconcileDocs)(ctx, {
224
+ live: docsLive,
225
+ collectionOf: plan.collectionOf,
226
+ metaOf,
227
+ urlsFor: (0, docs_apply_1.knownUrls)(ctx, existingAssets),
228
+ bulkOrder,
229
+ }, false);
230
+ }
231
+ else {
232
+ const urls = await (0, docs_apply_1.applyDocs)(ctx, plan, existingAssets);
233
+ const fresh = await api.docs(org, live.id);
234
+ const collectionOf = (0, docs_plan_1.matchCollections)(scan.collections, fresh.collections, spec.rootCollection);
235
+ await (0, docs_reconcile_1.reconcileDocs)(ctx, { live: fresh, collectionOf, metaOf, urlsFor: (f) => urls.get(f) ?? new Map(), bulkOrder }, true);
236
+ await (0, docs_apply_1.applyPrune)(ctx, plan);
237
+ }
238
+ if (mode !== 'verify') {
239
+ const cols = apply ? (await api.docs(org, live.id)).collections : docsLive.collections;
240
+ await (0, extras_1.syncOpenApi)(ctx, apply, run.manifest.file, cols);
241
+ }
242
+ }
243
+ if (!isNew)
244
+ await (0, extras_1.syncMonitors)(ctx, apply);
245
+ }
246
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/publish/command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * "Is the live page already this file?" — asked without the product's converter.
3
+ *
4
+ * The exact answer needs the product's own Markdown converter, which is not
5
+ * published, so a CLI on npm cannot load it. What that converter taught us the
6
+ * hard way still applies, so this keeps its rules:
7
+ *
8
+ * - Wrapping is not content. Source files are hard-wrapped and the stored
9
+ * page is one line per paragraph, so comparing lines measured the wrapping
10
+ * and reported everything as drifted.
11
+ * - The page's own title is not body: the importer lifts the leading `# H1`
12
+ * into the title, and the public `.md` puts it back.
13
+ * - Our agent footer ("## For AI agents") is appended on the public read and
14
+ * is never in the file.
15
+ * - Link and image TARGETS are not compared: the import rewrites `./x.md` to
16
+ * the page address and a local image to an uploaded asset URL, so the
17
+ * target is never the same string twice. The link TEXT is compared.
18
+ *
19
+ * What is left is the sequence of words and the punctuation that changes
20
+ * meaning. A change to formatting alone (bold added to a word) is invisible to
21
+ * this, on purpose — `--force` re-sends everything for the rare run where that
22
+ * is the whole change.
23
+ */
24
+ export declare function comparable(markdown: string): string;
25
+ /** Same text by the rules above. */
26
+ export declare const sameText: (a: string, b: string) => boolean;
27
+ /** Structural equality for JSON-ish values — objects compared key by key, order-free. */
28
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
29
+ /**
30
+ * Does `live` already hold everything `want` says? Extra keys on the live side
31
+ * are fine — a manifest names what it manages, and a PATCH merges.
32
+ */
33
+ export declare function holds(live: unknown, want: unknown): boolean;
34
+ /** The top-level keys of `want` that `live` does not already hold. */
35
+ export declare function differingKeys(live: Record<string, unknown> | undefined, want: Record<string, unknown>): string[];
36
+ /**
37
+ * Which items can stay where they are when `current` is rearranged into
38
+ * `desired` — the longest run already in the right relative order.
39
+ *
40
+ * Reordering one page at a time costs a request per page, paced to stay under
41
+ * the rate limit. Moving only the pages NOT in this run turns "swap
42
+ * two pages" from n requests into one or two.
43
+ */
44
+ export declare function stayPut(desired: string[], current: string[]): Set<string>;
45
+ //# sourceMappingURL=compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../src/publish/compare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkBnD;AAED,oCAAoC;AACpC,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OAA0C,CAAC;AAE3F,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAqBzD;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAO3D;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,EAAE,CAEV;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAsBzE"}
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sameText = void 0;
4
+ exports.comparable = comparable;
5
+ exports.deepEqual = deepEqual;
6
+ exports.holds = holds;
7
+ exports.differingKeys = differingKeys;
8
+ exports.stayPut = stayPut;
9
+ /**
10
+ * "Is the live page already this file?" — asked without the product's converter.
11
+ *
12
+ * The exact answer needs the product's own Markdown converter, which is not
13
+ * published, so a CLI on npm cannot load it. What that converter taught us the
14
+ * hard way still applies, so this keeps its rules:
15
+ *
16
+ * - Wrapping is not content. Source files are hard-wrapped and the stored
17
+ * page is one line per paragraph, so comparing lines measured the wrapping
18
+ * and reported everything as drifted.
19
+ * - The page's own title is not body: the importer lifts the leading `# H1`
20
+ * into the title, and the public `.md` puts it back.
21
+ * - Our agent footer ("## For AI agents") is appended on the public read and
22
+ * is never in the file.
23
+ * - Link and image TARGETS are not compared: the import rewrites `./x.md` to
24
+ * the page address and a local image to an uploaded asset URL, so the
25
+ * target is never the same string twice. The link TEXT is compared.
26
+ *
27
+ * What is left is the sequence of words and the punctuation that changes
28
+ * meaning. A change to formatting alone (bold added to a word) is invisible to
29
+ * this, on purpose — `--force` re-sends everything for the rare run where that
30
+ * is the whole change.
31
+ */
32
+ function comparable(markdown) {
33
+ let s = markdown.replace(/\r\n?/g, '\n');
34
+ s = s.replace(/^\ufeff?---\n[\s\S]*?\n---[ \t]*\n?/, '');
35
+ const footer = s.search(/\n-{3,}\s*\n+#{1,3} For AI agents\b/);
36
+ if (footer >= 0)
37
+ s = s.slice(0, footer);
38
+ // Every leading H1: the public read prepends the title, and a file that
39
+ // declares a title AND opens with a heading keeps that heading as content.
40
+ s = s.replace(/^(?:\s*#\s+[^\n]*(?:\n|$))+/, '');
41
+ s = s.replace(/(!?\[[^\]]*\])\([^)]*\)/g, '$1');
42
+ s = s.replace(/\b(?:src|href|poster)\s*=\s*["'][^"']*["']/g, '');
43
+ // Markup characters whose spelling the converter normalises: emphasis
44
+ // markers, table padding, list bullets, heading hashes, escapes.
45
+ s = s
46
+ .replace(/[*_`#>|\\~]+/g, ' ')
47
+ .replace(/^\s*[-+]\s+/gm, ' ')
48
+ .replace(/^\s*\d+[.)]\s+/gm, ' ');
49
+ s = s.replace(/:-{3,}:?|-{3,}:?/g, ' ');
50
+ return s.replace(/\s+/g, ' ').trim();
51
+ }
52
+ /** Same text by the rules above. */
53
+ const sameText = (a, b) => comparable(a) === comparable(b);
54
+ exports.sameText = sameText;
55
+ /** Structural equality for JSON-ish values — objects compared key by key, order-free. */
56
+ function deepEqual(a, b) {
57
+ if (a === b)
58
+ return true;
59
+ if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') {
60
+ // `undefined` and absent and `null` are the same "not set" for a patch.
61
+ return (a ?? null) === (b ?? null);
62
+ }
63
+ if (Array.isArray(a) !== Array.isArray(b))
64
+ return false;
65
+ if (Array.isArray(a)) {
66
+ const bb = b;
67
+ return a.length === bb.length && a.every((x, i) => deepEqual(x, bb[i]));
68
+ }
69
+ const ka = Object.keys(a).filter((k) => a[k] !== undefined);
70
+ const kb = Object.keys(b).filter((k) => b[k] !== undefined);
71
+ if (ka.length !== kb.length)
72
+ return false;
73
+ return ka.every((k) => deepEqual(a[k], b[k]));
74
+ }
75
+ /**
76
+ * Does `live` already hold everything `want` says? Extra keys on the live side
77
+ * are fine — a manifest names what it manages, and a PATCH merges.
78
+ */
79
+ function holds(live, want) {
80
+ if (want === null || typeof want !== 'object' || Array.isArray(want))
81
+ return deepEqual(live, want);
82
+ if (live === null || typeof live !== 'object' || Array.isArray(live))
83
+ return false;
84
+ return Object.entries(want).every(([k, v]) => holds(live[k], v));
85
+ }
86
+ /** The top-level keys of `want` that `live` does not already hold. */
87
+ function differingKeys(live, want) {
88
+ return Object.keys(want).filter((k) => !holds(live?.[k], want[k]));
89
+ }
90
+ /**
91
+ * Which items can stay where they are when `current` is rearranged into
92
+ * `desired` — the longest run already in the right relative order.
93
+ *
94
+ * Reordering one page at a time costs a request per page, paced to stay under
95
+ * the rate limit. Moving only the pages NOT in this run turns "swap
96
+ * two pages" from n requests into one or two.
97
+ */
98
+ function stayPut(desired, current) {
99
+ const pos = new Map(current.map((id, i) => [id, i]));
100
+ const seq = desired.filter((id) => pos.has(id));
101
+ const idx = seq.map((id) => pos.get(id));
102
+ // Patience LIS with predecessor links.
103
+ const tails = [];
104
+ const prev = new Array(idx.length).fill(-1);
105
+ for (let i = 0; i < idx.length; i++) {
106
+ let lo = 0;
107
+ let hi = tails.length;
108
+ while (lo < hi) {
109
+ const mid = (lo + hi) >> 1;
110
+ if (idx[tails[mid]] < idx[i])
111
+ lo = mid + 1;
112
+ else
113
+ hi = mid;
114
+ }
115
+ if (lo > 0)
116
+ prev[i] = tails[lo - 1];
117
+ tails[lo] = i;
118
+ }
119
+ const keep = new Set();
120
+ for (let k = tails.length ? tails[tails.length - 1] : -1; k >= 0; k = prev[k])
121
+ keep.add(seq[k]);
122
+ return keep;
123
+ }
124
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../../src/publish/compare.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { PublishApi } from './api';
2
+ import type { ScanResult } from './scan';
3
+ import type { PlanLine, SpaceSpec } from './types';
4
+ /**
5
+ * `--only`: what a run is allowed to touch.
6
+ *
7
+ * A token matches a slug, a file path or a folder (prefix), a collection, a
8
+ * space's folder or slug, or one of the manifest's parts by name — `site`,
9
+ * `theme`, `settings`, `openapi`, `monitors`. With no `--only`, everything.
10
+ * A run narrowed this way never prunes: "publish just this page" must not
11
+ * read as "and delete every page I did not name".
12
+ */
13
+ export declare class Selector {
14
+ readonly all: boolean;
15
+ private readonly tokens;
16
+ constructor(only: string[] | undefined);
17
+ private hit;
18
+ /** A manifest part (`theme`, `monitors`, …) of a space. */
19
+ part(name: string, space?: SpaceSpec): boolean;
20
+ space(spec: SpaceSpec): boolean;
21
+ /** A page or post, by slug, by its file (relative to the publish root), or its collection. */
22
+ piece(spec: SpaceSpec, slug: string, file: string, collection?: {
23
+ dir: string;
24
+ slug: string;
25
+ }): boolean;
26
+ }
27
+ /** Everything one space's planning and applying share. */
28
+ export interface SpaceCtx {
29
+ api: PublishApi;
30
+ /** The org as the API is addressed for this run: an id when authenticated, else what was given. */
31
+ org: string;
32
+ spaceId: string;
33
+ type: string;
34
+ spec: SpaceSpec;
35
+ scan: ScanResult;
36
+ /** The publish root (the folder given on the command line). */
37
+ root: string;
38
+ only: Selector;
39
+ force: boolean;
40
+ prune: boolean;
41
+ dryRun: boolean;
42
+ line: (l: PlanLine) => void;
43
+ errors: string[];
44
+ }
45
+ export declare const spacePath: (ctx: SpaceCtx, rest: string) => string;
46
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/publish/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACnB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;gBACtB,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS;IAMtC,OAAO,CAAC,GAAG;IAKX,2DAA2D;IAC3D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO;IAG9C,KAAK,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO;IAG/B,8FAA8F;IAC9F,KAAK,CACH,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GACzC,OAAO;CAcX;AAED,0DAA0D;AAC1D,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,UAAU,CAAC;IAChB,mGAAmG;IACnG,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,UAAU,CAAC;IACjB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,SAAS,GAAI,KAAK,QAAQ,EAAE,MAAM,MAAM,WACJ,CAAC"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spacePath = exports.Selector = void 0;
4
+ const node_path_1 = require("node:path");
5
+ /**
6
+ * `--only`: what a run is allowed to touch.
7
+ *
8
+ * A token matches a slug, a file path or a folder (prefix), a collection, a
9
+ * space's folder or slug, or one of the manifest's parts by name — `site`,
10
+ * `theme`, `settings`, `openapi`, `monitors`. With no `--only`, everything.
11
+ * A run narrowed this way never prunes: "publish just this page" must not
12
+ * read as "and delete every page I did not name".
13
+ */
14
+ class Selector {
15
+ all;
16
+ tokens;
17
+ constructor(only) {
18
+ this.tokens = (only ?? [])
19
+ .map((t) => t.trim().replace(/^\.\//, '').replace(/\/+$/, ''))
20
+ .filter(Boolean);
21
+ this.all = this.tokens.length === 0;
22
+ }
23
+ hit(value) {
24
+ if (!value)
25
+ return false;
26
+ const v = value.replace(/\/+$/, '');
27
+ return this.tokens.some((t) => v === t || v.startsWith(`${t}/`));
28
+ }
29
+ /** A manifest part (`theme`, `monitors`, …) of a space. */
30
+ part(name, space) {
31
+ return this.all || this.tokens.includes(name) || (space ? this.space(space) : false);
32
+ }
33
+ space(spec) {
34
+ return this.all || this.hit(spec.path) || this.hit(spec.space);
35
+ }
36
+ /** A page or post, by slug, by its file (relative to the publish root), or its collection. */
37
+ piece(spec, slug, file, collection) {
38
+ if (this.all || this.space(spec))
39
+ return true;
40
+ const rooted = spec.path ? node_path_1.posix.join(spec.path, file) : file;
41
+ return (this.tokens.includes(slug) ||
42
+ this.hit(rooted) ||
43
+ this.hit(file) ||
44
+ (collection
45
+ ? this.hit(collection.dir) ||
46
+ this.tokens.includes(collection.slug) ||
47
+ this.hit(node_path_1.posix.join(spec.path || '', collection.dir))
48
+ : false));
49
+ }
50
+ }
51
+ exports.Selector = Selector;
52
+ const spacePath = (ctx, rest) => `/orgs/${ctx.org}/spaces/${ctx.spaceId}${rest}`;
53
+ exports.spacePath = spacePath;
54
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/publish/context.ts"],"names":[],"mappings":";;;AAAA,yCAAkC;AAKlC;;;;;;;;GAQG;AACH,MAAa,QAAQ;IACV,GAAG,CAAU;IACL,MAAM,CAAW;IAClC,YAAY,IAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;aACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;aAC7D,MAAM,CAAC,OAAO,CAAC,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IACtC,CAAC;IACO,GAAG,CAAC,KAAyB;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,2DAA2D;IAC3D,IAAI,CAAC,IAAY,EAAE,KAAiB;QAClC,OAAO,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACvF,CAAC;IACD,KAAK,CAAC,IAAe;QACnB,OAAO,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjE,CAAC;IACD,8FAA8F;IAC9F,KAAK,CACH,IAAe,EACf,IAAY,EACZ,IAAY,EACZ,UAA0C;QAE1C,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,OAAO,CACL,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACd,CAAC,UAAU;gBACT,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;oBACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;oBACrC,IAAI,CAAC,GAAG,CAAC,iBAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;gBACvD,CAAC,CAAC,KAAK,CAAC,CACX,CAAC;IACJ,CAAC;CACF;AAzCD,4BAyCC;AAqBM,MAAM,SAAS,GAAG,CAAC,GAAa,EAAE,IAAY,EAAE,EAAE,CACvD,SAAS,GAAG,CAAC,GAAG,WAAW,GAAG,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;AADrC,QAAA,SAAS,aAC4B"}
@@ -0,0 +1,39 @@
1
+ import { type SpaceCtx } from './context';
2
+ import type { DocsPlan } from './docs-plan';
3
+ import type { LocalPage } from './types';
4
+ export interface ImportReport {
5
+ created?: number;
6
+ replaced?: number;
7
+ failed?: number;
8
+ failures?: {
9
+ file: string;
10
+ reason: string;
11
+ }[];
12
+ refused?: string[];
13
+ collisions?: string[];
14
+ brokenLinks?: {
15
+ pageSlug: string;
16
+ url: string;
17
+ }[];
18
+ plan?: {
19
+ slug: string;
20
+ action: string;
21
+ }[];
22
+ }
23
+ /** The text sent for one page: its address declared, links and assets pointed at the web. */
24
+ export declare function payloadOf(ctx: SpaceCtx, page: LocalPage, urls: Map<string, string>): string;
25
+ /** Upload what the given files reference; the map is ref → URL, per file. */
26
+ export declare function uploadAssetsFor(ctx: SpaceCtx, files: string[], existing: Map<string, string>): Promise<Map<string, Map<string, string>>>;
27
+ /** Step 1-4: collections, moves, assets, bodies. Returns the asset URLs it used. */
28
+ export declare function applyDocs(ctx: SpaceCtx, plan: DocsPlan, existingAssets: Map<string, string>): Promise<Map<string, Map<string, string>>>;
29
+ /** A dry run with a token asks the importer itself, so the plan is the server's too. */
30
+ export declare function dryRunImports(ctx: SpaceCtx, plan: DocsPlan): Promise<void>;
31
+ /** `--prune`, last: pages to the trash, then the collections left empty. */
32
+ export declare function applyPrune(ctx: SpaceCtx, plan: DocsPlan): Promise<void>;
33
+ /**
34
+ * Per file: local reference → the URL it already has, for assets uploaded on
35
+ * an earlier run. A reference not uploaded yet keeps its local spelling, which
36
+ * is what makes a plan say "coverUrl would change" — because it would.
37
+ */
38
+ export declare function knownUrls(ctx: SpaceCtx, existing: Map<string, string>): (file: string) => Map<string, string>;
39
+ //# sourceMappingURL=docs-apply.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-apply.d.ts","sourceRoot":"","sources":["../../src/publish/docs-apply.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAmC,SAAS,EAAE,MAAM,SAAS,CAAC;AAiB1E,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAI3F;AAED,6EAA6E;AAC7E,wBAAsB,eAAe,CACnC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAqB3C;AAED,oFAAoF;AACpF,wBAAsB,SAAS,CAC7B,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,QAAQ,EACd,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CA+C3C;AAED,wFAAwF;AACxF,wBAAsB,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChF;AAYD,4EAA4E;AAC5E,wBAAsB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,QAAQ,EACb,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASvC"}