@letterstory/cli 0.10.0 → 0.12.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.
- package/lib/cli.mjs +21 -7
- package/lib/commands/connectors.mjs +23 -1
- package/lib/commands/onboard.mjs +38 -0
- package/package.json +1 -1
package/lib/cli.mjs
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from "./commands.mjs";
|
|
41
41
|
|
|
42
42
|
// Keep in sync with cli/package.json.
|
|
43
|
-
export const VERSION = "0.
|
|
43
|
+
export const VERSION = "0.12.0";
|
|
44
44
|
|
|
45
45
|
// Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
|
|
46
46
|
// can't accidentally swallow the id as --json's value.
|
|
@@ -203,6 +203,11 @@ Connectors:
|
|
|
203
203
|
[--confirm-missing-target] re-publish even though
|
|
204
204
|
the item was deleted/unpublished on the provider
|
|
205
205
|
connectors status --connector <connector> --publish-id <id>
|
|
206
|
+
connectors pull [--collection <uuid>] [--provider <webflow|framer|sanity|contentful>]
|
|
207
|
+
Pull existing posts FROM a connected CMS into a
|
|
208
|
+
collection, reconciling (adopt/update/create/orphan).
|
|
209
|
+
--collection for a bound collection, --provider to
|
|
210
|
+
auto-resolve, or both to wire an unbound collection.
|
|
206
211
|
|
|
207
212
|
Strategy & onboarding:
|
|
208
213
|
strategy company get | set [--name] [--domain] [--manifesto <text>|--manifesto-file <path>]
|
|
@@ -270,14 +275,23 @@ Phantom onboarding recipe (domain -> live phantom blog with first posts):
|
|
|
270
275
|
|
|
271
276
|
Collection onboarding (your OWN blog, on your org's domain — no provisioning):
|
|
272
277
|
${bin === "phantom" ? "onboard" : "phantom-onboard"} collection [--collection <uuid>] [--name "<collection name>"]
|
|
273
|
-
[--about "the direction"] [--sitemap <url>] [--watch]
|
|
278
|
+
[--about "the direction"] [--sitemap <url>] [--cms <provider>] [--watch]
|
|
274
279
|
Import the existing blog from its sitemap
|
|
275
280
|
(auto-discovered from the org's domain unless
|
|
276
|
-
--sitemap pins one)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
+
--sitemap pins one) OR from a connected CMS with
|
|
282
|
+
--cms <webflow|framer|sanity|contentful>, then
|
|
283
|
+
derive content areas + series, build the topic
|
|
284
|
+
map, bind SEO demand, and stock Headlines & Queue.
|
|
285
|
+
Omit --collection to create a fresh one (--name,
|
|
286
|
+
default Blog). The Planner stays OFF (manual approval).
|
|
287
|
+
${bin === "phantom" ? "onboard" : "phantom-onboard"} sync-sitemap --collection <uuid>
|
|
288
|
+
Re-check an already-onboarded blog's sitemap
|
|
289
|
+
right now instead of waiting for its cadence
|
|
290
|
+
(default every 14 days). Skips pages whose
|
|
291
|
+
<lastmod> hasn't moved, imports new posts,
|
|
292
|
+
refreshes changed ones. Only for collections
|
|
293
|
+
with no CMS connected — once one is, use the
|
|
294
|
+
CMS pull/reconcile path instead.
|
|
281
295
|
--watch polls to completion, printing each
|
|
282
296
|
review note as it lands.
|
|
283
297
|
|
|
@@ -17,8 +17,11 @@ export async function cmdConnectors(ctx) {
|
|
|
17
17
|
return connectorsPublish(rest);
|
|
18
18
|
case "status":
|
|
19
19
|
return connectorsStatus(rest);
|
|
20
|
+
case "pull":
|
|
21
|
+
case "import":
|
|
22
|
+
return connectorsPull(rest);
|
|
20
23
|
default:
|
|
21
|
-
throw new CliError(`Unknown connectors subcommand: ${sub ?? "(none)"}. Try: list, publish, status`);
|
|
24
|
+
throw new CliError(`Unknown connectors subcommand: ${sub ?? "(none)"}. Try: list, publish, status, pull`);
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
|
|
@@ -59,3 +62,22 @@ async function connectorsStatus(ctx) {
|
|
|
59
62
|
printResult(io, flags, result);
|
|
60
63
|
return 0;
|
|
61
64
|
}
|
|
65
|
+
|
|
66
|
+
async function connectorsPull(ctx) {
|
|
67
|
+
const { client, flags, io } = ctx;
|
|
68
|
+
// Dual key: --collection (a CMS-bound collection), or --provider (resolve/wire),
|
|
69
|
+
// or both (--provider wires an unbound --collection first). At least one required.
|
|
70
|
+
const collectionId = flagStr(flags.collection);
|
|
71
|
+
const provider = flagStr(flags.provider);
|
|
72
|
+
if (!collectionId && !provider) {
|
|
73
|
+
throw new CliError("Pass --collection <id> and/or --provider <webflow|framer|sanity|contentful>");
|
|
74
|
+
}
|
|
75
|
+
const args = compact({ collection_id: collectionId, provider });
|
|
76
|
+
const result = await client.callTool("import_from_cms", args);
|
|
77
|
+
ok(
|
|
78
|
+
ctx,
|
|
79
|
+
`Pulled from ${result?.provider ?? provider ?? "CMS"} into collection ${result?.collection_id ?? collectionId ?? ""}.`
|
|
80
|
+
);
|
|
81
|
+
printResult(io, flags, result);
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
package/lib/commands/onboard.mjs
CHANGED
|
@@ -140,6 +140,8 @@ async function cmdOnboardCollection(ctx) {
|
|
|
140
140
|
collection_name: flagStr(flags.name),
|
|
141
141
|
direction: flagStr(flags.about) ?? flagStr(flags.direction),
|
|
142
142
|
sitemap_url: flagStr(flags.sitemap),
|
|
143
|
+
// Source the existing blog from a connected CMS instead of a sitemap.
|
|
144
|
+
cms_provider: flagStr(flags.cms),
|
|
143
145
|
});
|
|
144
146
|
|
|
145
147
|
ok(ctx, "Starting collection onboarding…");
|
|
@@ -182,12 +184,48 @@ async function cmdOnboardCollection(ctx) {
|
|
|
182
184
|
return 0;
|
|
183
185
|
}
|
|
184
186
|
|
|
187
|
+
// `onboard sync-sitemap --collection <uuid>` — the periodic-refresh sibling: re-check a
|
|
188
|
+
// collection's sitemap right now instead of waiting for its cadence
|
|
189
|
+
// (collections.sitemap_sync_cadence_days). One-shot, no polling — the underlying work is
|
|
190
|
+
// bounded per run, so it returns synchronously.
|
|
191
|
+
async function cmdOnboardSyncSitemap(ctx) {
|
|
192
|
+
const { client, flags } = ctx;
|
|
193
|
+
const collectionId = flagStr(flags.collection);
|
|
194
|
+
if (!collectionId) {
|
|
195
|
+
throw new CliError("onboard sync-sitemap requires --collection <uuid>.");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
ok(ctx, "Re-checking the sitemap…");
|
|
199
|
+
const result = await client.callTool("sync_collection_sitemap", { collection_id: collectionId });
|
|
200
|
+
|
|
201
|
+
printResult(ctx.io, flags, result, (r) =>
|
|
202
|
+
[
|
|
203
|
+
`Sitemap sync complete — ${r.checked} post${r.checked === 1 ? "" : "s"} checked.`,
|
|
204
|
+
` created: ${r.created}`,
|
|
205
|
+
` updated: ${r.updated}`,
|
|
206
|
+
` unchanged: ${r.unchanged} (skipped — <lastmod> hadn't moved)`,
|
|
207
|
+
r.skipped ? ` skipped: ${r.skipped} (nothing readable)` : null,
|
|
208
|
+
r.failed
|
|
209
|
+
? ` failed: ${r.failed}${r.failure_reasons?.length ? ` (${r.failure_reasons.join("; ")})` : ""}`
|
|
210
|
+
: null,
|
|
211
|
+
r.truncated ? ` capped this run — rerun (or wait for the cadence) to catch up the rest.` : null,
|
|
212
|
+
]
|
|
213
|
+
.filter(Boolean)
|
|
214
|
+
.join("\n")
|
|
215
|
+
);
|
|
216
|
+
return 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
185
219
|
export async function cmdOnboard(ctx) {
|
|
186
220
|
const { client, flags, io } = ctx;
|
|
187
221
|
// `onboard collection …` — the client-blog variant (no <domain>; org from the key).
|
|
188
222
|
if (ctx.positionals[0] === "collection") {
|
|
189
223
|
return cmdOnboardCollection({ ...ctx, positionals: ctx.positionals.slice(1) });
|
|
190
224
|
}
|
|
225
|
+
// `onboard sync-sitemap --collection <uuid>` — refresh an already-onboarded blog.
|
|
226
|
+
if (ctx.positionals[0] === "sync-sitemap") {
|
|
227
|
+
return cmdOnboardSyncSitemap({ ...ctx, positionals: ctx.positionals.slice(1) });
|
|
228
|
+
}
|
|
191
229
|
const domain = requirePositional(ctx.positionals, 0, "domain");
|
|
192
230
|
const overrides = overridesFromFlags(flags);
|
|
193
231
|
|