@forumulate/cli 0.3.6 → 0.5.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 (160) hide show
  1. package/README.md +4 -3
  2. package/dist/cli.js +37 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/content/command.d.ts +34 -0
  5. package/dist/content/command.d.ts.map +1 -0
  6. package/dist/content/command.js +225 -0
  7. package/dist/content/command.js.map +1 -0
  8. package/dist/content/library.d.ts +22 -0
  9. package/dist/content/library.d.ts.map +1 -0
  10. package/dist/content/library.js +40 -0
  11. package/dist/content/library.js.map +1 -0
  12. package/dist/content/render.d.ts +15 -0
  13. package/dist/content/render.d.ts.map +1 -0
  14. package/dist/content/render.js +85 -0
  15. package/dist/content/render.js.map +1 -0
  16. package/dist/content/types-gen.d.ts +40 -0
  17. package/dist/content/types-gen.d.ts.map +1 -0
  18. package/dist/content/types-gen.js +200 -0
  19. package/dist/content/types-gen.js.map +1 -0
  20. package/dist/import/coerce.d.ts +34 -0
  21. package/dist/import/coerce.d.ts.map +1 -0
  22. package/dist/import/coerce.js +134 -0
  23. package/dist/import/coerce.js.map +1 -0
  24. package/dist/import/command.d.ts +25 -0
  25. package/dist/import/command.d.ts.map +1 -0
  26. package/dist/import/command.js +127 -0
  27. package/dist/import/command.js.map +1 -0
  28. package/dist/import/config.d.ts +39 -0
  29. package/dist/import/config.d.ts.map +1 -0
  30. package/dist/import/config.js +48 -0
  31. package/dist/import/config.js.map +1 -0
  32. package/dist/import/contentful.d.ts +3 -0
  33. package/dist/import/contentful.d.ts.map +1 -0
  34. package/dist/import/contentful.js +179 -0
  35. package/dist/import/contentful.js.map +1 -0
  36. package/dist/import/disk.d.ts +4 -0
  37. package/dist/import/disk.d.ts.map +1 -0
  38. package/dist/import/disk.js +19 -0
  39. package/dist/import/disk.js.map +1 -0
  40. package/dist/import/engine-locales.d.ts +35 -0
  41. package/dist/import/engine-locales.d.ts.map +1 -0
  42. package/dist/import/engine-locales.js +61 -0
  43. package/dist/import/engine-locales.js.map +1 -0
  44. package/dist/import/engine.d.ts +29 -0
  45. package/dist/import/engine.d.ts.map +1 -0
  46. package/dist/import/engine.js +248 -0
  47. package/dist/import/engine.js.map +1 -0
  48. package/dist/import/media.d.ts +24 -0
  49. package/dist/import/media.d.ts.map +1 -0
  50. package/dist/import/media.js +39 -0
  51. package/dist/import/media.js.map +1 -0
  52. package/dist/import/model-fields.d.ts +22 -0
  53. package/dist/import/model-fields.d.ts.map +1 -0
  54. package/dist/import/model-fields.js +60 -0
  55. package/dist/import/model-fields.js.map +1 -0
  56. package/dist/import/payload/index.d.ts +9 -0
  57. package/dist/import/payload/index.d.ts.map +1 -0
  58. package/dist/import/payload/index.js +129 -0
  59. package/dist/import/payload/index.js.map +1 -0
  60. package/dist/import/report.d.ts +5 -0
  61. package/dist/import/report.d.ts.map +1 -0
  62. package/dist/import/report.js +52 -0
  63. package/dist/import/report.js.map +1 -0
  64. package/dist/import/richtext-core.d.ts +26 -0
  65. package/dist/import/richtext-core.d.ts.map +1 -0
  66. package/dist/import/richtext-core.js +65 -0
  67. package/dist/import/richtext-core.js.map +1 -0
  68. package/dist/import/richtext-html.d.ts +5 -0
  69. package/dist/import/richtext-html.d.ts.map +1 -0
  70. package/dist/import/richtext-html.js +311 -0
  71. package/dist/import/richtext-html.js.map +1 -0
  72. package/dist/import/richtext-json.d.ts +10 -0
  73. package/dist/import/richtext-json.d.ts.map +1 -0
  74. package/dist/import/richtext-json.js +250 -0
  75. package/dist/import/richtext-json.js.map +1 -0
  76. package/dist/import/sanity.d.ts +8 -0
  77. package/dist/import/sanity.d.ts.map +1 -0
  78. package/dist/import/sanity.js +158 -0
  79. package/dist/import/sanity.js.map +1 -0
  80. package/dist/import/strapi-archive.d.ts +6 -0
  81. package/dist/import/strapi-archive.d.ts.map +1 -0
  82. package/dist/import/strapi-archive.js +127 -0
  83. package/dist/import/strapi-archive.js.map +1 -0
  84. package/dist/import/strapi.d.ts +7 -0
  85. package/dist/import/strapi.d.ts.map +1 -0
  86. package/dist/import/strapi.js +185 -0
  87. package/dist/import/strapi.js.map +1 -0
  88. package/dist/import/tar.d.ts +3 -0
  89. package/dist/import/tar.d.ts.map +1 -0
  90. package/dist/import/tar.js +48 -0
  91. package/dist/import/tar.js.map +1 -0
  92. package/dist/import/types.d.ts +157 -0
  93. package/dist/import/types.d.ts.map +1 -0
  94. package/dist/import/types.js +12 -0
  95. package/dist/import/types.js.map +1 -0
  96. package/dist/import/wordpress.d.ts +15 -0
  97. package/dist/import/wordpress.d.ts.map +1 -0
  98. package/dist/import/wordpress.js +147 -0
  99. package/dist/import/wordpress.js.map +1 -0
  100. package/dist/publish/api.d.ts +95 -0
  101. package/dist/publish/api.d.ts.map +1 -0
  102. package/dist/publish/api.js +265 -0
  103. package/dist/publish/api.js.map +1 -0
  104. package/dist/publish/command.d.ts +44 -0
  105. package/dist/publish/command.d.ts.map +1 -0
  106. package/dist/publish/command.js +246 -0
  107. package/dist/publish/command.js.map +1 -0
  108. package/dist/publish/compare.d.ts +45 -0
  109. package/dist/publish/compare.d.ts.map +1 -0
  110. package/dist/publish/compare.js +124 -0
  111. package/dist/publish/compare.js.map +1 -0
  112. package/dist/publish/context.d.ts +46 -0
  113. package/dist/publish/context.d.ts.map +1 -0
  114. package/dist/publish/context.js +54 -0
  115. package/dist/publish/context.js.map +1 -0
  116. package/dist/publish/docs-apply.d.ts +39 -0
  117. package/dist/publish/docs-apply.d.ts.map +1 -0
  118. package/dist/publish/docs-apply.js +178 -0
  119. package/dist/publish/docs-apply.js.map +1 -0
  120. package/dist/publish/docs-plan.d.ts +40 -0
  121. package/dist/publish/docs-plan.d.ts.map +1 -0
  122. package/dist/publish/docs-plan.js +211 -0
  123. package/dist/publish/docs-plan.js.map +1 -0
  124. package/dist/publish/docs-reconcile.d.ts +26 -0
  125. package/dist/publish/docs-reconcile.d.ts.map +1 -0
  126. package/dist/publish/docs-reconcile.js +162 -0
  127. package/dist/publish/docs-reconcile.js.map +1 -0
  128. package/dist/publish/extras.d.ts +25 -0
  129. package/dist/publish/extras.d.ts.map +1 -0
  130. package/dist/publish/extras.js +218 -0
  131. package/dist/publish/extras.js.map +1 -0
  132. package/dist/publish/frontmatter.d.ts +45 -0
  133. package/dist/publish/frontmatter.d.ts.map +1 -0
  134. package/dist/publish/frontmatter.js +265 -0
  135. package/dist/publish/frontmatter.js.map +1 -0
  136. package/dist/publish/manifest.d.ts +5 -0
  137. package/dist/publish/manifest.d.ts.map +1 -0
  138. package/dist/publish/manifest.js +144 -0
  139. package/dist/publish/manifest.js.map +1 -0
  140. package/dist/publish/posts.d.ts +39 -0
  141. package/dist/publish/posts.d.ts.map +1 -0
  142. package/dist/publish/posts.js +350 -0
  143. package/dist/publish/posts.js.map +1 -0
  144. package/dist/publish/rewrite.d.ts +20 -0
  145. package/dist/publish/rewrite.d.ts.map +1 -0
  146. package/dist/publish/rewrite.js +82 -0
  147. package/dist/publish/rewrite.js.map +1 -0
  148. package/dist/publish/scan.d.ts +25 -0
  149. package/dist/publish/scan.d.ts.map +1 -0
  150. package/dist/publish/scan.js +351 -0
  151. package/dist/publish/scan.js.map +1 -0
  152. package/dist/publish/types.d.ts +155 -0
  153. package/dist/publish/types.d.ts.map +1 -0
  154. package/dist/publish/types.js +13 -0
  155. package/dist/publish/types.js.map +1 -0
  156. package/dist/run.d.ts +15 -1
  157. package/dist/run.d.ts.map +1 -1
  158. package/dist/run.js +103 -45
  159. package/dist/run.js.map +1 -1
  160. package/package.json +3 -2
