@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.
Files changed (224) hide show
  1. package/README.md +3 -3
  2. package/dist/api/args.d.ts.map +1 -1
  3. package/dist/api/args.js +1 -0
  4. package/dist/api/args.js.map +1 -1
  5. package/dist/api/command.d.ts +1 -1
  6. package/dist/api/command.d.ts.map +1 -1
  7. package/dist/api/command.js +86 -11
  8. package/dist/api/command.js.map +1 -1
  9. package/dist/api/http.d.ts +8 -0
  10. package/dist/api/http.d.ts.map +1 -1
  11. package/dist/api/http.js +3 -2
  12. package/dist/api/http.js.map +1 -1
  13. package/dist/api/live-spec.d.ts +48 -0
  14. package/dist/api/live-spec.d.ts.map +1 -0
  15. package/dist/api/live-spec.js +72 -0
  16. package/dist/api/live-spec.js.map +1 -0
  17. package/dist/api/operations.json +1 -1
  18. package/dist/api/request.d.ts.map +1 -1
  19. package/dist/api/request.js +25 -1
  20. package/dist/api/request.js.map +1 -1
  21. package/dist/api/send.d.ts +10 -1
  22. package/dist/api/send.d.ts.map +1 -1
  23. package/dist/api/send.js +14 -3
  24. package/dist/api/send.js.map +1 -1
  25. package/dist/api/slim.d.ts +14 -0
  26. package/dist/api/slim.d.ts.map +1 -0
  27. package/dist/api/slim.js +174 -0
  28. package/dist/api/slim.js.map +1 -0
  29. package/dist/cache-command.d.ts +12 -0
  30. package/dist/cache-command.d.ts.map +1 -0
  31. package/dist/cache-command.js +93 -0
  32. package/dist/cache-command.js.map +1 -0
  33. package/dist/check/command.d.ts +48 -0
  34. package/dist/check/command.d.ts.map +1 -0
  35. package/dist/check/command.js +256 -0
  36. package/dist/check/command.js.map +1 -0
  37. package/dist/check/external.d.ts +66 -0
  38. package/dist/check/external.d.ts.map +1 -0
  39. package/dist/check/external.js +177 -0
  40. package/dist/check/external.js.map +1 -0
  41. package/dist/check/markdown-links.d.ts +38 -0
  42. package/dist/check/markdown-links.d.ts.map +1 -0
  43. package/dist/check/markdown-links.js +166 -0
  44. package/dist/check/markdown-links.js.map +1 -0
  45. package/dist/cli.js +42 -7
  46. package/dist/cli.js.map +1 -1
  47. package/dist/commands/completion.d.ts.map +1 -1
  48. package/dist/commands/completion.js +1 -0
  49. package/dist/commands/completion.js.map +1 -1
  50. package/dist/commands/context.d.ts.map +1 -1
  51. package/dist/commands/context.js +6 -2
  52. package/dist/commands/context.js.map +1 -1
  53. package/dist/commands/groups-api.d.ts.map +1 -1
  54. package/dist/commands/groups-api.js +20 -2
  55. package/dist/commands/groups-api.js.map +1 -1
  56. package/dist/commands/groups-docs.d.ts.map +1 -1
  57. package/dist/commands/groups-docs.js +8 -2
  58. package/dist/commands/groups-docs.js.map +1 -1
  59. package/dist/commands/groups-jobs.d.ts +10 -0
  60. package/dist/commands/groups-jobs.d.ts.map +1 -0
  61. package/dist/commands/groups-jobs.js +89 -0
  62. package/dist/commands/groups-jobs.js.map +1 -0
  63. package/dist/commands/groups-org.d.ts.map +1 -1
  64. package/dist/commands/groups-org.js +59 -2
  65. package/dist/commands/groups-org.js.map +1 -1
  66. package/dist/commands/groups-site.d.ts.map +1 -1
  67. package/dist/commands/groups-site.js +33 -3
  68. package/dist/commands/groups-site.js.map +1 -1
  69. package/dist/commands/groups-spaces.d.ts.map +1 -1
  70. package/dist/commands/groups-spaces.js +11 -5
  71. package/dist/commands/groups-spaces.js.map +1 -1
  72. package/dist/commands/groups-types.d.ts.map +1 -1
  73. package/dist/commands/groups-types.js +74 -0
  74. package/dist/commands/groups-types.js.map +1 -1
  75. package/dist/commands/groups.d.ts.map +1 -1
  76. package/dist/commands/groups.js +2 -0
  77. package/dist/commands/groups.js.map +1 -1
  78. package/dist/commands/index.d.ts +9 -0
  79. package/dist/commands/index.d.ts.map +1 -1
  80. package/dist/commands/index.js +18 -3
  81. package/dist/commands/index.js.map +1 -1
  82. package/dist/commands/job-wait.d.ts +64 -0
  83. package/dist/commands/job-wait.d.ts.map +1 -0
  84. package/dist/commands/job-wait.js +91 -0
  85. package/dist/commands/job-wait.js.map +1 -0
  86. package/dist/commands/resource.d.ts +19 -0
  87. package/dist/commands/resource.d.ts.map +1 -1
  88. package/dist/commands/resource.js +65 -3
  89. package/dist/commands/resource.js.map +1 -1
  90. package/dist/content/library.d.ts +8 -0
  91. package/dist/content/library.d.ts.map +1 -1
  92. package/dist/content/library.js +10 -2
  93. package/dist/content/library.js.map +1 -1
  94. package/dist/credentials.d.ts +43 -4
  95. package/dist/credentials.d.ts.map +1 -1
  96. package/dist/credentials.js +67 -4
  97. package/dist/credentials.js.map +1 -1
  98. package/dist/doctor/address-checks.d.ts +56 -0
  99. package/dist/doctor/address-checks.d.ts.map +1 -0
  100. package/dist/doctor/address-checks.js +183 -0
  101. package/dist/doctor/address-checks.js.map +1 -0
  102. package/dist/doctor/boilerplate.d.ts +33 -0
  103. package/dist/doctor/boilerplate.d.ts.map +1 -0
  104. package/dist/doctor/boilerplate.js +78 -0
  105. package/dist/doctor/boilerplate.js.map +1 -0
  106. package/dist/doctor/command.d.ts +18 -0
  107. package/dist/doctor/command.d.ts.map +1 -0
  108. package/dist/doctor/command.js +234 -0
  109. package/dist/doctor/command.js.map +1 -0
  110. package/dist/doctor/crawl.d.ts +49 -0
  111. package/dist/doctor/crawl.d.ts.map +1 -0
  112. package/dist/doctor/crawl.js +210 -0
  113. package/dist/doctor/crawl.js.map +1 -0
  114. package/dist/doctor/extended.d.ts +52 -0
  115. package/dist/doctor/extended.d.ts.map +1 -0
  116. package/dist/doctor/extended.js +150 -0
  117. package/dist/doctor/extended.js.map +1 -0
  118. package/dist/doctor/page-checks.d.ts +42 -0
  119. package/dist/doctor/page-checks.d.ts.map +1 -0
  120. package/dist/doctor/page-checks.js +200 -0
  121. package/dist/doctor/page-checks.js.map +1 -0
  122. package/dist/doctor/probe.d.ts +63 -0
  123. package/dist/doctor/probe.d.ts.map +1 -0
  124. package/dist/doctor/probe.js +170 -0
  125. package/dist/doctor/probe.js.map +1 -0
  126. package/dist/doctor/reader-auth-atlas.d.ts +18 -0
  127. package/dist/doctor/reader-auth-atlas.d.ts.map +1 -0
  128. package/dist/doctor/reader-auth-atlas.js +50 -0
  129. package/dist/doctor/reader-auth-atlas.js.map +1 -0
  130. package/dist/doctor/robots-params.d.ts +36 -0
  131. package/dist/doctor/robots-params.d.ts.map +1 -0
  132. package/dist/doctor/robots-params.js +97 -0
  133. package/dist/doctor/robots-params.js.map +1 -0
  134. package/dist/doctor/site.d.ts +42 -0
  135. package/dist/doctor/site.d.ts.map +1 -0
  136. package/dist/doctor/site.js +82 -0
  137. package/dist/doctor/site.js.map +1 -0
  138. package/dist/doctor.d.ts +21 -0
  139. package/dist/doctor.d.ts.map +1 -1
  140. package/dist/doctor.js +94 -3
  141. package/dist/doctor.js.map +1 -1
  142. package/dist/exit-codes.d.ts +40 -0
  143. package/dist/exit-codes.d.ts.map +1 -0
  144. package/dist/exit-codes.js +66 -0
  145. package/dist/exit-codes.js.map +1 -0
  146. package/dist/help-commands.d.ts +13 -0
  147. package/dist/help-commands.d.ts.map +1 -0
  148. package/dist/help-commands.js +215 -0
  149. package/dist/help-commands.js.map +1 -0
  150. package/dist/help.d.ts +1 -1
  151. package/dist/help.d.ts.map +1 -1
  152. package/dist/help.js +57 -11
  153. package/dist/help.js.map +1 -1
  154. package/dist/io.d.ts +33 -0
  155. package/dist/io.d.ts.map +1 -0
  156. package/dist/io.js +81 -0
  157. package/dist/io.js.map +1 -0
  158. package/dist/preview-comment.d.ts +20 -0
  159. package/dist/preview-comment.d.ts.map +1 -0
  160. package/dist/preview-comment.js +88 -0
  161. package/dist/preview-comment.js.map +1 -0
  162. package/dist/publish/about.d.ts +23 -0
  163. package/dist/publish/about.d.ts.map +1 -0
  164. package/dist/publish/about.js +66 -0
  165. package/dist/publish/about.js.map +1 -0
  166. package/dist/publish/command.d.ts +20 -0
  167. package/dist/publish/command.d.ts.map +1 -1
  168. package/dist/publish/command.js +97 -4
  169. package/dist/publish/command.js.map +1 -1
  170. package/dist/publish/context.d.ts +8 -0
  171. package/dist/publish/context.d.ts.map +1 -1
  172. package/dist/publish/context.js.map +1 -1
  173. package/dist/publish/docs-apply.d.ts.map +1 -1
  174. package/dist/publish/docs-apply.js +13 -1
  175. package/dist/publish/docs-apply.js.map +1 -1
  176. package/dist/publish/extras.d.ts +10 -0
  177. package/dist/publish/extras.d.ts.map +1 -1
  178. package/dist/publish/extras.js +54 -2
  179. package/dist/publish/extras.js.map +1 -1
  180. package/dist/publish/manifest.d.ts.map +1 -1
  181. package/dist/publish/manifest.js +27 -2
  182. package/dist/publish/manifest.js.map +1 -1
  183. package/dist/publish/preview.d.ts +56 -0
  184. package/dist/publish/preview.d.ts.map +1 -0
  185. package/dist/publish/preview.js +133 -0
  186. package/dist/publish/preview.js.map +1 -0
  187. package/dist/publish/redirects.d.ts +13 -0
  188. package/dist/publish/redirects.d.ts.map +1 -0
  189. package/dist/publish/redirects.js +154 -0
  190. package/dist/publish/redirects.js.map +1 -0
  191. package/dist/publish/studio-edits.d.ts +25 -0
  192. package/dist/publish/studio-edits.d.ts.map +1 -0
  193. package/dist/publish/studio-edits.js +53 -0
  194. package/dist/publish/studio-edits.js.map +1 -0
  195. package/dist/publish/types.d.ts +22 -1
  196. package/dist/publish/types.d.ts.map +1 -1
  197. package/dist/publish-command.d.ts +55 -0
  198. package/dist/publish-command.d.ts.map +1 -0
  199. package/dist/publish-command.js +197 -0
  200. package/dist/publish-command.js.map +1 -0
  201. package/dist/run.d.ts +3 -10
  202. package/dist/run.d.ts.map +1 -1
  203. package/dist/run.js +122 -110
  204. package/dist/run.js.map +1 -1
  205. package/dist/translations/target.d.ts.map +1 -1
  206. package/dist/translations/target.js +2 -2
  207. package/dist/translations/target.js.map +1 -1
  208. package/dist/validate.d.ts +39 -0
  209. package/dist/validate.d.ts.map +1 -0
  210. package/dist/validate.js +166 -0
  211. package/dist/validate.js.map +1 -0
  212. package/dist/version.d.ts +8 -0
  213. package/dist/version.d.ts.map +1 -0
  214. package/dist/version.js +11 -0
  215. package/dist/version.js.map +1 -0
  216. package/dist/whoami.d.ts +41 -0
  217. package/dist/whoami.d.ts.map +1 -0
  218. package/dist/whoami.js +161 -0
  219. package/dist/whoami.js.map +1 -0
  220. package/package.json +2 -2
  221. package/dist/publish-dir.d.ts +0 -54
  222. package/dist/publish-dir.d.ts.map +0 -1
  223. package/dist/publish-dir.js +0 -119
  224. package/dist/publish-dir.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,eAAO,MAAM,IAAI,k2TAyJhB,CAAC"}
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 Show the authenticated user
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) | webhooks | extensions | audit
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> Publish a folder of Markdown: one folder per
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
- publish <orgId> <spaceId> <pageId> Publish a page
80
- publish <orgId> <spaceId> <dir> The folder form, with org and space given
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
- doctor <readerUrl> Check a live site from the outside: health,
130
- public read, canonical, cache headers,
131
- crawler access, feeds, HTML rewriting
132
- help Show this help
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. Mint one at
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyJnB,CAAC"}
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
@@ -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":"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"}
@@ -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;AAU1C,OAAO,KAAK,EAAsB,QAAQ,EAAa,MAAM,SAAS,CAAC;AAEvE;;;;;;;;;;;;;;;;;;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;CAC9B;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;CAChC;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,CA2JzF"}
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"}