@softure-ai/blog 0.0.0-stage → 0.1.5
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/LICENSE +21 -0
- package/README.md +602 -2
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +5 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/command.d.ts +9 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +40 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/run.d.ts +62 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +552 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/skill.d.ts +47 -0
- package/dist/cli/skill.d.ts.map +1 -0
- package/dist/cli/skill.js +221 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/content/article-file.d.ts +27 -0
- package/dist/content/article-file.d.ts.map +1 -0
- package/dist/content/article-file.js +179 -0
- package/dist/content/article-file.js.map +1 -0
- package/dist/contract.d.ts +77 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +5 -0
- package/dist/contract.js.map +1 -0
- package/dist/db/articles.d.ts +30 -0
- package/dist/db/articles.d.ts.map +1 -0
- package/dist/db/articles.js +138 -0
- package/dist/db/articles.js.map +1 -0
- package/dist/db/publish-run.d.ts +50 -0
- package/dist/db/publish-run.d.ts.map +1 -0
- package/dist/db/publish-run.js +168 -0
- package/dist/db/publish-run.js.map +1 -0
- package/dist/db/schema.d.ts +403 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +33 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/discovery/dates.d.ts +9 -0
- package/dist/discovery/dates.d.ts.map +1 -0
- package/dist/discovery/dates.js +19 -0
- package/dist/discovery/dates.js.map +1 -0
- package/dist/discovery/index.d.ts +8 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +11 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/indexnow.d.ts +11 -0
- package/dist/discovery/indexnow.d.ts.map +1 -0
- package/dist/discovery/indexnow.js +23 -0
- package/dist/discovery/indexnow.js.map +1 -0
- package/dist/discovery/refresh.d.ts +49 -0
- package/dist/discovery/refresh.d.ts.map +1 -0
- package/dist/discovery/refresh.js +55 -0
- package/dist/discovery/refresh.js.map +1 -0
- package/dist/discovery/related.d.ts +17 -0
- package/dist/discovery/related.d.ts.map +1 -0
- package/dist/discovery/related.js +28 -0
- package/dist/discovery/related.js.map +1 -0
- package/dist/discovery/rss.d.ts +30 -0
- package/dist/discovery/rss.d.ts.map +1 -0
- package/dist/discovery/rss.js +48 -0
- package/dist/discovery/rss.js.map +1 -0
- package/dist/discovery/sitemap.d.ts +25 -0
- package/dist/discovery/sitemap.d.ts.map +1 -0
- package/dist/discovery/sitemap.js +31 -0
- package/dist/discovery/sitemap.js.map +1 -0
- package/dist/discovery/submit.d.ts +44 -0
- package/dist/discovery/submit.d.ts.map +1 -0
- package/dist/discovery/submit.js +46 -0
- package/dist/discovery/submit.js.map +1 -0
- package/dist/index.d.ts +371 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/messages/en.d.ts +83 -0
- package/dist/messages/en.d.ts.map +1 -0
- package/dist/messages/en.js +83 -0
- package/dist/messages/en.js.map +1 -0
- package/dist/messages/index.d.ts +158 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +5 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/pl.d.ts +78 -0
- package/dist/messages/pl.d.ts.map +1 -0
- package/dist/messages/pl.js +78 -0
- package/dist/messages/pl.js.map +1 -0
- package/dist/next/context.d.ts +6 -0
- package/dist/next/context.d.ts.map +1 -0
- package/dist/next/context.js +27 -0
- package/dist/next/context.js.map +1 -0
- package/dist/next/data.d.ts +11 -0
- package/dist/next/data.d.ts.map +1 -0
- package/dist/next/data.js +40 -0
- package/dist/next/data.js.map +1 -0
- package/dist/next/discovery.d.ts +6 -0
- package/dist/next/discovery.d.ts.map +1 -0
- package/dist/next/discovery.js +49 -0
- package/dist/next/discovery.js.map +1 -0
- package/dist/next/index.d.ts +9 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +10 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/og-fonts.d.ts +6 -0
- package/dist/next/og-fonts.d.ts.map +1 -0
- package/dist/next/og-fonts.js +8 -0
- package/dist/next/og-fonts.js.map +1 -0
- package/dist/next/og-image.d.ts +36 -0
- package/dist/next/og-image.d.ts.map +1 -0
- package/dist/next/og-image.js +77 -0
- package/dist/next/og-image.js.map +1 -0
- package/dist/next/pages.d.ts +45 -0
- package/dist/next/pages.d.ts.map +1 -0
- package/dist/next/pages.js +189 -0
- package/dist/next/pages.js.map +1 -0
- package/dist/next/refresh.d.ts +9 -0
- package/dist/next/refresh.d.ts.map +1 -0
- package/dist/next/refresh.js +81 -0
- package/dist/next/refresh.js.map +1 -0
- package/dist/options.d.ts +320 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +184 -0
- package/dist/options.js.map +1 -0
- package/dist/pages/body.d.ts +18 -0
- package/dist/pages/body.d.ts.map +1 -0
- package/dist/pages/body.js +21 -0
- package/dist/pages/body.js.map +1 -0
- package/dist/pages/dates.d.ts +21 -0
- package/dist/pages/dates.d.ts.map +1 -0
- package/dist/pages/dates.js +24 -0
- package/dist/pages/dates.js.map +1 -0
- package/dist/pages/index.d.ts +7 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +9 -0
- package/dist/pages/index.js.map +1 -0
- package/dist/pages/json-ld.d.ts +33 -0
- package/dist/pages/json-ld.d.ts.map +1 -0
- package/dist/pages/json-ld.js +95 -0
- package/dist/pages/json-ld.js.map +1 -0
- package/dist/pages/listing.d.ts +46 -0
- package/dist/pages/listing.d.ts.map +1 -0
- package/dist/pages/listing.js +57 -0
- package/dist/pages/listing.js.map +1 -0
- package/dist/pages/paths.d.ts +37 -0
- package/dist/pages/paths.d.ts.map +1 -0
- package/dist/pages/paths.js +61 -0
- package/dist/pages/paths.js.map +1 -0
- package/dist/pages/redirects.d.ts +57 -0
- package/dist/pages/redirects.d.ts.map +1 -0
- package/dist/pages/redirects.js +78 -0
- package/dist/pages/redirects.js.map +1 -0
- package/dist/proxy/index.d.ts +15 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +60 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/quality/blocks.d.ts +21 -0
- package/dist/quality/blocks.d.ts.map +1 -0
- package/dist/quality/blocks.js +113 -0
- package/dist/quality/blocks.js.map +1 -0
- package/dist/quality/catalog.d.ts +10 -0
- package/dist/quality/catalog.d.ts.map +1 -0
- package/dist/quality/catalog.js +71 -0
- package/dist/quality/catalog.js.map +1 -0
- package/dist/quality/check-article.d.ts +34 -0
- package/dist/quality/check-article.d.ts.map +1 -0
- package/dist/quality/check-article.js +74 -0
- package/dist/quality/check-article.js.map +1 -0
- package/dist/quality/check-files.d.ts +23 -0
- package/dist/quality/check-files.d.ts.map +1 -0
- package/dist/quality/check-files.js +44 -0
- package/dist/quality/check-files.js.map +1 -0
- package/dist/quality/external-links.d.ts +19 -0
- package/dist/quality/external-links.d.ts.map +1 -0
- package/dist/quality/external-links.js +30 -0
- package/dist/quality/external-links.js.map +1 -0
- package/dist/quality/finding.d.ts +17 -0
- package/dist/quality/finding.d.ts.map +1 -0
- package/dist/quality/finding.js +15 -0
- package/dist/quality/finding.js.map +1 -0
- package/dist/quality/gate.d.ts +5 -0
- package/dist/quality/gate.d.ts.map +1 -0
- package/dist/quality/gate.js +10 -0
- package/dist/quality/gate.js.map +1 -0
- package/dist/quality/index.d.ts +15 -0
- package/dist/quality/index.d.ts.map +1 -0
- package/dist/quality/index.js +16 -0
- package/dist/quality/index.js.map +1 -0
- package/dist/quality/link-targets.d.ts +44 -0
- package/dist/quality/link-targets.d.ts.map +1 -0
- package/dist/quality/link-targets.js +91 -0
- package/dist/quality/link-targets.js.map +1 -0
- package/dist/quality/options.d.ts +113 -0
- package/dist/quality/options.d.ts.map +1 -0
- package/dist/quality/options.js +93 -0
- package/dist/quality/options.js.map +1 -0
- package/dist/quality/plugin.d.ts +34 -0
- package/dist/quality/plugin.d.ts.map +1 -0
- package/dist/quality/plugin.js +7 -0
- package/dist/quality/plugin.js.map +1 -0
- package/dist/quality/rules/blocks.d.ts +5 -0
- package/dist/quality/rules/blocks.d.ts.map +1 -0
- package/dist/quality/rules/blocks.js +35 -0
- package/dist/quality/rules/blocks.js.map +1 -0
- package/dist/quality/rules/images.d.ts +4 -0
- package/dist/quality/rules/images.d.ts.map +1 -0
- package/dist/quality/rules/images.js +33 -0
- package/dist/quality/rules/images.js.map +1 -0
- package/dist/quality/rules/input.d.ts +11 -0
- package/dist/quality/rules/input.d.ts.map +1 -0
- package/dist/quality/rules/input.js +2 -0
- package/dist/quality/rules/input.js.map +1 -0
- package/dist/quality/rules/links.d.ts +17 -0
- package/dist/quality/rules/links.d.ts.map +1 -0
- package/dist/quality/rules/links.js +46 -0
- package/dist/quality/rules/links.js.map +1 -0
- package/dist/quality/rules/structure.d.ts +13 -0
- package/dist/quality/rules/structure.d.ts.map +1 -0
- package/dist/quality/rules/structure.js +139 -0
- package/dist/quality/rules/structure.js.map +1 -0
- package/dist/quality/rules/style.d.ts +11 -0
- package/dist/quality/rules/style.d.ts.map +1 -0
- package/dist/quality/rules/style.js +129 -0
- package/dist/quality/rules/style.js.map +1 -0
- package/dist/quality/rules/ymyl.d.ts +5 -0
- package/dist/quality/rules/ymyl.d.ts.map +1 -0
- package/dist/quality/rules/ymyl.js +51 -0
- package/dist/quality/rules/ymyl.js.map +1 -0
- package/dist/quality/rulesets/en/ruleset.d.ts +3 -0
- package/dist/quality/rulesets/en/ruleset.d.ts.map +1 -0
- package/dist/quality/rulesets/en/ruleset.js +106 -0
- package/dist/quality/rulesets/en/ruleset.js.map +1 -0
- package/dist/quality/rulesets/index.d.ts +7 -0
- package/dist/quality/rulesets/index.d.ts.map +1 -0
- package/dist/quality/rulesets/index.js +7 -0
- package/dist/quality/rulesets/index.js.map +1 -0
- package/dist/quality/rulesets/pl/ruleset.d.ts +3 -0
- package/dist/quality/rulesets/pl/ruleset.d.ts.map +1 -0
- package/dist/quality/rulesets/pl/ruleset.js +114 -0
- package/dist/quality/rulesets/pl/ruleset.js.map +1 -0
- package/dist/quality/rulesets/types.d.ts +28 -0
- package/dist/quality/rulesets/types.d.ts.map +1 -0
- package/dist/quality/rulesets/types.js +2 -0
- package/dist/quality/rulesets/types.js.map +1 -0
- package/dist/quality/settings.d.ts +26 -0
- package/dist/quality/settings.d.ts.map +1 -0
- package/dist/quality/settings.js +32 -0
- package/dist/quality/settings.js.map +1 -0
- package/dist/quality/text.d.ts +43 -0
- package/dist/quality/text.d.ts.map +1 -0
- package/dist/quality/text.js +85 -0
- package/dist/quality/text.js.map +1 -0
- package/dist/render/glossary.d.ts +27 -0
- package/dist/render/glossary.d.ts.map +1 -0
- package/dist/render/glossary.js +71 -0
- package/dist/render/glossary.js.map +1 -0
- package/dist/render/images.d.ts +42 -0
- package/dist/render/images.d.ts.map +1 -0
- package/dist/render/images.js +84 -0
- package/dist/render/images.js.map +1 -0
- package/dist/render/index.d.ts +6 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +8 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/reading-time.d.ts +8 -0
- package/dist/render/reading-time.d.ts.map +1 -0
- package/dist/render/reading-time.js +17 -0
- package/dist/render/reading-time.js.map +1 -0
- package/dist/render/render-article.d.ts +97 -0
- package/dist/render/render-article.d.ts.map +1 -0
- package/dist/render/render-article.js +373 -0
- package/dist/render/render-article.js.map +1 -0
- package/dist/render/slugify-heading.d.ts +2 -0
- package/dist/render/slugify-heading.d.ts.map +1 -0
- package/dist/render/slugify-heading.js +21 -0
- package/dist/render/slugify-heading.js.map +1 -0
- package/dist/server/health.d.ts +3 -0
- package/dist/server/health.d.ts.map +1 -0
- package/dist/server/health.js +11 -0
- package/dist/server/health.js.map +1 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +13 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/og-fonts.d.ts +24 -0
- package/dist/server/og-fonts.d.ts.map +1 -0
- package/dist/server/og-fonts.js +85 -0
- package/dist/server/og-fonts.js.map +1 -0
- package/dist/server/options.d.ts +17 -0
- package/dist/server/options.d.ts.map +1 -0
- package/dist/server/options.js +56 -0
- package/dist/server/options.js.map +1 -0
- package/dist/sitemap.d.ts +11 -0
- package/dist/sitemap.d.ts.map +1 -0
- package/dist/sitemap.js +35 -0
- package/dist/sitemap.js.map +1 -0
- package/dist/ui/blog-article.d.ts +49 -0
- package/dist/ui/blog-article.d.ts.map +1 -0
- package/dist/ui/blog-article.js +45 -0
- package/dist/ui/blog-article.js.map +1 -0
- package/dist/ui/blog-glossary.d.ts +27 -0
- package/dist/ui/blog-glossary.d.ts.map +1 -0
- package/dist/ui/blog-glossary.js +20 -0
- package/dist/ui/blog-glossary.js.map +1 -0
- package/dist/ui/blog-layout.d.ts +31 -0
- package/dist/ui/blog-layout.d.ts.map +1 -0
- package/dist/ui/blog-layout.js +25 -0
- package/dist/ui/blog-layout.js.map +1 -0
- package/dist/ui/blog-listing.d.ts +15 -0
- package/dist/ui/blog-listing.d.ts.map +1 -0
- package/dist/ui/blog-listing.js +29 -0
- package/dist/ui/blog-listing.js.map +1 -0
- package/dist/ui/blog-method.d.ts +5 -0
- package/dist/ui/blog-method.d.ts.map +1 -0
- package/dist/ui/blog-method.js +21 -0
- package/dist/ui/blog-method.js.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +8 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/page-context.d.ts +15 -0
- package/dist/ui/page-context.d.ts.map +1 -0
- package/dist/ui/page-context.js +2 -0
- package/dist/ui/page-context.js.map +1 -0
- package/migrations/0001_create_articles.sql +67 -0
- package/migrations/README.md +8 -0
- package/module.json +28 -0
- package/package.json +98 -4
- package/skill/SKILL.md +72 -0
- package/skill/references/reviewer.md +39 -0
- package/skill/references/rules.md +122 -0
- package/skill/references/structure.md +69 -0
- package/skill/references/template.md +86 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/command.ts +49 -0
- package/src/cli/index.ts +20 -0
- package/src/cli/run.ts +589 -0
- package/src/cli/skill.ts +242 -0
- package/src/content/article-file.ts +184 -0
- package/src/contract.ts +88 -0
- package/src/db/articles.ts +160 -0
- package/src/db/publish-run.ts +224 -0
- package/src/db/schema.ts +36 -0
- package/src/discovery/dates.ts +27 -0
- package/src/discovery/index.ts +18 -0
- package/src/discovery/indexnow.ts +25 -0
- package/src/discovery/refresh.ts +79 -0
- package/src/discovery/related.ts +35 -0
- package/src/discovery/rss.ts +77 -0
- package/src/discovery/sitemap.ts +59 -0
- package/src/discovery/submit.ts +69 -0
- package/src/index.ts +99 -0
- package/src/messages/en.ts +82 -0
- package/src/messages/index.ts +7 -0
- package/src/messages/pl.ts +77 -0
- package/src/next/context.ts +30 -0
- package/src/next/data.ts +55 -0
- package/src/next/discovery.ts +49 -0
- package/src/next/index.ts +25 -0
- package/src/next/next-modules.d.ts +15 -0
- package/src/next/og-fonts.ts +14 -0
- package/src/next/og-image.tsx +108 -0
- package/src/next/pages.tsx +251 -0
- package/src/next/refresh.ts +85 -0
- package/src/options.ts +224 -0
- package/src/pages/body.ts +38 -0
- package/src/pages/dates.ts +39 -0
- package/src/pages/index.ts +37 -0
- package/src/pages/json-ld.ts +120 -0
- package/src/pages/listing.ts +95 -0
- package/src/pages/paths.ts +84 -0
- package/src/pages/redirects.ts +120 -0
- package/src/proxy/index.ts +66 -0
- package/src/quality/blocks.ts +130 -0
- package/src/quality/catalog.ts +86 -0
- package/src/quality/check-article.ts +112 -0
- package/src/quality/check-files.ts +63 -0
- package/src/quality/external-links.ts +37 -0
- package/src/quality/finding.ts +29 -0
- package/src/quality/gate.ts +15 -0
- package/src/quality/index.ts +28 -0
- package/src/quality/link-targets.ts +107 -0
- package/src/quality/options.ts +105 -0
- package/src/quality/plugin.ts +43 -0
- package/src/quality/rules/blocks.ts +43 -0
- package/src/quality/rules/images.ts +34 -0
- package/src/quality/rules/input.ts +12 -0
- package/src/quality/rules/links.ts +56 -0
- package/src/quality/rules/structure.ts +137 -0
- package/src/quality/rules/style.ts +137 -0
- package/src/quality/rules/ymyl.ts +57 -0
- package/src/quality/rulesets/en/ruleset.ts +117 -0
- package/src/quality/rulesets/index.ts +9 -0
- package/src/quality/rulesets/pl/ruleset.ts +126 -0
- package/src/quality/rulesets/types.ts +31 -0
- package/src/quality/settings.ts +60 -0
- package/src/quality/text.ts +113 -0
- package/src/render/glossary.ts +103 -0
- package/src/render/images.ts +110 -0
- package/src/render/index.ts +29 -0
- package/src/render/reading-time.ts +18 -0
- package/src/render/render-article.ts +487 -0
- package/src/render/slugify-heading.ts +22 -0
- package/src/server/health.ts +12 -0
- package/src/server/index.ts +28 -0
- package/src/server/og-fonts.ts +102 -0
- package/src/server/options.ts +62 -0
- package/src/sitemap.ts +36 -0
- package/src/ui/blog-article.tsx +186 -0
- package/src/ui/blog-glossary.tsx +104 -0
- package/src/ui/blog-layout.tsx +89 -0
- package/src/ui/blog-listing.tsx +95 -0
- package/src/ui/blog-method.tsx +34 -0
- package/src/ui/index.ts +8 -0
- package/src/ui/page-context.ts +17 -0
- package/styles.css +498 -0
package/dist/cli/run.js
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
// `softure-blog`: publishes the app's article files into the module's tables. The app passes its
|
|
2
|
+
// validated config, so the same function serves the bin and an app script that a bundler packs
|
|
3
|
+
// for a container:
|
|
4
|
+
//
|
|
5
|
+
// // scripts/blog.ts
|
|
6
|
+
// import { runBlogCli } from "@softure-ai/blog/cli";
|
|
7
|
+
// import config from "../softure.config";
|
|
8
|
+
// process.exitCode = await runBlogCli({ config, argv: process.argv.slice(2) });
|
|
9
|
+
import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
10
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
11
|
+
import { parseArgs } from "node:util";
|
|
12
|
+
import { systemClock } from "@softure-ai/core";
|
|
13
|
+
import { createDatabase } from "@softure-ai/db";
|
|
14
|
+
import { BLOG_REFRESH_SECRET_ENV, requestBlogRefresh } from "../discovery/refresh.js";
|
|
15
|
+
import { submitBlogChanges } from "../discovery/submit.js";
|
|
16
|
+
import { runBlogPublish } from "../db/publish-run.js";
|
|
17
|
+
import { checkArticleFiles } from "../quality/check-files.js";
|
|
18
|
+
import { createQualityGate } from "../quality/gate.js";
|
|
19
|
+
import { createInternalLinkResolver, findAppDir, readContentFolder, readGlossaryTerms, readPublishedContent } from "../quality/link-targets.js";
|
|
20
|
+
import { getLocalDate } from "../quality/settings.js";
|
|
21
|
+
import { createOgFontLoader } from "../server/og-fonts.js";
|
|
22
|
+
import { getBlogOptions, getBlogReservedSlugs, getQualitySettings } from "../server/options.js";
|
|
23
|
+
import { DEFAULT_SKILL_COMMAND, DEFAULT_SKILL_DIR, renderBlogSkill, SKILL_MARKER } from "./skill.js";
|
|
24
|
+
export const EXIT_OK = 0;
|
|
25
|
+
export const EXIT_FAILED = 1;
|
|
26
|
+
export const EXIT_USAGE = 2;
|
|
27
|
+
export const BLOG_USAGE = `Usage:
|
|
28
|
+
softure-blog publish [<path>...] [--commit] [--withdraw] [--no-indexnow] [--app-url <origin>]
|
|
29
|
+
softure-blog check [<path>...] [--external] [--today <YYYY-MM-DD>]
|
|
30
|
+
softure-blog skill install [--dir <path>] [--command <cmd>] [--check]
|
|
31
|
+
|
|
32
|
+
publish Brings the blog's tables to the state of the article files. A <path> is a file or a
|
|
33
|
+
folder (every *.md in it except README.md); without one, blog({ contentDir }).
|
|
34
|
+
Every file is checked before the first write, and one problem writes nothing.
|
|
35
|
+
--commit write the changes; without it, a dry run that shows them and writes nothing
|
|
36
|
+
--withdraw publish the one given file as withdrawn, whatever its status
|
|
37
|
+
--no-indexnow do not submit the changed addresses to IndexNow
|
|
38
|
+
--app-url the running app's origin for the cache refresh; default: appOrigin
|
|
39
|
+
Files going public pass the quality gate first; an error writes nothing.
|
|
40
|
+
With ${BLOG_REFRESH_SECRET_ENV} set, a commit that changed a text asks the running
|
|
41
|
+
app (refreshBlogCache) to refresh its blog cache, before the IndexNow submit.
|
|
42
|
+
With seo({ indexNow }) enabled, a commit submits the addresses whose answer
|
|
43
|
+
changed (the text, its old slug, its listing) to IndexNow; a dry run prints them.
|
|
44
|
+
|
|
45
|
+
check Runs the quality gate of blog({ quality }) over the files, without a database, and
|
|
46
|
+
prints every finding as file:line: severity [rule] message. Exits 1 on any error.
|
|
47
|
+
--external also request every external link (2xx after redirects)
|
|
48
|
+
--today the date to check freshness against; default: today in the app's time zone
|
|
49
|
+
|
|
50
|
+
skill install
|
|
51
|
+
Writes the article writing skill, filled from blog({ quality, skill }),
|
|
52
|
+
into ${DEFAULT_SKILL_DIR}. Overwrites only a skill it generated before.
|
|
53
|
+
--dir the skill folder; default ${DEFAULT_SKILL_DIR}
|
|
54
|
+
--command how the skill runs this command; default "${DEFAULT_SKILL_COMMAND}"
|
|
55
|
+
--check write nothing; exit 1 when the folder differs from what install would write
|
|
56
|
+
|
|
57
|
+
Options:
|
|
58
|
+
--config <file> the app's softure.config file (bin only)
|
|
59
|
+
--help show this help`;
|
|
60
|
+
const consoleOutput = {
|
|
61
|
+
log: (line) => console.log(line),
|
|
62
|
+
error: (line) => console.error(line),
|
|
63
|
+
};
|
|
64
|
+
/** Runs the command and returns the process exit code: 0 done, 1 refused or failed, 2 usage error. */
|
|
65
|
+
export async function runBlogCli(options) {
|
|
66
|
+
const output = options.output ?? consoleOutput;
|
|
67
|
+
const command = parseBlogCommand(options.argv);
|
|
68
|
+
if (typeof command === "string") {
|
|
69
|
+
output.error(`softure-blog: ${command}`);
|
|
70
|
+
output.error(BLOG_USAGE);
|
|
71
|
+
return EXIT_USAGE;
|
|
72
|
+
}
|
|
73
|
+
if (command.kind === "help") {
|
|
74
|
+
output.log(BLOG_USAGE);
|
|
75
|
+
return EXIT_OK;
|
|
76
|
+
}
|
|
77
|
+
if (command.kind === "skill-install")
|
|
78
|
+
return runSkillInstall(command, options, output);
|
|
79
|
+
return command.kind === "check" ? runCheck(command, options, output) : runPublish(command, options, output);
|
|
80
|
+
}
|
|
81
|
+
/** The command the arguments name, or why they name none. Reads nothing. */
|
|
82
|
+
export function parseBlogCommand(argv) {
|
|
83
|
+
const [name, ...rest] = argv;
|
|
84
|
+
if (name === undefined)
|
|
85
|
+
return "missing command; use publish, check or skill install";
|
|
86
|
+
if (name === "--help")
|
|
87
|
+
return { kind: "help" };
|
|
88
|
+
if (name === "check")
|
|
89
|
+
return parseCheckCommand(rest);
|
|
90
|
+
if (name === "skill")
|
|
91
|
+
return parseSkillCommand(rest);
|
|
92
|
+
if (name !== "publish")
|
|
93
|
+
return `unknown command "${name}"; use publish, check or skill install`;
|
|
94
|
+
let parsed;
|
|
95
|
+
try {
|
|
96
|
+
parsed = parsePublishArgs(rest);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return error instanceof Error ? error.message : String(error);
|
|
100
|
+
}
|
|
101
|
+
const { values, positionals } = parsed;
|
|
102
|
+
if (values.help === true)
|
|
103
|
+
return { kind: "help" };
|
|
104
|
+
const withdraw = values.withdraw === true;
|
|
105
|
+
if (withdraw && positionals.length !== 1)
|
|
106
|
+
return "--withdraw takes exactly one article file";
|
|
107
|
+
const appUrl = values["app-url"] === undefined ? null : parseOrigin(values["app-url"]);
|
|
108
|
+
if (appUrl === undefined)
|
|
109
|
+
return `--app-url needs an http or https origin, e.g. http://web:3000, not "${values["app-url"] ?? ""}"`;
|
|
110
|
+
return { kind: "publish", paths: positionals, commit: values.commit === true, withdraw, indexNow: values["no-indexnow"] !== true, appUrl };
|
|
111
|
+
}
|
|
112
|
+
/** The origin of an http(s) URL, or `undefined` for anything else. */
|
|
113
|
+
function parseOrigin(value) {
|
|
114
|
+
try {
|
|
115
|
+
const url = new URL(value);
|
|
116
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url.origin : undefined;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// The caller names the value.
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function parseCheckCommand(args) {
|
|
124
|
+
let parsed;
|
|
125
|
+
try {
|
|
126
|
+
parsed = parseCheckArgs(args);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return error instanceof Error ? error.message : String(error);
|
|
130
|
+
}
|
|
131
|
+
const { values, positionals } = parsed;
|
|
132
|
+
if (values.help === true)
|
|
133
|
+
return { kind: "help" };
|
|
134
|
+
const today = values.today ?? null;
|
|
135
|
+
if (today !== null && (!/^\d{4}-\d{2}-\d{2}$/.test(today) || Number.isNaN(Date.parse(`${today}T00:00:00Z`))))
|
|
136
|
+
return `--today needs a date YYYY-MM-DD, not "${today}"`;
|
|
137
|
+
return { kind: "check", paths: positionals, external: values.external === true, today };
|
|
138
|
+
}
|
|
139
|
+
function parseSkillCommand(args) {
|
|
140
|
+
const [subcommand, ...rest] = args;
|
|
141
|
+
if (subcommand === "--help")
|
|
142
|
+
return { kind: "help" };
|
|
143
|
+
if (subcommand !== "install")
|
|
144
|
+
return subcommand === undefined ? "skill needs a subcommand: install" : `unknown skill subcommand "${subcommand}"; use install`;
|
|
145
|
+
let parsed;
|
|
146
|
+
try {
|
|
147
|
+
parsed = parseSkillArgs(rest);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
return error instanceof Error ? error.message : String(error);
|
|
151
|
+
}
|
|
152
|
+
const { values, positionals } = parsed;
|
|
153
|
+
if (values.help === true)
|
|
154
|
+
return { kind: "help" };
|
|
155
|
+
if (positionals.length > 0)
|
|
156
|
+
return `skill install takes no paths; use --dir <path>, not "${positionals.join(" ")}"`;
|
|
157
|
+
const dir = values.dir ?? DEFAULT_SKILL_DIR;
|
|
158
|
+
const command = values.command ?? DEFAULT_SKILL_COMMAND;
|
|
159
|
+
if (dir.trim() === "")
|
|
160
|
+
return "--dir needs a folder";
|
|
161
|
+
if (command.trim() === "")
|
|
162
|
+
return "--command needs the command, e.g. \"npm run blog --\"";
|
|
163
|
+
return { kind: "skill-install", dir, command: command.trim(), check: values.check === true };
|
|
164
|
+
}
|
|
165
|
+
function parseSkillArgs(args) {
|
|
166
|
+
return parseArgs({
|
|
167
|
+
args: [...args],
|
|
168
|
+
options: {
|
|
169
|
+
dir: { type: "string" },
|
|
170
|
+
command: { type: "string" },
|
|
171
|
+
check: { type: "boolean" },
|
|
172
|
+
help: { type: "boolean" },
|
|
173
|
+
},
|
|
174
|
+
strict: true,
|
|
175
|
+
allowPositionals: true,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function parseCheckArgs(args) {
|
|
179
|
+
return parseArgs({
|
|
180
|
+
args: [...args],
|
|
181
|
+
options: {
|
|
182
|
+
external: { type: "boolean" },
|
|
183
|
+
today: { type: "string" },
|
|
184
|
+
help: { type: "boolean" },
|
|
185
|
+
},
|
|
186
|
+
strict: true,
|
|
187
|
+
allowPositionals: true,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function parsePublishArgs(args) {
|
|
191
|
+
return parseArgs({
|
|
192
|
+
args: [...args],
|
|
193
|
+
options: {
|
|
194
|
+
commit: { type: "boolean" },
|
|
195
|
+
withdraw: { type: "boolean" },
|
|
196
|
+
"no-indexnow": { type: "boolean" },
|
|
197
|
+
"app-url": { type: "string" },
|
|
198
|
+
help: { type: "boolean" },
|
|
199
|
+
},
|
|
200
|
+
strict: true,
|
|
201
|
+
allowPositionals: true,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function runPublish(command, options, output) {
|
|
205
|
+
const cwd = options.cwd ?? process.cwd();
|
|
206
|
+
const { config } = options;
|
|
207
|
+
let blogOptions;
|
|
208
|
+
try {
|
|
209
|
+
blogOptions = getBlogOptions(config);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
output.error(`softure-blog publish: ${describeError(error)}`);
|
|
213
|
+
return EXIT_FAILED;
|
|
214
|
+
}
|
|
215
|
+
const paths = command.paths.length > 0 ? command.paths : [blogOptions.contentDir];
|
|
216
|
+
const files = await readArticleFiles(paths.map((path) => resolve(cwd, path)));
|
|
217
|
+
if (typeof files === "string") {
|
|
218
|
+
output.error(`softure-blog publish: ${files}`);
|
|
219
|
+
return EXIT_FAILED;
|
|
220
|
+
}
|
|
221
|
+
if (command.withdraw && files.length !== 1) {
|
|
222
|
+
output.error("softure-blog publish: --withdraw takes exactly one article file, not a folder");
|
|
223
|
+
return EXIT_FAILED;
|
|
224
|
+
}
|
|
225
|
+
if (config.database === null) {
|
|
226
|
+
output.error("softure-blog publish: the config has no database; set database.url in softure.config");
|
|
227
|
+
return EXIT_FAILED;
|
|
228
|
+
}
|
|
229
|
+
const clock = options.clock ?? systemClock;
|
|
230
|
+
let gate = options.gate;
|
|
231
|
+
if (gate === undefined) {
|
|
232
|
+
const settings = getQualitySettings(config);
|
|
233
|
+
if (settings !== null)
|
|
234
|
+
gate = createQualityGate(settings, clock);
|
|
235
|
+
}
|
|
236
|
+
let handle;
|
|
237
|
+
try {
|
|
238
|
+
handle = await (options.openDatabase ?? openDatabase)(config.database.url);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
output.error(`softure-blog publish: ${describeError(error)}`);
|
|
242
|
+
return EXIT_FAILED;
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
const run = await runBlogPublish({ db: handle.db, clock, config }, files, {
|
|
246
|
+
commit: command.commit,
|
|
247
|
+
withdraw: command.withdraw,
|
|
248
|
+
reservedSlugs: getBlogReservedSlugs(config),
|
|
249
|
+
...(blogOptions.fields === undefined ? {} : { fields: blogOptions.fields }),
|
|
250
|
+
...(gate === undefined ? {} : { gate }),
|
|
251
|
+
});
|
|
252
|
+
const code = reportRun(run, output);
|
|
253
|
+
if (run.status === "done") {
|
|
254
|
+
// Before the IndexNow submit: a crawler that answers the ping must find the new text.
|
|
255
|
+
const refresh = await requestBlogRefresh(config, run.changes, {
|
|
256
|
+
commit: run.committed,
|
|
257
|
+
...(command.appUrl === null ? {} : { appUrl: command.appUrl }),
|
|
258
|
+
...(options.env === undefined ? {} : { env: options.env }),
|
|
259
|
+
...(options.refreshFetch === undefined ? {} : { fetchImpl: options.refreshFetch }),
|
|
260
|
+
});
|
|
261
|
+
reportRefresh(refresh, output);
|
|
262
|
+
}
|
|
263
|
+
if (run.status === "done" && command.indexNow) {
|
|
264
|
+
reportIndexNow(await submitBlogChanges(config, run.changes, { commit: run.committed, ...(options.indexNowFetch === undefined ? {} : { fetchImpl: options.indexNowFetch }) }), output);
|
|
265
|
+
}
|
|
266
|
+
return code;
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
// Driver errors: the message only, never a stack or the database URL.
|
|
270
|
+
output.error(`softure-blog publish: ${describeError(error)} (did softure migrate run?)`);
|
|
271
|
+
return EXIT_FAILED;
|
|
272
|
+
}
|
|
273
|
+
finally {
|
|
274
|
+
await handle.close();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
async function runCheck(command, options, output) {
|
|
278
|
+
const cwd = options.cwd ?? process.cwd();
|
|
279
|
+
let blogOptions;
|
|
280
|
+
let settings;
|
|
281
|
+
try {
|
|
282
|
+
blogOptions = getBlogOptions(options.config);
|
|
283
|
+
settings = getQualitySettings(options.config);
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
output.error(`softure-blog check: ${describeError(error)}`);
|
|
287
|
+
return EXIT_FAILED;
|
|
288
|
+
}
|
|
289
|
+
if (settings === null) {
|
|
290
|
+
output.error("softure-blog check: the quality gate is off (blog({ quality: false })); nothing to check");
|
|
291
|
+
return EXIT_FAILED;
|
|
292
|
+
}
|
|
293
|
+
// The OG card's fonts, read as the card's route reads them (paths from the app's root), so CI
|
|
294
|
+
// reports a source the first card would fail on.
|
|
295
|
+
const fontProblem = await checkBrandFonts(blogOptions.brand?.fonts, cwd, options.fontFetch);
|
|
296
|
+
if (fontProblem !== null)
|
|
297
|
+
output.error(`softure-blog check: ${fontProblem}`);
|
|
298
|
+
const fontErrors = fontProblem === null ? 0 : 1;
|
|
299
|
+
const contentDir = resolve(cwd, blogOptions.contentDir);
|
|
300
|
+
const paths = command.paths.length > 0 ? command.paths.map((path) => resolve(cwd, path)) : [contentDir];
|
|
301
|
+
const files = await readArticleFiles(paths);
|
|
302
|
+
if (typeof files === "string") {
|
|
303
|
+
output.error(`softure-blog check: ${files}`);
|
|
304
|
+
return EXIT_FAILED;
|
|
305
|
+
}
|
|
306
|
+
if (files.length === 0) {
|
|
307
|
+
output.log("check: no article files");
|
|
308
|
+
return fontErrors > 0 ? EXIT_FAILED : EXIT_OK;
|
|
309
|
+
}
|
|
310
|
+
// Link targets and glossary forms: the published texts of the content folder and of the checked files, and the app's routes.
|
|
311
|
+
const siteFiles = [...readContentFolder(contentDir), ...files];
|
|
312
|
+
const content = readPublishedContent(siteFiles);
|
|
313
|
+
const parse = { reservedSlugs: getBlogReservedSlugs(options.config), ...(blogOptions.fields === undefined ? {} : { fields: blogOptions.fields }) };
|
|
314
|
+
const resolveInternalLink = createInternalLinkResolver({
|
|
315
|
+
appDir: findAppDir(cwd, settings.options.appDir),
|
|
316
|
+
privateRouteSegments: settings.options.privateRouteSegments,
|
|
317
|
+
paths: settings.options.paths,
|
|
318
|
+
content,
|
|
319
|
+
});
|
|
320
|
+
const results = await checkArticleFiles(files, {
|
|
321
|
+
settings,
|
|
322
|
+
today: command.today ?? getLocalDate((options.clock ?? systemClock).now(), settings.timeZone),
|
|
323
|
+
resolveInternalLink,
|
|
324
|
+
parse,
|
|
325
|
+
glossary: readGlossaryTerms(siteFiles, parse),
|
|
326
|
+
...(command.external ? { fetch: options.fetch ?? fetch } : {}),
|
|
327
|
+
});
|
|
328
|
+
return reportCheck(results, files, cwd, output, fontErrors);
|
|
329
|
+
}
|
|
330
|
+
/** The loader's message for a `brand.fonts` source the card cannot read; `null` when every one reads or none is set. */
|
|
331
|
+
async function checkBrandFonts(fonts, root, fetchImpl) {
|
|
332
|
+
if (fonts === undefined)
|
|
333
|
+
return null;
|
|
334
|
+
const loaded = await createOgFontLoader({ root, ...(fetchImpl === undefined ? {} : { fetchImpl }) })(fonts);
|
|
335
|
+
return loaded.ok ? null : loaded.error;
|
|
336
|
+
}
|
|
337
|
+
async function runSkillInstall(command, options, output) {
|
|
338
|
+
const cwd = options.cwd ?? process.cwd();
|
|
339
|
+
const dir = resolve(cwd, command.dir);
|
|
340
|
+
const shown = relative(cwd, dir) || ".";
|
|
341
|
+
let files;
|
|
342
|
+
try {
|
|
343
|
+
files = renderBlogSkill(options.config, { command: command.command });
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
output.error(`softure-blog skill install: ${describeError(error)}`);
|
|
347
|
+
return EXIT_FAILED;
|
|
348
|
+
}
|
|
349
|
+
let extra;
|
|
350
|
+
try {
|
|
351
|
+
const rendered = new Set(files.map((file) => file.path));
|
|
352
|
+
extra = (await listMarkdownFiles(dir)).filter((path) => !rendered.has(path));
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
output.error(`softure-blog skill install: cannot read ${shown}: ${describeError(error)}`);
|
|
356
|
+
return EXIT_FAILED;
|
|
357
|
+
}
|
|
358
|
+
if (command.check) {
|
|
359
|
+
const stale = [];
|
|
360
|
+
for (const file of files) {
|
|
361
|
+
if ((await readText(join(dir, file.path))) !== file.text)
|
|
362
|
+
stale.push(file.path);
|
|
363
|
+
}
|
|
364
|
+
if (stale.length === 0 && extra.length === 0) {
|
|
365
|
+
output.log(`skill: ${shown} is up to date`);
|
|
366
|
+
return EXIT_OK;
|
|
367
|
+
}
|
|
368
|
+
for (const path of stale)
|
|
369
|
+
output.error(`skill: ${join(shown, path)} differs from the blog config`);
|
|
370
|
+
for (const path of extra)
|
|
371
|
+
output.error(`skill: ${join(shown, path)} is not part of the skill`);
|
|
372
|
+
output.error("skill: run softure-blog skill install with the same options and commit the folder");
|
|
373
|
+
return EXIT_FAILED;
|
|
374
|
+
}
|
|
375
|
+
const existing = await readText(join(dir, "SKILL.md"));
|
|
376
|
+
if (existing !== null && !existing.includes(SKILL_MARKER)) {
|
|
377
|
+
output.error(`softure-blog skill install: ${join(shown, "SKILL.md")} was not generated by this command; refusing to overwrite it (choose another --dir)`);
|
|
378
|
+
return EXIT_FAILED;
|
|
379
|
+
}
|
|
380
|
+
try {
|
|
381
|
+
for (const file of files) {
|
|
382
|
+
const path = join(dir, file.path);
|
|
383
|
+
await mkdir(dirname(path), { recursive: true });
|
|
384
|
+
await writeFile(path, file.text, "utf8");
|
|
385
|
+
}
|
|
386
|
+
// The folder is the command's own (its SKILL.md carries the marker): a Markdown file it no longer renders goes.
|
|
387
|
+
for (const path of extra)
|
|
388
|
+
await rm(join(dir, path));
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
output.error(`softure-blog skill install: cannot write ${shown}: ${describeError(error)}`);
|
|
392
|
+
return EXIT_FAILED;
|
|
393
|
+
}
|
|
394
|
+
for (const file of files)
|
|
395
|
+
output.log(`wrote ${join(shown, file.path)}`);
|
|
396
|
+
for (const path of extra)
|
|
397
|
+
output.log(`removed ${join(shown, path)}`);
|
|
398
|
+
output.log(`skill: installed into ${shown}; commit it, and run skill install --check in CI`);
|
|
399
|
+
return EXIT_OK;
|
|
400
|
+
}
|
|
401
|
+
/** `configErrors`: problems of the config itself (the brand's fonts), already printed. */
|
|
402
|
+
function reportCheck(results, files, cwd, output, configErrors) {
|
|
403
|
+
let errors = configErrors;
|
|
404
|
+
let warnings = 0;
|
|
405
|
+
for (const [index, result] of results.entries()) {
|
|
406
|
+
const shown = relative(cwd, files[index]?.path ?? result.file) || result.file;
|
|
407
|
+
if (result.findings.length === 0)
|
|
408
|
+
output.log(`${shown}: OK`);
|
|
409
|
+
for (const finding of result.findings) {
|
|
410
|
+
output.log(`${finding.line === undefined ? shown : `${shown}:${String(finding.line)}`}: ${finding.severity} [${finding.rule}] ${finding.message}`);
|
|
411
|
+
if (finding.severity === "error")
|
|
412
|
+
errors += 1;
|
|
413
|
+
else
|
|
414
|
+
warnings += 1;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
output.log(`check: ${String(results.length)} file(s), ${String(errors)} error(s), ${String(warnings)} warning(s): ${errors > 0 ? "red, do not publish" : "green"}`);
|
|
418
|
+
return errors > 0 ? EXIT_FAILED : EXIT_OK;
|
|
419
|
+
}
|
|
420
|
+
function reportRun(run, output) {
|
|
421
|
+
for (const warning of run.warnings)
|
|
422
|
+
output.error(`warning ${formatProblem(warning)}`);
|
|
423
|
+
if (run.status === "refused") {
|
|
424
|
+
for (const problem of run.problems)
|
|
425
|
+
output.error(`error ${formatProblem(problem)}`);
|
|
426
|
+
output.error("refused: nothing written; fix the problems above");
|
|
427
|
+
return EXIT_FAILED;
|
|
428
|
+
}
|
|
429
|
+
for (const change of run.changes) {
|
|
430
|
+
output.log(formatChange(change));
|
|
431
|
+
if (change.previousSlug !== null)
|
|
432
|
+
output.log(`moved ${change.id} ${change.previousSlug} -> ${change.slug}`);
|
|
433
|
+
}
|
|
434
|
+
const count = (action) => String(run.changes.filter((change) => change.action === action).length);
|
|
435
|
+
output.log(`summary: added ${count("added")}, changed ${count("changed")}, unchanged ${count("unchanged")}`);
|
|
436
|
+
output.log(run.committed ? "written" : "dry run: nothing written; pass --commit to write");
|
|
437
|
+
return EXIT_OK;
|
|
438
|
+
}
|
|
439
|
+
/** One line about the cache refresh; a failure is a warning and never changes the exit code. */
|
|
440
|
+
function reportRefresh(outcome, output) {
|
|
441
|
+
switch (outcome.kind) {
|
|
442
|
+
case "not_configured":
|
|
443
|
+
output.log(`cache: the running app shows the change within revalidateSeconds (${String(outcome.revalidateSeconds)} s); set ${BLOG_REFRESH_SECRET_ENV} to refresh it now`);
|
|
444
|
+
return;
|
|
445
|
+
case "skipped":
|
|
446
|
+
output.log("cache: no text changed, nothing to refresh");
|
|
447
|
+
return;
|
|
448
|
+
case "dry_run":
|
|
449
|
+
output.log(`cache: dry run, a commit would refresh ${outcome.url}`);
|
|
450
|
+
return;
|
|
451
|
+
case "refreshed":
|
|
452
|
+
output.log(`cache: refreshed ${outcome.url}`);
|
|
453
|
+
return;
|
|
454
|
+
case "failed":
|
|
455
|
+
output.error(`warning cache: ${outcome.reason} (${outcome.code}); the publish is written, the app shows it within ${String(outcome.revalidateSeconds)} s`);
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/** One line about the IndexNow submit; a failure is a warning and never changes the exit code. */
|
|
460
|
+
function reportIndexNow({ paths, outcome }, output) {
|
|
461
|
+
switch (outcome.kind) {
|
|
462
|
+
case "not_configured":
|
|
463
|
+
output.log(`indexnow: off, ${outcome.reason}`);
|
|
464
|
+
return;
|
|
465
|
+
case "skipped":
|
|
466
|
+
output.log("indexnow: no public address changed, nothing to submit");
|
|
467
|
+
return;
|
|
468
|
+
case "dry_run":
|
|
469
|
+
output.log(`indexnow: dry run, a commit would submit ${String(outcome.urls.length)} URL(s): ${outcome.urls.join(" ")}`);
|
|
470
|
+
return;
|
|
471
|
+
case "submitted":
|
|
472
|
+
output.log(`indexnow: submitted ${String(outcome.count)} URL(s) (${String(outcome.status)}): ${paths.join(" ")}`);
|
|
473
|
+
return;
|
|
474
|
+
case "failed":
|
|
475
|
+
output.error(`warning indexnow: ${outcome.reason} (${outcome.code}); the publish is written, submit the addresses later: ${paths.join(" ")}`);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function formatChange(change) {
|
|
480
|
+
const before = change.statusBefore === null || change.slugBefore === null ? "none" : `${change.statusBefore}/${change.slugBefore}`;
|
|
481
|
+
return `${change.action} ${change.id} ${before} -> ${change.statusAfter}/${change.slug}`;
|
|
482
|
+
}
|
|
483
|
+
function formatProblem(problem) {
|
|
484
|
+
return `${problem.subject}: ${problem.message}`;
|
|
485
|
+
}
|
|
486
|
+
/** The files the paths name, sorted by name within a folder, or why they cannot be read. */
|
|
487
|
+
async function readArticleFiles(paths) {
|
|
488
|
+
const files = [];
|
|
489
|
+
for (const path of paths) {
|
|
490
|
+
const kind = await getPathKind(path);
|
|
491
|
+
if (kind === null)
|
|
492
|
+
return `cannot read ${path}`;
|
|
493
|
+
const filePaths = kind === "file"
|
|
494
|
+
? [path]
|
|
495
|
+
: (await readdir(path))
|
|
496
|
+
.filter((name) => name.endsWith(".md") && name !== "README.md")
|
|
497
|
+
.sort()
|
|
498
|
+
.map((name) => join(path, name));
|
|
499
|
+
for (const filePath of filePaths) {
|
|
500
|
+
const text = await readText(filePath);
|
|
501
|
+
if (text === null)
|
|
502
|
+
return `cannot read ${filePath}`;
|
|
503
|
+
files.push({ name: basename(filePath), text, path: filePath });
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return files;
|
|
507
|
+
}
|
|
508
|
+
async function getPathKind(path) {
|
|
509
|
+
try {
|
|
510
|
+
const stats = await stat(path);
|
|
511
|
+
return stats.isDirectory() ? "folder" : "file";
|
|
512
|
+
}
|
|
513
|
+
catch {
|
|
514
|
+
// The caller names the path; the error code adds nothing an editor can act on.
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
/** The `.md` files under `dir`, relative to it with `/`; none when the folder does not exist. */
|
|
519
|
+
async function listMarkdownFiles(dir) {
|
|
520
|
+
let entries;
|
|
521
|
+
try {
|
|
522
|
+
entries = await readdir(dir, { recursive: true });
|
|
523
|
+
}
|
|
524
|
+
catch (error) {
|
|
525
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
526
|
+
return [];
|
|
527
|
+
throw error;
|
|
528
|
+
}
|
|
529
|
+
return entries
|
|
530
|
+
.map((entry) => entry.split("\\").join("/"))
|
|
531
|
+
.filter((entry) => entry.endsWith(".md"))
|
|
532
|
+
.sort();
|
|
533
|
+
}
|
|
534
|
+
async function readText(path) {
|
|
535
|
+
try {
|
|
536
|
+
return await readFile(path, "utf8");
|
|
537
|
+
}
|
|
538
|
+
catch {
|
|
539
|
+
// The caller names the path.
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
function openDatabase(url) {
|
|
544
|
+
return createDatabase(url, { max: 1 });
|
|
545
|
+
}
|
|
546
|
+
/** The driver's own message; drizzle's "Failed query: … params: …" wrapper is dropped. */
|
|
547
|
+
function describeError(error) {
|
|
548
|
+
if (!(error instanceof Error))
|
|
549
|
+
return String(error);
|
|
550
|
+
return error.cause instanceof Error ? error.cause.message : error.message;
|
|
551
|
+
}
|
|
552
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SoftureConfig } from "@softure-ai/core";
|
|
2
|
+
import { type QualityCatalogRule } from "../quality/catalog.js";
|
|
3
|
+
import type { BlogSkillSection } from "../options.js";
|
|
4
|
+
import type { QualitySettings } from "../quality/settings.js";
|
|
5
|
+
/** The folder the skill installs into, relative to the app's root. */
|
|
6
|
+
export declare const DEFAULT_SKILL_DIR = ".claude/skills/blog-write";
|
|
7
|
+
/** How the skill tells the agent to run the command. */
|
|
8
|
+
export declare const DEFAULT_SKILL_COMMAND = "npx softure-blog";
|
|
9
|
+
/** The line every generated `SKILL.md` holds; install overwrites only a folder whose `SKILL.md` has it. */
|
|
10
|
+
export declare const SKILL_MARKER = "<!-- Generated by `softure-blog skill install`";
|
|
11
|
+
/** The file that holds the app's own sections (`blog({ skill: { sections } })`), written only when there are some. */
|
|
12
|
+
export declare const APP_SECTIONS_FILE = "references/app.md";
|
|
13
|
+
export type SkillValues = Readonly<Record<string, string | boolean>>;
|
|
14
|
+
export interface SkillFile {
|
|
15
|
+
/** Relative to the skill folder, with `/`. */
|
|
16
|
+
readonly path: string;
|
|
17
|
+
readonly text: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RenderBlogSkillOptions {
|
|
20
|
+
/** How the skill names the command. Default: `npx softure-blog`. */
|
|
21
|
+
readonly command?: string;
|
|
22
|
+
}
|
|
23
|
+
/** The skill's files for the app's config. Throws when the gate is off: the skill is built on it. */
|
|
24
|
+
export declare function renderBlogSkill(config: SoftureConfig, options?: RenderBlogSkillOptions): SkillFile[];
|
|
25
|
+
/** `references/app.md`: each section as `## <title>` with its body verbatim, never run through the template engine. */
|
|
26
|
+
export declare function renderAppSections(sections: readonly BlogSkillSection[]): string;
|
|
27
|
+
/** The values the templates read. */
|
|
28
|
+
export declare function getSkillValues(config: SoftureConfig, settings: QualitySettings, options?: RenderBlogSkillOptions): SkillValues;
|
|
29
|
+
/**
|
|
30
|
+
* Fills `{{name}}` with a value and keeps `{{#flag}}…{{/flag}}` when the value is truthy (a non-empty
|
|
31
|
+
* string or `true`), `{{^flag}}…{{/flag}}` when it is not. A tag alone on its line takes the line with
|
|
32
|
+
* it. Throws on a name without a value and on a section that does not close, naming it.
|
|
33
|
+
*/
|
|
34
|
+
export declare function renderSkillTemplate(template: string, values: SkillValues): string;
|
|
35
|
+
/** The rule ids the template's tables name. */
|
|
36
|
+
export declare function findTemplateRuleIds(rulesTemplate: string): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Fills the rows of rules the gate enforces with their severity and description, drops the rows of
|
|
39
|
+
* rules it does not, drops a table (and its heading) left without rows, and lists every catalog rule
|
|
40
|
+
* the template has no row for (the app's voice phrases and plugin rules) under the app's own rules.
|
|
41
|
+
*/
|
|
42
|
+
export declare function fillRulesTables(text: string, rules: readonly QualityCatalogRule[]): string;
|
|
43
|
+
/** The template files, relative to `skill/`. */
|
|
44
|
+
export declare function listTemplateFiles(): string[];
|
|
45
|
+
/** The text of one template file, as shipped. */
|
|
46
|
+
export declare function readSkillTemplate(path: string): string;
|
|
47
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/cli/skill.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAC7D,wDAAwD;AACxD,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AACxD,2GAA2G;AAC3G,eAAO,MAAM,YAAY,mDAAmD,CAAC;AAK7E,sHAAsH;AACtH,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;AAErE,MAAM,WAAW,SAAS;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAID,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE,sBAA2B,GAAG,SAAS,EAAE,CAYxG;AAED,uHAAuH;AACvH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,CAS/E;AAED,qCAAqC;AACrC,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,sBAA2B,GAAG,WAAW,CAwClI;AAYD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,MAAM,CA+BjF;AAWD,+CAA+C;AAC/C,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAKnE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAsB1F;AAqBD,gDAAgD;AAChD,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAW5C;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|