@@ -0,0 +1,95 @@
1
+ import type { ForumulateClient } from '@forumulate/sdk';
2
+ import type { LiveCollection, LivePage, LivePost } from './types';
3
+ /**
4
+ * Every call the publisher makes, through `@forumulate/sdk`.
5
+ *
6
+ * Two things every customer publisher re-learned are built in here once:
7
+ *
8
+ * - A 429 is a pause, not a failure. Reading 38 pages as fast as the event
9
+ * loop allows is indistinguishable from a scraper (an earlier publisher met
10
+ * this after its import had already landed, and reported a crash on work
11
+ * that succeeded). Retries honour `Retry-After`, then back off.
12
+ * - Writes are paced. Per-page reorder is one request per page, and
13
+ * a publisher that fires 400 of them at once spends the rest of the run in
14
+ * 429s.
15
+ *
16
+ * And one that is ours: a dry run CANNOT write. Every mutating method checks
17
+ * `readOnly` and throws, so a planning bug fails loudly instead of quietly
18
+ * publishing.
19
+ */
20
+ export interface ApiOptions {
21
+ client: ForumulateClient;
22
+ /** Whether a token is present — decides authenticated vs public reads. */
23
+ authed: boolean;
24
+ readOnly: boolean;
25
+ /** Minimum gap between writes, ms. */
26
+ paceMs: number;
27
+ /** Multipart upload is the one call the SDK's JSON `request` cannot make. */
28
+ upload?: (path: string, form: FormData) => Promise<unknown>;
29
+ sleep?: (ms: number) => Promise<void>;
30
+ }
31
+ type Q = Record<string, string | number | boolean | undefined>;
32
+ export declare const isUuid: (s: string) => boolean;
33
+ export declare class PublishApi {
34
+ readonly opts: ApiOptions;
35
+ private lastWrite;
36
+ /** Writes this run made, for the summary — and for a test to assert none happened. */
37
+ writes: number;
38
+ constructor(opts: ApiOptions);
39
+ private call;
40
+ get<T>(path: string, query?: Q): Promise<T>;
41
+ post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
42
+ patch<T>(path: string, body: unknown): Promise<T>;
43
+ put<T>(path: string, body: unknown): Promise<T>;
44
+ del<T>(path: string): Promise<T>;
45
+ /** Walk a cursor-paged list to the end. */
46
+ all<T>(path: string, key: string, query?: Q): Promise<T[]>;
47
+ orgId(ref: string): Promise<string>;
48
+ /** The space by id or slug, or null when it does not exist. */
49
+ space(org: string, ref: string): Promise<{
50
+ id: string;
51
+ slug: string;
52
+ type: string;
53
+ orgId: string;
54
+ } | null>;
55
+ /**
56
+ * Collections and pages as they are now. Anonymous reads see only what is
57
+ * published — the plan says so rather than presenting a partial view as whole.
58
+ */
59
+ docs(org: string, space: string): Promise<{
60
+ collections: LiveCollection[];
61
+ pages: LivePage[];
62
+ fieldKeys: string[];
63
+ publicRows: Map<string, Record<string, unknown>>;
64
+ }>;
65
+ /** Every page's markdown, in one paged walk when authenticated. */
66
+ markdownById(org: string, space: string): Promise<Map<string, string>>;
67
+ /** One published page's markdown, the way a reader (or an agent) gets it. */
68
+ publicMarkdown(org: string, space: string, pageId: string): Promise<string | null>;
69
+ pageMeta(org: string, space: string, pageId: string): Promise<Record<string, unknown>>;
70
+ posts(org: string, space: string, type: string): Promise<LivePost[] | null>;
71
+ shape(org: string, space: string): Promise<{
72
+ sections: {
73
+ key: string;
74
+ required?: boolean;
75
+ role?: string;
76
+ schemaProperty?: string;
77
+ }[];
78
+ params: {
79
+ key: string;
80
+ }[];
81
+ }>;
82
+ assets(org: string, space: string): Promise<Map<string, string>>;
83
+ /**
84
+ * Upload once, by content. The stored name carries a hash of the bytes, so a
85
+ * re-run finds the asset it uploaded last time instead of storing a copy per
86
+ * run — and a changed image gets a new name, so no cache serves the old one.
87
+ */
88
+ upload(org: string, space: string, abs: string, existing: Map<string, string>): Promise<string>;
89
+ }
90
+ /** `<12 hex of sha256>-<file name>` — the stored name an asset is found by. */
91
+ export declare function assetName(abs: string): string;
92
+ /** A short, stable key for `Idempotency-Key`: the same write retried is one write. */
93
+ export declare function idemKey(...parts: string[]): string;
94
+ export {};
95
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/publish/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,265 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PublishApi = exports.isUuid = void 0;
4
+ exports.assetName = assetName;
5
+ exports.idemKey = idemKey;
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const node_crypto_1 = require("node:crypto");
9
+ const sleeper = (ms) => new Promise((r) => setTimeout(r, ms));
10
+ const isUuid = (s) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s);
11
+ exports.isUuid = isUuid;
12
+ class PublishApi {
13
+ opts;
14
+ lastWrite = 0;
15
+ /** Writes this run made, for the summary — and for a test to assert none happened. */
16
+ writes = 0;
17
+ constructor(opts) {
18
+ this.opts = opts;
19
+ }
20
+ async call(method, path, body, query, headers) {
21
+ const sleep = this.opts.sleep ?? sleeper;
22
+ const write = method !== 'GET';
23
+ if (write && this.opts.readOnly)
24
+ throw new Error(`dry run tried to write: ${method} ${path}`);
25
+ for (let attempt = 0;; attempt++) {
26
+ if (write) {
27
+ const wait = this.lastWrite + this.opts.paceMs - Date.now();
28
+ if (wait > 0)
29
+ await sleep(wait);
30
+ this.lastWrite = Date.now();
31
+ }
32
+ try {
33
+ const res = await this.opts.client.request(method, path, { body, query, headers });
34
+ if (write)
35
+ this.writes++;
36
+ return res;
37
+ }
38
+ catch (e) {
39
+ const status = e.status;
40
+ // 429 and the transient 5xx a deploy produces; never a 4xx that means "no".
41
+ if ((status === 429 || status === 502 || status === 503) && attempt < 5) {
42
+ await sleep(2000 * (attempt + 1));
43
+ continue;
44
+ }
45
+ throw e;
46
+ }
47
+ }
48
+ }
49
+ get(path, query) {
50
+ return this.call('GET', path, undefined, query);
51
+ }
52
+ post(path, body = {}, headers) {
53
+ return this.call('POST', path, body, undefined, headers);
54
+ }
55
+ patch(path, body) {
56
+ return this.call('PATCH', path, body);
57
+ }
58
+ put(path, body) {
59
+ return this.call('PUT', path, body);
60
+ }
61
+ del(path) {
62
+ return this.call('DELETE', path);
63
+ }
64
+ /** Walk a cursor-paged list to the end. */
65
+ async all(path, key, query = {}) {
66
+ const out = [];
67
+ let cursor;
68
+ for (let i = 0; i < 1000; i++) {
69
+ const res = await this.get(path, {
70
+ ...query,
71
+ ...(cursor ? { cursor } : {}),
72
+ });
73
+ out.push(...(res[key] ?? []));
74
+ const page = res.page;
75
+ cursor = page?.nextCursor ?? undefined;
76
+ if (!(page?.hasMore ?? page?.has_more) || !cursor)
77
+ break;
78
+ }
79
+ return out;
80
+ }
81
+ // ── Resolution ─────────────────────────────────────────────────────────────
82
+ async orgId(ref) {
83
+ if ((0, exports.isUuid)(ref) || !this.opts.authed)
84
+ return ref;
85
+ const { orgs } = await this.get('/orgs');
86
+ const hit = orgs.find((o) => o.slug === ref || o.id === ref);
87
+ if (!hit)
88
+ throw new Error(`No organization "${ref}" for this token (it sees: ${orgs.map((o) => o.slug).join(', ') || 'none'})`);
89
+ return hit.id;
90
+ }
91
+ /** The space by id or slug, or null when it does not exist. */
92
+ async space(org, ref) {
93
+ if (!this.opts.authed) {
94
+ try {
95
+ const r = await this.get(`/public/orgs/${org}/spaces/${ref}`);
96
+ return { ...r.space, orgId: r.organization.id };
97
+ }
98
+ catch (e) {
99
+ if (e.status === 404)
100
+ return null;
101
+ throw e;
102
+ }
103
+ }
104
+ const spaces = await this.all(`/orgs/${org}/spaces`, 'spaces', { limit: 500 });
105
+ const hit = spaces.find((s) => s.id === ref || s.slug === ref);
106
+ return hit ? { ...hit, orgId: org } : null;
107
+ }
108
+ // ── Docs state ─────────────────────────────────────────────────────────────
109
+ /**
110
+ * Collections and pages as they are now. Anonymous reads see only what is
111
+ * published — the plan says so rather than presenting a partial view as whole.
112
+ */
113
+ async docs(org, space) {
114
+ const publicRows = new Map();
115
+ if (!this.opts.authed) {
116
+ const r = await this.get(`/public/orgs/${org}/spaces/${space}`);
117
+ const pages = [];
118
+ const flatten = (rows, collectionId) => {
119
+ for (const p of rows) {
120
+ publicRows.set(String(p.id), p);
121
+ pages.push({
122
+ id: String(p.id),
123
+ slug: String(p.slug),
124
+ title: String(p.title),
125
+ collectionId,
126
+ parentId: p.parentId ?? null,
127
+ sortKey: String(p.sortKey ?? ''),
128
+ published: p.hasLive !== false,
129
+ });
130
+ if (Array.isArray(p.children))
131
+ flatten(p.children, collectionId);
132
+ }
133
+ };
134
+ for (const c of r.collections ?? [])
135
+ flatten((c.pages ?? []), c.id);
136
+ const collections = (r.collections ?? []).map((c, i) => ({
137
+ id: c.id,
138
+ slug: c.slug,
139
+ name: c.name,
140
+ isDefault: Boolean(c.isDefault),
141
+ sortKey: String(i).padStart(6, '0'),
142
+ nav: c.nav,
143
+ }));
144
+ return {
145
+ collections,
146
+ pages,
147
+ fieldKeys: (r.shape?.params ?? []).map((p) => p.key),
148
+ publicRows,
149
+ };
150
+ }
151
+ const [collections, rows, shape] = await Promise.all([
152
+ this.all(`/orgs/${org}/spaces/${space}/collections`, 'collections', {
153
+ limit: 500,
154
+ }),
155
+ this.all(`/orgs/${org}/spaces/${space}/pages`, 'pages', { limit: 1000 }),
156
+ this.get(`/orgs/${org}/spaces/${space}/shape`).catch(() => ({ shape: undefined })),
157
+ ]);
158
+ // Versions and translations are clones carrying the same slug; the
159
+ // publisher writes the primary, so it reads the primary.
160
+ const pages = rows
161
+ .filter((p) => (p.versionKey ?? 'default') === 'default' && (p.locale ?? 'default') === 'default')
162
+ .map((p) => ({
163
+ ...p,
164
+ published: p.status ? p.status === 'published' : p.published !== false,
165
+ }));
166
+ return {
167
+ collections,
168
+ pages,
169
+ fieldKeys: (shape.shape?.params ?? []).map((p) => p.key),
170
+ publicRows,
171
+ };
172
+ }
173
+ /** Every page's markdown, in one paged walk when authenticated. */
174
+ async markdownById(org, space) {
175
+ const out = new Map();
176
+ if (!this.opts.authed)
177
+ return out;
178
+ const items = await this.all(`/orgs/${org}/spaces/${space}/items`, 'items', { limit: 50, include: 'body' });
179
+ for (const i of items)
180
+ if (typeof i.markdown === 'string')
181
+ out.set(i.id, i.markdown);
182
+ return out;
183
+ }
184
+ /** One published page's markdown, the way a reader (or an agent) gets it. */
185
+ async publicMarkdown(org, space, pageId) {
186
+ try {
187
+ const res = await this.opts.client.request('GET', `/public/orgs/${org}/spaces/${space}/pages/${pageId}.md`, { raw: true });
188
+ return await res.text();
189
+ }
190
+ catch (e) {
191
+ const status = e.status;
192
+ if (status === 404)
193
+ return null;
194
+ if (status === 429) {
195
+ await (this.opts.sleep ?? sleeper)(3000);
196
+ return this.publicMarkdown(org, space, pageId);
197
+ }
198
+ throw e;
199
+ }
200
+ }
201
+ async pageMeta(org, space, pageId) {
202
+ const r = await this.get(`/orgs/${org}/spaces/${space}/pages/${pageId}/metadata`);
203
+ return r.metadata ?? {};
204
+ }
205
+ // ── Posts state ────────────────────────────────────────────────────────────
206
+ async posts(org, space, type) {
207
+ if (this.opts.authed) {
208
+ const items = await this.all(`/orgs/${org}/spaces/${space}/items`, 'items', { limit: 50, include: 'sections,body' });
209
+ return items.filter((i) => i.slug);
210
+ }
211
+ if (type !== 'BLOG')
212
+ return null;
213
+ const rows = await this.all(`/public/orgs/${org}/spaces/${space}/blog`, 'articles', { limit: 100 });
214
+ return rows.map((r) => ({ ...r, published: true }));
215
+ }
216
+ async shape(org, space) {
217
+ if (!this.opts.authed) {
218
+ const r = await this.get(`/public/orgs/${org}/spaces/${space}`).catch(() => ({ shape: undefined }));
219
+ return { sections: r.shape?.sections ?? [], params: r.shape?.params ?? [] };
220
+ }
221
+ const r = await this.get(`/orgs/${org}/spaces/${space}/shape`);
222
+ return { sections: r.shape?.sections ?? [], params: r.shape?.params ?? [] };
223
+ }
224
+ // ── Assets ─────────────────────────────────────────────────────────────────
225
+ async assets(org, space) {
226
+ if (!this.opts.authed)
227
+ return new Map();
228
+ const rows = await this.all(`/orgs/${org}/spaces/${space}/assets`, 'assets', { limit: 500 });
229
+ return new Map(rows.map((a) => [a.filename, a.url]));
230
+ }
231
+ /**
232
+ * Upload once, by content. The stored name carries a hash of the bytes, so a
233
+ * re-run finds the asset it uploaded last time instead of storing a copy per
234
+ * run — and a changed image gets a new name, so no cache serves the old one.
235
+ */
236
+ async upload(org, space, abs, existing) {
237
+ const name = assetName(abs);
238
+ const known = existing.get(name);
239
+ if (known)
240
+ return known;
241
+ if (this.opts.readOnly)
242
+ throw new Error(`dry run tried to upload ${abs}`);
243
+ if (!this.opts.upload)
244
+ throw new Error('asset upload is not available in this environment');
245
+ const form = new FormData();
246
+ form.set('file', new Blob([(0, node_fs_1.readFileSync)(abs)]), name);
247
+ const res = (await this.opts.upload(`/orgs/${org}/spaces/${space}/assets`, form));
248
+ if (!res.asset?.url)
249
+ throw new Error(`upload of ${abs} answered without an asset url`);
250
+ this.writes++;
251
+ existing.set(name, res.asset.url);
252
+ return res.asset.url;
253
+ }
254
+ }
255
+ exports.PublishApi = PublishApi;
256
+ /** `<12 hex of sha256>-<file name>` — the stored name an asset is found by. */
257
+ function assetName(abs) {
258
+ const hash = (0, node_crypto_1.createHash)('sha256').update((0, node_fs_1.readFileSync)(abs)).digest('hex').slice(0, 12);
259
+ return `${hash}-${(0, node_path_1.basename)(abs).replace(/[^\w.-]+/g, '-')}`;
260
+ }
261
+ /** A short, stable key for `Idempotency-Key`: the same write retried is one write. */
262
+ function idemKey(...parts) {
263
+ return (0, node_crypto_1.createHash)('sha256').update(parts.join('\u0000')).digest('hex').slice(0, 40);
264
+ }
265
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/publish/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { ForumulateClient } from '@forumulate/sdk';
2
+ /**
3
+ * `forumulate publish <folder>` — a folder of Markdown, and optionally a
4
+ * manifest, made into a live presence; and the same command run again changes
5
+ * only what changed.
6
+ *
7
+ * Four customers wrote this themselves before we did (a Python script, two
8
+ * converter-plus-publisher pairs, ~400 lines of TypeScript), and every one of
9
+ * them did the same seven things: front matter to collections and pages,
10
+ * idempotent re-runs, prune, reorder, read back, dry run, the OpenAPI
11
+ * reference. That is the spec of this command.
12
+ *
13
+ * Three modes over ONE planner: `--dry-run` plans against the live space and
14
+ * writes nothing (a token is optional — without one it reads the public
15
+ * space); a real run applies the plan; and then the planner runs once more
16
+ * against what is now live, and anything it would still change is reported as
17
+ * a failure. That last pass is the read-back: a publish that answered 200 and
18
+ * changed nothing is the failure every one of those scripts was eventually
19
+ * written to catch.
20
+ */
21
+ export interface PublishOptions {
22
+ folder: string;
23
+ org?: string;
24
+ space?: string;
25
+ manifest?: string;
26
+ dryRun: boolean;
27
+ prune: boolean;
28
+ force: boolean;
29
+ verify: boolean;
30
+ only?: string[];
31
+ paceMs: number;
32
+ json: boolean;
33
+ }
34
+ export interface PublishDeps {
35
+ client: ForumulateClient;
36
+ authed: boolean;
37
+ out: (line: string) => void;
38
+ err: (line: string) => void;
39
+ upload?: (path: string, form: FormData) => Promise<unknown>;
40
+ env?: NodeJS.ProcessEnv;
41
+ sleep?: (ms: number) => Promise<void>;
42
+ }
43
+ export declare function runPublish(opts: PublishOptions, deps: PublishDeps): Promise<number>;
44
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/publish/command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAYxD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAKD,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA+IzF"}