@forumulate/cli 0.9.0 → 0.10.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/README.md +3 -3
- package/dist/api/args.d.ts.map +1 -1
- package/dist/api/args.js +1 -0
- package/dist/api/args.js.map +1 -1
- package/dist/api/command.d.ts +1 -1
- package/dist/api/command.d.ts.map +1 -1
- package/dist/api/command.js +86 -11
- package/dist/api/command.js.map +1 -1
- package/dist/api/http.d.ts +8 -0
- package/dist/api/http.d.ts.map +1 -1
- package/dist/api/http.js +3 -2
- package/dist/api/http.js.map +1 -1
- package/dist/api/live-spec.d.ts +48 -0
- package/dist/api/live-spec.d.ts.map +1 -0
- package/dist/api/live-spec.js +72 -0
- package/dist/api/live-spec.js.map +1 -0
- package/dist/api/operations.json +1 -1
- package/dist/api/request.d.ts.map +1 -1
- package/dist/api/request.js +25 -1
- package/dist/api/request.js.map +1 -1
- package/dist/api/send.d.ts +10 -1
- package/dist/api/send.d.ts.map +1 -1
- package/dist/api/send.js +14 -3
- package/dist/api/send.js.map +1 -1
- package/dist/api/slim.d.ts +14 -0
- package/dist/api/slim.d.ts.map +1 -0
- package/dist/api/slim.js +174 -0
- package/dist/api/slim.js.map +1 -0
- package/dist/cache-command.d.ts +12 -0
- package/dist/cache-command.d.ts.map +1 -0
- package/dist/cache-command.js +93 -0
- package/dist/cache-command.js.map +1 -0
- package/dist/check/command.d.ts +48 -0
- package/dist/check/command.d.ts.map +1 -0
- package/dist/check/command.js +256 -0
- package/dist/check/command.js.map +1 -0
- package/dist/check/external.d.ts +66 -0
- package/dist/check/external.d.ts.map +1 -0
- package/dist/check/external.js +177 -0
- package/dist/check/external.js.map +1 -0
- package/dist/check/markdown-links.d.ts +38 -0
- package/dist/check/markdown-links.d.ts.map +1 -0
- package/dist/check/markdown-links.js +166 -0
- package/dist/check/markdown-links.js.map +1 -0
- package/dist/cli.js +42 -7
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +1 -0
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +6 -2
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/groups-api.d.ts.map +1 -1
- package/dist/commands/groups-api.js +20 -2
- package/dist/commands/groups-api.js.map +1 -1
- package/dist/commands/groups-docs.d.ts.map +1 -1
- package/dist/commands/groups-docs.js +8 -2
- package/dist/commands/groups-docs.js.map +1 -1
- package/dist/commands/groups-jobs.d.ts +10 -0
- package/dist/commands/groups-jobs.d.ts.map +1 -0
- package/dist/commands/groups-jobs.js +89 -0
- package/dist/commands/groups-jobs.js.map +1 -0
- package/dist/commands/groups-org.d.ts.map +1 -1
- package/dist/commands/groups-org.js +59 -2
- package/dist/commands/groups-org.js.map +1 -1
- package/dist/commands/groups-site.d.ts.map +1 -1
- package/dist/commands/groups-site.js +33 -3
- package/dist/commands/groups-site.js.map +1 -1
- package/dist/commands/groups-spaces.d.ts.map +1 -1
- package/dist/commands/groups-spaces.js +11 -5
- package/dist/commands/groups-spaces.js.map +1 -1
- package/dist/commands/groups-types.d.ts.map +1 -1
- package/dist/commands/groups-types.js +74 -0
- package/dist/commands/groups-types.js.map +1 -1
- package/dist/commands/groups.d.ts.map +1 -1
- package/dist/commands/groups.js +2 -0
- package/dist/commands/groups.js.map +1 -1
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +18 -3
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/job-wait.d.ts +64 -0
- package/dist/commands/job-wait.d.ts.map +1 -0
- package/dist/commands/job-wait.js +91 -0
- package/dist/commands/job-wait.js.map +1 -0
- package/dist/commands/resource.d.ts +19 -0
- package/dist/commands/resource.d.ts.map +1 -1
- package/dist/commands/resource.js +65 -3
- package/dist/commands/resource.js.map +1 -1
- package/dist/content/library.d.ts +8 -0
- package/dist/content/library.d.ts.map +1 -1
- package/dist/content/library.js +10 -2
- package/dist/content/library.js.map +1 -1
- package/dist/credentials.d.ts +43 -4
- package/dist/credentials.d.ts.map +1 -1
- package/dist/credentials.js +67 -4
- package/dist/credentials.js.map +1 -1
- package/dist/doctor/address-checks.d.ts +56 -0
- package/dist/doctor/address-checks.d.ts.map +1 -0
- package/dist/doctor/address-checks.js +183 -0
- package/dist/doctor/address-checks.js.map +1 -0
- package/dist/doctor/boilerplate.d.ts +33 -0
- package/dist/doctor/boilerplate.d.ts.map +1 -0
- package/dist/doctor/boilerplate.js +78 -0
- package/dist/doctor/boilerplate.js.map +1 -0
- package/dist/doctor/command.d.ts +18 -0
- package/dist/doctor/command.d.ts.map +1 -0
- package/dist/doctor/command.js +234 -0
- package/dist/doctor/command.js.map +1 -0
- package/dist/doctor/crawl.d.ts +49 -0
- package/dist/doctor/crawl.d.ts.map +1 -0
- package/dist/doctor/crawl.js +210 -0
- package/dist/doctor/crawl.js.map +1 -0
- package/dist/doctor/extended.d.ts +52 -0
- package/dist/doctor/extended.d.ts.map +1 -0
- package/dist/doctor/extended.js +150 -0
- package/dist/doctor/extended.js.map +1 -0
- package/dist/doctor/page-checks.d.ts +42 -0
- package/dist/doctor/page-checks.d.ts.map +1 -0
- package/dist/doctor/page-checks.js +200 -0
- package/dist/doctor/page-checks.js.map +1 -0
- package/dist/doctor/probe.d.ts +63 -0
- package/dist/doctor/probe.d.ts.map +1 -0
- package/dist/doctor/probe.js +170 -0
- package/dist/doctor/probe.js.map +1 -0
- package/dist/doctor/reader-auth-atlas.d.ts +18 -0
- package/dist/doctor/reader-auth-atlas.d.ts.map +1 -0
- package/dist/doctor/reader-auth-atlas.js +50 -0
- package/dist/doctor/reader-auth-atlas.js.map +1 -0
- package/dist/doctor/robots-params.d.ts +36 -0
- package/dist/doctor/robots-params.d.ts.map +1 -0
- package/dist/doctor/robots-params.js +97 -0
- package/dist/doctor/robots-params.js.map +1 -0
- package/dist/doctor/site.d.ts +42 -0
- package/dist/doctor/site.d.ts.map +1 -0
- package/dist/doctor/site.js +82 -0
- package/dist/doctor/site.js.map +1 -0
- package/dist/doctor.d.ts +21 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +94 -3
- package/dist/doctor.js.map +1 -1
- package/dist/exit-codes.d.ts +40 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +66 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/help-commands.d.ts +13 -0
- package/dist/help-commands.d.ts.map +1 -0
- package/dist/help-commands.js +215 -0
- package/dist/help-commands.js.map +1 -0
- package/dist/help.d.ts +1 -1
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +57 -11
- package/dist/help.js.map +1 -1
- package/dist/io.d.ts +33 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +81 -0
- package/dist/io.js.map +1 -0
- package/dist/preview-comment.d.ts +20 -0
- package/dist/preview-comment.d.ts.map +1 -0
- package/dist/preview-comment.js +88 -0
- package/dist/preview-comment.js.map +1 -0
- package/dist/publish/about.d.ts +23 -0
- package/dist/publish/about.d.ts.map +1 -0
- package/dist/publish/about.js +66 -0
- package/dist/publish/about.js.map +1 -0
- package/dist/publish/command.d.ts +20 -0
- package/dist/publish/command.d.ts.map +1 -1
- package/dist/publish/command.js +97 -4
- package/dist/publish/command.js.map +1 -1
- package/dist/publish/context.d.ts +8 -0
- package/dist/publish/context.d.ts.map +1 -1
- package/dist/publish/context.js.map +1 -1
- package/dist/publish/docs-apply.d.ts.map +1 -1
- package/dist/publish/docs-apply.js +13 -1
- package/dist/publish/docs-apply.js.map +1 -1
- package/dist/publish/extras.d.ts +10 -0
- package/dist/publish/extras.d.ts.map +1 -1
- package/dist/publish/extras.js +54 -2
- package/dist/publish/extras.js.map +1 -1
- package/dist/publish/manifest.d.ts.map +1 -1
- package/dist/publish/manifest.js +27 -2
- package/dist/publish/manifest.js.map +1 -1
- package/dist/publish/preview.d.ts +56 -0
- package/dist/publish/preview.d.ts.map +1 -0
- package/dist/publish/preview.js +133 -0
- package/dist/publish/preview.js.map +1 -0
- package/dist/publish/redirects.d.ts +13 -0
- package/dist/publish/redirects.d.ts.map +1 -0
- package/dist/publish/redirects.js +154 -0
- package/dist/publish/redirects.js.map +1 -0
- package/dist/publish/studio-edits.d.ts +25 -0
- package/dist/publish/studio-edits.d.ts.map +1 -0
- package/dist/publish/studio-edits.js +53 -0
- package/dist/publish/studio-edits.js.map +1 -0
- package/dist/publish/types.d.ts +22 -1
- package/dist/publish/types.d.ts.map +1 -1
- package/dist/publish-command.d.ts +55 -0
- package/dist/publish-command.d.ts.map +1 -0
- package/dist/publish-command.js +197 -0
- package/dist/publish-command.js.map +1 -0
- package/dist/run.d.ts +3 -10
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +122 -110
- package/dist/run.js.map +1 -1
- package/dist/translations/target.d.ts.map +1 -1
- package/dist/translations/target.js +2 -2
- package/dist/translations/target.js.map +1 -1
- package/dist/validate.d.ts +39 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +166 -0
- package/dist/validate.js.map +1 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/dist/whoami.d.ts +41 -0
- package/dist/whoami.d.ts.map +1 -0
- package/dist/whoami.js +161 -0
- package/dist/whoami.js.map +1 -0
- package/package.json +2 -2
- package/dist/publish-dir.d.ts +0 -54
- package/dist/publish-dir.d.ts.map +0 -1
- package/dist/publish-dir.js +0 -119
- package/dist/publish-dir.js.map +0 -1
package/dist/help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,eAAO,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,eAAO,MAAM,IAAI,0iaAuMhB,CAAC"}
|
package/dist/help.js
CHANGED
|
@@ -12,19 +12,24 @@ Commands:
|
|
|
12
12
|
command stops needing FORUMULATE_TOKEN in
|
|
13
13
|
the environment
|
|
14
14
|
logout Forget the stored token
|
|
15
|
-
whoami
|
|
15
|
+
whoami [--json] Who you are, and WHICH token: its source (--token,
|
|
16
|
+
FORUMULATE_TOKEN or credentials.json), id, name,
|
|
17
|
+
last 4, expiry, narrowing and the API base
|
|
18
|
+
auth status [--json] The same report, for scripts
|
|
16
19
|
config set|get|unset|list Defaults: org, space, library, api-version
|
|
17
20
|
(\`forumulate config set org acme\`)
|
|
18
21
|
|
|
19
22
|
Every API operation:
|
|
20
23
|
api list [--tag t] [--search w] Discover operations and their summaries
|
|
24
|
+
[--refresh] ...from the live API's spec, not the bundled one
|
|
21
25
|
api describe <operationId> Parameters and body schema, as flags
|
|
22
26
|
api <operationId> [args] [flags] Call it: --<param> value, --data @f.json,
|
|
23
27
|
api <METHOD> <path> [flags] --field a.b=v, --paginate, --json
|
|
24
28
|
|
|
25
29
|
Resources (each: <group> --help lists its verbs and the operation each calls):
|
|
26
30
|
Org: orgs | members | invites | groups | roles | service-accounts (bots)
|
|
27
|
-
tokens (pats) |
|
|
31
|
+
tokens (pats) | keys | integration-tokens (int-tokens)
|
|
32
|
+
webhooks | extensions | audit
|
|
28
33
|
Spaces: spaces | snapshots | shape | domains | assets | space-types (types)
|
|
29
34
|
Docs: items (pages) | docs | collections | versions | change-requests (crs)
|
|
30
35
|
openapi | sdks | github (git)
|
|
@@ -32,11 +37,14 @@ Resources (each: <group> --help lists its verbs and the operation each calls):
|
|
|
32
37
|
careers | forms (blog/forum/changelog/status: translations …)
|
|
33
38
|
CMS: libraries | entries | media | releases | environments (envs)
|
|
34
39
|
Site: theme | sites | reader
|
|
40
|
+
Jobs: jobs | backups | imports | manifest (starters take --wait [--timeout s])
|
|
35
41
|
search <query...> [--org] e.g. spaces create Docs --slug docs --type DOCS
|
|
36
42
|
items create --space docs --file a.md --publish
|
|
37
43
|
docs schedule set <pageId> <when> --space docs
|
|
38
44
|
webhooks deliveries <id>; webhooks replay <id> <d>
|
|
39
45
|
--out <file> where a file answer goes (SDK archive, PDF, CSV export)
|
|
46
|
+
cache purge --space <s> [--page p] Drop cached copies (web tier + every CDN); deletes
|
|
47
|
+
nothing
|
|
40
48
|
completion bash|zsh|fish Shell completion script
|
|
41
49
|
|
|
42
50
|
Older forms, unchanged:
|
|
@@ -48,7 +56,8 @@ Older forms, unchanged:
|
|
|
48
56
|
dev <folder> Preview a folder of Markdown locally, rendered
|
|
49
57
|
by your space's own renderer; reloads on save.
|
|
50
58
|
--org <id> --space <id> [--port 4321] [--site <your docs URL>]
|
|
51
|
-
publish <folder>
|
|
59
|
+
publish <folder> --org <o> --space <s>
|
|
60
|
+
Publish a folder of Markdown: one folder per
|
|
52
61
|
collection, front matter, assets, order,
|
|
53
62
|
and a forumulate.yaml manifest for space,
|
|
54
63
|
site, theme, OpenAPI and monitors. Re-runs
|
|
@@ -63,6 +72,12 @@ Older forms, unchanged:
|
|
|
63
72
|
--no-verify skip the read-back --pace <ms> gap between writes
|
|
64
73
|
--manifest <file> a manifest somewhere else
|
|
65
74
|
--diff print the changed paragraphs and fields of each update
|
|
75
|
+
--purge page|space|none what to drop from the cache (default page),
|
|
76
|
+
reported per CDN
|
|
77
|
+
--json one summary: created, updated, unchanged, trashed, purged,
|
|
78
|
+
verify, diffUrl (the run is recorded; publish.completed fires)
|
|
79
|
+
Pages edited in the studio since the last publish are not overwritten
|
|
80
|
+
without --force. Full reference: forumulate publish --help
|
|
66
81
|
sync <folder> Content as code: the same folder publish,
|
|
67
82
|
PLAN BY DEFAULT. Posts (blog), pages
|
|
68
83
|
(docs, custom, legal), FAQ questions,
|
|
@@ -76,8 +91,15 @@ Older forms, unchanged:
|
|
|
76
91
|
--diff print the changed paragraphs and fields of each update
|
|
77
92
|
--org, --space, --only, --force, --no-verify, --pace, --manifest, --json
|
|
78
93
|
as for publish
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
check links [folder] Broken internal links, #anchors, pictures and
|
|
95
|
+
(--external) outside links in a folder, before
|
|
96
|
+
publishing; exit 1 when any is broken
|
|
97
|
+
--space <s> [--org <o>] the same report for a published space
|
|
98
|
+
--allow-redirect <hosts> --ignore <text> --json
|
|
99
|
+
publish <folder> --preview <name> Send the change to a preview link instead of
|
|
100
|
+
publishing it (--comment posts it on the PR)
|
|
101
|
+
publish <orgId> <spaceId> <pageId> (deprecated) Publish a page — use items publish
|
|
102
|
+
publish <orgId> <spaceId> <dir> (deprecated) — use publish <dir> --org --space
|
|
81
103
|
domains <orgId> <spaceId> List this space's domains and their state
|
|
82
104
|
domains verify <orgId> <spaceId> <hostname>
|
|
83
105
|
Re-run verification and say what is missing
|
|
@@ -126,14 +148,21 @@ Older forms, unchanged:
|
|
|
126
148
|
provider status|connect|disconnect your DeepL key (DEEPL_API_KEY)
|
|
127
149
|
conformance <collectionUrl> Run the Content Sync Protocol suite against
|
|
128
150
|
any platform's collection endpoint
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
validate [dir] Check forumulate.yaml, front matter and $schema
|
|
152
|
+
files against the published schemas, with
|
|
153
|
+
did-you-mean hints. --json; exit 2 if invalid
|
|
154
|
+
doctor <readerUrl> | --site <s> Check a live site from the outside: health,
|
|
155
|
+
canonical on both addresses, sitemap, cache
|
|
156
|
+
consistency, root redirect, descriptions,
|
|
157
|
+
llms.txt, favicon, consent tag, white-label
|
|
158
|
+
leaks. --json; exit 1 on any FAIL
|
|
159
|
+
help [command] Show this help, or a command's own
|
|
160
|
+
(every command also takes --help)
|
|
133
161
|
|
|
134
162
|
Environment:
|
|
135
163
|
FORUMULATE_TOKEN Personal Access Token (Bearer). Overrides a stored one, so
|
|
136
|
-
CI keeps working exactly as it did
|
|
164
|
+
CI keeps working exactly as it did; --token overrides it.
|
|
165
|
+
Mint one at
|
|
137
166
|
https://forumulate.com/account/tokens
|
|
138
167
|
FORUMULATE_URL The site (default https://forumulate.com); the API is its
|
|
139
168
|
/api, i.e. https://forumulate.com/api. A value already
|
|
@@ -150,10 +179,27 @@ Environment:
|
|
|
150
179
|
The SDK (ForumulateClient.fromEnv) and the MCP server (@forumulate/mcp) read
|
|
151
180
|
the same variables. Guide: https://forumulate.com/guides/api-tokens-and-scopes
|
|
152
181
|
|
|
182
|
+
Every FORUMULATE_* variable not listed above is reported (with the one you
|
|
183
|
+
probably meant) by \`forumulate whoami\` and on any authentication failure.
|
|
184
|
+
|
|
153
185
|
Flags:
|
|
154
|
-
--json Emit raw JSON instead of a formatted summary
|
|
186
|
+
--json Emit raw JSON instead of a formatted summary (stdout only;
|
|
187
|
+
progress and warnings go to stderr)
|
|
188
|
+
--out <file> Write stdout to a file (never truncated; non-zero exit if the
|
|
189
|
+
write fails). content/translations use --out for their own file
|
|
190
|
+
--jsonl With --paginate: one JSON row per line, streamed
|
|
191
|
+
--token <pat> The token for this run, on every command. Precedence:
|
|
192
|
+
--token, then FORUMULATE_TOKEN, then credentials.json. On an
|
|
193
|
+
operation with a \`token\` parameter of its own (registries
|
|
194
|
+
set, github connect, domains acme-challenge) the flag is that
|
|
195
|
+
parameter; set FORUMULATE_TOKEN for the PAT there
|
|
155
196
|
--dry-run (api, resources) print the request instead of sending it
|
|
156
197
|
--dry-run Plan the work and write nothing (publish of a directory)
|
|
157
198
|
--version Print the CLI version
|
|
199
|
+
|
|
200
|
+
Exit status:
|
|
201
|
+
0 ok 1 failed (verification mismatch, doctor FAIL) 2 usage
|
|
202
|
+
3 auth (no token, 401, token not allowed) 4 not found
|
|
203
|
+
5 conflict (409/412, edited in the studio since your last publish)
|
|
158
204
|
`;
|
|
159
205
|
//# sourceMappingURL=help.js.map
|
package/dist/help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":";;;AAAA,2FAA2F;AAC9E,QAAA,IAAI,GAAG
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":";;;AAAA,2FAA2F;AAC9E,QAAA,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuMnB,CAAC"}
|
package/dist/io.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Writable } from 'node:stream';
|
|
2
|
+
/**
|
|
3
|
+
* Where a command's output goes, and the promise that it got there (FMU-B02/D05).
|
|
4
|
+
*
|
|
5
|
+
* `--json` piped into another program stopped at exactly 65,536 or 131,072
|
|
6
|
+
* bytes: the CLI called `process.exit()` the moment the command returned, and
|
|
7
|
+
* on a pipe Node writes stdout asynchronously, so whatever was still queued
|
|
8
|
+
* was thrown away — `items list --json | wc -c` said 65536 while the same
|
|
9
|
+
* command into a file wrote 8 MB. A sink buffers nothing of its own; it writes
|
|
10
|
+
* through, counts what the stream has not yet flushed, and `finish()` waits for
|
|
11
|
+
* the stream to say every byte is handed to the OS before the process ends.
|
|
12
|
+
* A write the OS refuses (a closed pipe, a full disk) is remembered and turns
|
|
13
|
+
* into a non-zero exit, rather than a truncated file and an exit 0.
|
|
14
|
+
*/
|
|
15
|
+
export interface Sink {
|
|
16
|
+
line(text: string): void;
|
|
17
|
+
/** Resolves once everything written is flushed; the first write error, if any. */
|
|
18
|
+
finish(): Promise<Error | undefined>;
|
|
19
|
+
}
|
|
20
|
+
export declare function streamSink(stream: Writable, opts?: {
|
|
21
|
+
closeOnFinish?: boolean;
|
|
22
|
+
}): Sink;
|
|
23
|
+
/**
|
|
24
|
+
* `--out <file>`: stdout into a file, opened on the first line so a command
|
|
25
|
+
* that prints nothing leaves no empty file behind. The write errors (no such
|
|
26
|
+
* directory, permission) surface on `finish()` like a pipe's.
|
|
27
|
+
*/
|
|
28
|
+
export declare function fileSink(path: string): Sink;
|
|
29
|
+
/** Commands whose own `--out` means "the file this command writes", not "my stdout". */
|
|
30
|
+
export declare const OWNS_OUT: Set<string>;
|
|
31
|
+
/** The `--out` value a global redirect should use, or undefined. */
|
|
32
|
+
export declare function globalOut(argv: string[]): string | undefined;
|
|
33
|
+
//# sourceMappingURL=io.d.ts.map
|
package/dist/io.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kFAAkF;IAClF,MAAM,IAAI,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;CACtC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,IAAI,CAoCzF;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAW3C;AAED,wFAAwF;AACxF,eAAO,MAAM,QAAQ,aAA+C,CAAC;AAErE,oEAAoE;AACpE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAQ5D"}
|
package/dist/io.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OWNS_OUT = void 0;
|
|
4
|
+
exports.streamSink = streamSink;
|
|
5
|
+
exports.fileSink = fileSink;
|
|
6
|
+
exports.globalOut = globalOut;
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
function streamSink(stream, opts = {}) {
|
|
9
|
+
let failed;
|
|
10
|
+
stream.on('error', (e) => {
|
|
11
|
+
failed ??= e;
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
line(text) {
|
|
15
|
+
if (failed)
|
|
16
|
+
return;
|
|
17
|
+
try {
|
|
18
|
+
stream.write(`${text}\n`);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
failed ??= e;
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
finish() {
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
let settled = false;
|
|
27
|
+
const done = (e) => {
|
|
28
|
+
if (settled)
|
|
29
|
+
return;
|
|
30
|
+
settled = true;
|
|
31
|
+
resolve(failed ?? e ?? undefined);
|
|
32
|
+
};
|
|
33
|
+
if (failed)
|
|
34
|
+
return done();
|
|
35
|
+
// A stream that errors never finishes: listen for both.
|
|
36
|
+
stream.once('error', (e) => done(e));
|
|
37
|
+
// `end`'s callback carries the error, and Node runs it BEFORE the
|
|
38
|
+
// 'error' event: dropping its argument resolved "no error" for an
|
|
39
|
+
// `--out` into a missing directory, and the CLI exited 0 having
|
|
40
|
+
// written nothing.
|
|
41
|
+
if (opts.closeOnFinish)
|
|
42
|
+
stream.end((e) => done(e ?? undefined));
|
|
43
|
+
// An empty write's callback runs after every earlier write has flushed.
|
|
44
|
+
else
|
|
45
|
+
stream.write('', (e) => done(e ?? undefined));
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* `--out <file>`: stdout into a file, opened on the first line so a command
|
|
52
|
+
* that prints nothing leaves no empty file behind. The write errors (no such
|
|
53
|
+
* directory, permission) surface on `finish()` like a pipe's.
|
|
54
|
+
*/
|
|
55
|
+
function fileSink(path) {
|
|
56
|
+
let inner;
|
|
57
|
+
return {
|
|
58
|
+
line(text) {
|
|
59
|
+
inner ??= streamSink((0, node_fs_1.createWriteStream)(path), { closeOnFinish: true });
|
|
60
|
+
inner.line(text);
|
|
61
|
+
},
|
|
62
|
+
finish() {
|
|
63
|
+
return inner ? inner.finish() : Promise.resolve(undefined);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Commands whose own `--out` means "the file this command writes", not "my stdout". */
|
|
68
|
+
exports.OWNS_OUT = new Set(['content', 'translations', 'i18n']);
|
|
69
|
+
/** The `--out` value a global redirect should use, or undefined. */
|
|
70
|
+
function globalOut(argv) {
|
|
71
|
+
const cmd = argv.find((a) => !a.startsWith('-'));
|
|
72
|
+
if (cmd && exports.OWNS_OUT.has(cmd))
|
|
73
|
+
return undefined;
|
|
74
|
+
const inline = argv.find((a) => a.startsWith('--out='));
|
|
75
|
+
if (inline)
|
|
76
|
+
return inline.slice(6) || undefined;
|
|
77
|
+
const at = argv.indexOf('--out');
|
|
78
|
+
const v = at >= 0 ? argv[at + 1] : undefined;
|
|
79
|
+
return v && !v.startsWith('--') ? v : undefined;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=io.js.map
|
package/dist/io.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":";;;AAsBA,gCAoCC;AAOD,4BAWC;AAMD,8BAQC;AA1FD,qCAA8D;AAsB9D,SAAgB,UAAU,CAAC,MAAgB,EAAE,OAAoC,EAAE;IACjF,IAAI,MAAyB,CAAC;IAC9B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;QAC9B,MAAM,KAAK,CAAC,CAAC;IACf,CAAC,CAAC,CAAC;IACH,OAAO;QACL,IAAI,CAAC,IAAY;YACf,IAAI,MAAM;gBAAE,OAAO;YACnB,IAAI,CAAC;gBACH,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,KAAK,CAAU,CAAC;YACxB,CAAC;QACH,CAAC;QACD,MAAM;YACJ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,IAAI,OAAO,GAAG,KAAK,CAAC;gBACpB,MAAM,IAAI,GAAG,CAAC,CAAgB,EAAE,EAAE;oBAChC,IAAI,OAAO;wBAAE,OAAO;oBACpB,OAAO,GAAG,IAAI,CAAC;oBACf,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC;gBACpC,CAAC,CAAC;gBACF,IAAI,MAAM;oBAAE,OAAO,IAAI,EAAE,CAAC;gBAC1B,wDAAwD;gBACxD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,kEAAkE;gBAClE,kEAAkE;gBAClE,gEAAgE;gBAChE,mBAAmB;gBACnB,IAAI,IAAI,CAAC,aAAa;oBACnB,MAAsB,CAAC,GAAG,CAAC,CAAC,CAAgB,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;gBAC1E,wEAAwE;;oBACnE,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;YACrD,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,QAAQ,CAAC,IAAY;IACnC,IAAI,KAAuB,CAAC;IAC5B,OAAO;QACL,IAAI,CAAC,IAAY;YACf,KAAK,KAAK,UAAU,CAAC,IAAA,2BAAiB,EAAC,IAAI,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QACD,MAAM;YACJ,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wFAAwF;AAC3E,QAAA,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AAErE,oEAAoE;AACpE,SAAgB,SAAS,CAAC,IAAc;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,IAAI,GAAG,IAAI,gBAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IAChD,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type PreviewResult } from './publish/preview';
|
|
2
|
+
type Fetch = typeof fetch;
|
|
3
|
+
/**
|
|
4
|
+
* `publish --preview <name> --comment` (FMU-F01): post the preview's link and
|
|
5
|
+
* diff on the pull request it was built for — and on the next push EDIT that
|
|
6
|
+
* comment rather than add another, found by the hidden
|
|
7
|
+
* `<!-- forumulate-preview:<name> -->` marker the API puts in it.
|
|
8
|
+
*
|
|
9
|
+
* Host-neutral: GitHub, Gitea/Forgejo (the same REST shape), GitLab and
|
|
10
|
+
* Bitbucket, each with the token its CI documents for writing comments
|
|
11
|
+
* (`GITHUB_TOKEN`, `GITEA_TOKEN`, `GITLAB_TOKEN`, `BITBUCKET_TOKEN`). Any other
|
|
12
|
+
* host: print the comment with `--json` (`previews[].comment`) and post it with
|
|
13
|
+
* that host's own tool — the recipes in docs/guides/docs-workflow.md do both.
|
|
14
|
+
*
|
|
15
|
+
* Answers the pull request's address, or null when there is nothing to
|
|
16
|
+
* comment on (not a PR build). Throws with a sentence when the host refuses.
|
|
17
|
+
*/
|
|
18
|
+
export declare function postPreviewComment(preview: PreviewResult, env: NodeJS.ProcessEnv, doFetch?: Fetch): Promise<string | null>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=preview-comment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-comment.d.ts","sourceRoot":"","sources":["../src/preview-comment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEjE,KAAK,KAAK,GAAG,OAAO,KAAK,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,GAAE,KAAa,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA+DxB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.postPreviewComment = postPreviewComment;
|
|
4
|
+
const preview_1 = require("./publish/preview");
|
|
5
|
+
/**
|
|
6
|
+
* `publish --preview <name> --comment` (FMU-F01): post the preview's link and
|
|
7
|
+
* diff on the pull request it was built for — and on the next push EDIT that
|
|
8
|
+
* comment rather than add another, found by the hidden
|
|
9
|
+
* `<!-- forumulate-preview:<name> -->` marker the API puts in it.
|
|
10
|
+
*
|
|
11
|
+
* Host-neutral: GitHub, Gitea/Forgejo (the same REST shape), GitLab and
|
|
12
|
+
* Bitbucket, each with the token its CI documents for writing comments
|
|
13
|
+
* (`GITHUB_TOKEN`, `GITEA_TOKEN`, `GITLAB_TOKEN`, `BITBUCKET_TOKEN`). Any other
|
|
14
|
+
* host: print the comment with `--json` (`previews[].comment`) and post it with
|
|
15
|
+
* that host's own tool — the recipes in docs/guides/docs-workflow.md do both.
|
|
16
|
+
*
|
|
17
|
+
* Answers the pull request's address, or null when there is nothing to
|
|
18
|
+
* comment on (not a PR build). Throws with a sentence when the host refuses.
|
|
19
|
+
*/
|
|
20
|
+
async function postPreviewComment(preview, env, doFetch = fetch) {
|
|
21
|
+
const src = (0, preview_1.ciSource)(env);
|
|
22
|
+
if (!src.provider || !src.repository || !src.number)
|
|
23
|
+
return null;
|
|
24
|
+
const marker = `<!-- forumulate-preview:${preview.name} -->`;
|
|
25
|
+
const body = preview.comment.includes(marker) ? preview.comment : `${marker}\n${preview.comment}`;
|
|
26
|
+
const call = async (url, init) => {
|
|
27
|
+
const res = await doFetch(url, init);
|
|
28
|
+
if (!res.ok)
|
|
29
|
+
throw new Error(`${src.provider} answered ${res.status} for ${init.method ?? 'GET'} ${url}`);
|
|
30
|
+
return res.status === 204 ? null : res.json();
|
|
31
|
+
};
|
|
32
|
+
switch (src.provider) {
|
|
33
|
+
case 'github':
|
|
34
|
+
case 'gitea': {
|
|
35
|
+
const token = env.GITEA_TOKEN || env.GITHUB_TOKEN || env.GH_TOKEN;
|
|
36
|
+
if (!token)
|
|
37
|
+
throw new Error('no GITHUB_TOKEN (or GITEA_TOKEN) to comment with');
|
|
38
|
+
const api = (env.GITHUB_API_URL || 'https://api.github.com').replace(/\/$/, '');
|
|
39
|
+
const headers = {
|
|
40
|
+
authorization: src.provider === 'gitea' ? `token ${token}` : `Bearer ${token}`,
|
|
41
|
+
accept: 'application/vnd.github+json',
|
|
42
|
+
'content-type': 'application/json',
|
|
43
|
+
'user-agent': 'forumulate-cli',
|
|
44
|
+
};
|
|
45
|
+
const base = `${api}/repos/${src.repository}/issues`;
|
|
46
|
+
const list = (await call(`${base}/${src.number}/comments?per_page=100`, { headers }));
|
|
47
|
+
const mine = list?.find((c) => c.body?.includes(marker));
|
|
48
|
+
if (mine)
|
|
49
|
+
await call(`${base}/comments/${mine.id}`, { method: 'PATCH', headers, body: JSON.stringify({ body }) });
|
|
50
|
+
else
|
|
51
|
+
await call(`${base}/${src.number}/comments`, { method: 'POST', headers, body: JSON.stringify({ body }) });
|
|
52
|
+
return src.url ?? `${src.repository}#${src.number}`;
|
|
53
|
+
}
|
|
54
|
+
case 'gitlab': {
|
|
55
|
+
const token = env.GITLAB_TOKEN;
|
|
56
|
+
if (!token)
|
|
57
|
+
throw new Error('no GITLAB_TOKEN to comment with (CI_JOB_TOKEN cannot write notes)');
|
|
58
|
+
const api = (env.CI_API_V4_URL || 'https://gitlab.com/api/v4').replace(/\/$/, '');
|
|
59
|
+
const headers = { 'private-token': token, 'content-type': 'application/json' };
|
|
60
|
+
const base = `${api}/projects/${encodeURIComponent(src.repository)}/merge_requests/${src.number}/notes`;
|
|
61
|
+
const list = (await call(`${base}?per_page=100`, { headers }));
|
|
62
|
+
const mine = list?.find((n) => n.body?.includes(marker));
|
|
63
|
+
if (mine)
|
|
64
|
+
await call(`${base}/${mine.id}`, { method: 'PUT', headers, body: JSON.stringify({ body }) });
|
|
65
|
+
else
|
|
66
|
+
await call(base, { method: 'POST', headers, body: JSON.stringify({ body }) });
|
|
67
|
+
return src.url ?? `${src.repository}!${src.number}`;
|
|
68
|
+
}
|
|
69
|
+
case 'bitbucket': {
|
|
70
|
+
const token = env.BITBUCKET_TOKEN;
|
|
71
|
+
if (!token)
|
|
72
|
+
throw new Error('no BITBUCKET_TOKEN (a repository access token) to comment with');
|
|
73
|
+
const headers = { authorization: `Bearer ${token}`, 'content-type': 'application/json' };
|
|
74
|
+
const base = `https://api.bitbucket.org/2.0/repositories/${src.repository}/pullrequests/${src.number}/comments`;
|
|
75
|
+
const list = (await call(`${base}?pagelen=100`, { headers }));
|
|
76
|
+
const mine = list?.values?.find((c) => c.content?.raw?.includes(marker));
|
|
77
|
+
const payload = JSON.stringify({ content: { raw: body } });
|
|
78
|
+
if (mine)
|
|
79
|
+
await call(`${base}/${mine.id}`, { method: 'PUT', headers, body: payload });
|
|
80
|
+
else
|
|
81
|
+
await call(base, { method: 'POST', headers, body: payload });
|
|
82
|
+
return src.url ?? `${src.repository}#${src.number}`;
|
|
83
|
+
}
|
|
84
|
+
default:
|
|
85
|
+
throw new Error(`no built-in commenter for ${src.provider}; post previews[].comment from \`--json\` with your host's tool`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=preview-comment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preview-comment.js","sourceRoot":"","sources":["../src/preview-comment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type SpaceCtx } from './context';
|
|
2
|
+
/**
|
|
3
|
+
* `about:` in forumulate.yaml — an About page's parts, as content-as-code.
|
|
4
|
+
*
|
|
5
|
+
* spaces:
|
|
6
|
+
* - path: about
|
|
7
|
+
* space: about
|
|
8
|
+
* create: { type: ABOUT, name: About }
|
|
9
|
+
* about:
|
|
10
|
+
* mission: Make work lighter.
|
|
11
|
+
* values: [{ title: Ship small }, { title: Write it down }]
|
|
12
|
+
* team: { source: authors, keys: [ada, grace], founders: [ada] }
|
|
13
|
+
* company: { legalName: Acme Software GmbH, vatId: DE123456789 }
|
|
14
|
+
*
|
|
15
|
+
* or `about: about.yaml` (a file beside the manifest holding the same map).
|
|
16
|
+
* The folder's own Markdown is the story page, published like any page. Only
|
|
17
|
+
* the top-level keys that differ from what the space holds are sent, through
|
|
18
|
+
* `PUT …/about` (PATCH semantics), so a re-run that changes nothing writes
|
|
19
|
+
* nothing; `null` in the manifest clears a part. Every reference is checked by
|
|
20
|
+
* the API, and a 422 names the key.
|
|
21
|
+
*/
|
|
22
|
+
export declare function syncAbout(ctx: SpaceCtx, apply: boolean, manifestFile: string | null): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=about.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"about.d.ts","sourceRoot":"","sources":["../../src/publish/about.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAmCf"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.syncAbout = syncAbout;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const yaml_1 = require("yaml");
|
|
7
|
+
const compare_1 = require("./compare");
|
|
8
|
+
const context_1 = require("./context");
|
|
9
|
+
/**
|
|
10
|
+
* `about:` in forumulate.yaml — an About page's parts, as content-as-code.
|
|
11
|
+
*
|
|
12
|
+
* spaces:
|
|
13
|
+
* - path: about
|
|
14
|
+
* space: about
|
|
15
|
+
* create: { type: ABOUT, name: About }
|
|
16
|
+
* about:
|
|
17
|
+
* mission: Make work lighter.
|
|
18
|
+
* values: [{ title: Ship small }, { title: Write it down }]
|
|
19
|
+
* team: { source: authors, keys: [ada, grace], founders: [ada] }
|
|
20
|
+
* company: { legalName: Acme Software GmbH, vatId: DE123456789 }
|
|
21
|
+
*
|
|
22
|
+
* or `about: about.yaml` (a file beside the manifest holding the same map).
|
|
23
|
+
* The folder's own Markdown is the story page, published like any page. Only
|
|
24
|
+
* the top-level keys that differ from what the space holds are sent, through
|
|
25
|
+
* `PUT …/about` (PATCH semantics), so a re-run that changes nothing writes
|
|
26
|
+
* nothing; `null` in the manifest clears a part. Every reference is checked by
|
|
27
|
+
* the API, and a 422 names the key.
|
|
28
|
+
*/
|
|
29
|
+
async function syncAbout(ctx, apply, manifestFile) {
|
|
30
|
+
const raw = ctx.spec.about;
|
|
31
|
+
if (raw === undefined || !ctx.only.part('about', ctx.spec))
|
|
32
|
+
return;
|
|
33
|
+
if (ctx.type !== 'ABOUT') {
|
|
34
|
+
ctx.errors.push(`about: belongs on an ABOUT space; ${ctx.spec.space} is ${ctx.type}`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let want;
|
|
38
|
+
if (typeof raw === 'string') {
|
|
39
|
+
const abs = (0, node_path_1.resolve)(manifestFile ? (0, node_path_1.dirname)(manifestFile) : ctx.root, raw);
|
|
40
|
+
const text = (0, node_fs_1.readFileSync)(abs, 'utf8');
|
|
41
|
+
const parsed = /\.json$/i.test(abs) ? JSON.parse(text) : (0, yaml_1.parse)(text);
|
|
42
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
43
|
+
ctx.errors.push(`about: ${raw} must hold a map of About parts`);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
want = parsed;
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
want = raw;
|
|
50
|
+
if (!ctx.api.opts.authed) {
|
|
51
|
+
ctx.line({
|
|
52
|
+
verb: 'patch',
|
|
53
|
+
what: 'about',
|
|
54
|
+
detail: `${Object.keys(want).join(', ')} — cannot compare without a token`,
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const current = await ctx.api.get((0, context_1.spacePath)(ctx, '/about'));
|
|
59
|
+
const keys = (0, compare_1.differingKeys)(current, want);
|
|
60
|
+
if (!keys.length)
|
|
61
|
+
return;
|
|
62
|
+
ctx.line({ verb: 'patch', what: 'about', detail: keys.join(', ') });
|
|
63
|
+
if (apply)
|
|
64
|
+
await ctx.api.put((0, context_1.spacePath)(ctx, '/about'), Object.fromEntries(keys.map((k) => [k, want[k]])));
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=about.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"about.js","sourceRoot":"","sources":["../../src/publish/about.ts"],"names":[],"mappings":";;AA0BA,8BAuCC;AAjED,qCAAuC;AACvC,yCAA6C;AAC7C,+BAA0C;AAC1C,uCAA0C;AAC1C,uCAAqD;AAErD;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,SAAS,CAC7B,GAAa,EACb,KAAc,EACd,YAA2B;IAE3B,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;IAC3B,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IACnE,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACzB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,qCAAqC,GAAG,CAAC,IAAI,CAAC,KAAK,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACtF,OAAO;IACT,CAAC;IACD,IAAI,IAA6B,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAA,mBAAO,EAAC,YAAY,CAAC,CAAC,CAAC,IAAA,mBAAO,EAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,IAAA,sBAAY,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAY,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAA,YAAS,EAAC,IAAI,CAAC,CAAC;QAClF,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,iCAAiC,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QACD,IAAI,GAAG,MAAiC,CAAC;IAC3C,CAAC;;QAAM,IAAI,GAAG,GAAG,CAAC;IAClB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC;SAC3E,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,CAA0B,IAAA,mBAAS,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,IAAA,uBAAa,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO;IACzB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpE,IAAI,KAAK;QACP,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,CACf,IAAA,mBAAS,EAAC,GAAG,EAAE,QAAQ,CAAC,EACxB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAClD,CAAC;AACN,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ApiClient } from './client';
|
|
2
2
|
import type { PlanLine } from './types';
|
|
3
|
+
import { type StudioConflict } from './studio-edits';
|
|
4
|
+
import { type PreviewResult } from './preview';
|
|
3
5
|
/**
|
|
4
6
|
* `forumulate publish <folder>` — a folder of Markdown, and optionally a
|
|
5
7
|
* manifest, made into a live presence; and the same command run again changes
|
|
@@ -41,6 +43,16 @@ export interface PublishOptions {
|
|
|
41
43
|
defaultSpace?: string;
|
|
42
44
|
/** Which command is speaking, for the words of the summary. */
|
|
43
45
|
command?: 'publish' | 'sync';
|
|
46
|
+
/** `--purge` (FMU-D04). Undefined: the server's background purge, unreported. */
|
|
47
|
+
purge?: 'page' | 'space' | 'none';
|
|
48
|
+
/**
|
|
49
|
+
* `--preview <name>` (FMU-F01): plan as a publish would, then send the pages
|
|
50
|
+
* to a preview of that name instead of publishing them. Implies a plan: no
|
|
51
|
+
* page, setting or theme is written.
|
|
52
|
+
*/
|
|
53
|
+
preview?: string;
|
|
54
|
+
/** `--preview-ttl <days>`: ask for a shorter-lived preview link. */
|
|
55
|
+
previewTtlDays?: number;
|
|
44
56
|
}
|
|
45
57
|
/** Everything a run decided, for a caller that keeps it (the git sync job stores it). */
|
|
46
58
|
export interface PublishReport {
|
|
@@ -57,6 +69,14 @@ export interface PublishReport {
|
|
|
57
69
|
writes: number;
|
|
58
70
|
/** Count per verb that changes something (`create`, `update`, …). */
|
|
59
71
|
counts: Record<string, number>;
|
|
72
|
+
/** Pieces that already matched the folder. */
|
|
73
|
+
unchanged: number;
|
|
74
|
+
/** Every purge the server reported for this run, per space (FMU-D04). */
|
|
75
|
+
purged: Record<string, unknown>[];
|
|
76
|
+
/** Pages the run refused to overwrite: edited in the studio since (FMU-D18). */
|
|
77
|
+
conflicts: StudioConflict[];
|
|
78
|
+
/** `--preview`: each space's preview link and summary (FMU-F01). */
|
|
79
|
+
previews: PreviewResult[];
|
|
60
80
|
}
|
|
61
81
|
export interface PublishDeps {
|
|
62
82
|
client: ApiClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/publish/command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/publish/command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAW1C,OAAO,KAAK,EAAsB,QAAQ,EAAa,MAAM,SAAS,CAAC;AACvE,OAAO,EAAiC,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpF,OAAO,EAAuC,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAEpF;;;;;;;;;;;;;;;;;;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;IACd,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC7B,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,yFAAyF;AACzF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,EAAE,CAAC;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,EAAE,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAClC,gFAAgF;IAChF,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,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;IACtC,sEAAsE;IACtE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC;CACrC;AAKD,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAwMzF"}
|