@saastemly/voidcommerce 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +269 -76
- package/dist/deploy/github.d.ts +85 -0
- package/dist/deploy/index.d.ts +3 -0
- package/dist/deploy/keys.d.ts +68 -25
- package/dist/deploy/link.d.ts +2 -0
- package/dist/deploy/secrets.d.ts +51 -8
- package/dist/generate/ci.d.ts +33 -18
- package/dist/generate/frontend.d.ts +1 -1
- package/dist/generate/index.d.ts +2 -0
- package/dist/index-2qt2yh3z.js +797 -0
- package/dist/{index-yzezvy5h.js → index-f1wds190.js} +322 -663
- package/dist/{index-pz6m2hkm.js → index-xx5p4b8d.js} +5 -4
- package/dist/index.js +12 -8
- package/dist/keys-qwvt324e.js +19 -0
- package/dist/manifest.d.ts +27 -5
- package/dist/manifest.js +3 -1
- package/package.json +1 -1
- package/src/cli.ts +14 -1
- package/src/deploy/cloudflare.ts +68 -4
- package/src/deploy/github.ts +198 -0
- package/src/deploy/index.ts +66 -18
- package/src/deploy/keys.ts +208 -144
- package/src/deploy/link.ts +185 -0
- package/src/deploy/secrets.ts +217 -35
- package/src/dotenvx-primitives.d.ts +4 -0
- package/src/generate/ci.ts +176 -121
- package/src/generate/frontend.ts +26 -4
- package/src/generate/index.ts +46 -8
- package/src/generate/support.ts +7 -5
- package/src/init.ts +2 -1
- package/src/manifest.ts +33 -8
- package/src/regenerate.ts +1 -0
- package/src/wizard.ts +7 -3
package/src/manifest.ts
CHANGED
|
@@ -30,9 +30,10 @@ export const MANIFEST_FILE = "voidcommerce.json";
|
|
|
30
30
|
* strict EXPERIMENTAL. A monorepo turned inside out. The REPOSITORY
|
|
31
31
|
* ROOT is the storefront — its package.json, its pages, yours to
|
|
32
32
|
* edit — and the worker is generated underneath it at .vc/app
|
|
33
|
-
* from the manifest, gitignored, never hand-edited.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* from the manifest, gitignored, never hand-edited. ONE worker
|
|
34
|
+
* serves both at <domain>: the storefront's prerendered tree is
|
|
35
|
+
* folded into the worker's assets at build time, so there is one
|
|
36
|
+
* origin, one deploy, and one certificate Cloudflare issues.
|
|
36
37
|
*
|
|
37
38
|
* The first question, because it decides where `void init` runs and what
|
|
38
39
|
* the domain means. It cannot change after init: moving files is not a
|
|
@@ -54,7 +55,7 @@ export const LAYOUTS: Array<{ id: Layout; label: string; hint: string }> = [
|
|
|
54
55
|
{
|
|
55
56
|
id: "strict",
|
|
56
57
|
label: "Strict (experimental)",
|
|
57
|
-
hint: "the root IS the storefront, sharing one package.json; the worker is generated under .vc/app
|
|
58
|
+
hint: "the root IS the storefront, sharing one package.json; the worker is generated under .vc/app and serves the storefront from its own assets — one origin, one deploy",
|
|
58
59
|
},
|
|
59
60
|
];
|
|
60
61
|
|
|
@@ -68,9 +69,28 @@ export const LAYOUTS: Array<{ id: Layout; label: string; hint: string }> = [
|
|
|
68
69
|
*/
|
|
69
70
|
export const isSingleApp = (layout: Layout): boolean => layout === "app";
|
|
70
71
|
|
|
71
|
-
/** Does this layout carry a storefront of its own,
|
|
72
|
+
/** Does this layout carry a storefront of its own, in the repository? */
|
|
72
73
|
export const hasFrontend = (layout: Layout): boolean => layout !== "app";
|
|
73
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Does ONE worker serve both the storefront and the API?
|
|
77
|
+
*
|
|
78
|
+
* `app` always did — it generates its storefront into the worker. `strict`
|
|
79
|
+
* now does too: the root's prerendered tree is merged into the worker's own
|
|
80
|
+
* assets directory at build time, so there is one origin, one hostname, one
|
|
81
|
+
* deploy, and one certificate that Cloudflare issues itself.
|
|
82
|
+
*
|
|
83
|
+
* That deletes the whole GitHub Pages half — the A/AAAA records, the CNAME
|
|
84
|
+
* file, the base-path rewriting — and with it a trap worth naming: GitHub
|
|
85
|
+
* treats any Cloudflare IP as ineligible for a certificate, so a proxied
|
|
86
|
+
* record silently stops issuance AND renewal about ninety days later, while
|
|
87
|
+
* GitHub's own health check still reports green.
|
|
88
|
+
*
|
|
89
|
+
* `monorepo` keeps the split, because there the frontend is a separate app
|
|
90
|
+
* that a person may well want hosted separately.
|
|
91
|
+
*/
|
|
92
|
+
export const oneOrigin = (layout: Layout): boolean => layout !== "monorepo";
|
|
93
|
+
|
|
74
94
|
/**
|
|
75
95
|
* Public suffixes whose second label is not a registrable name, so
|
|
76
96
|
* `shop.example.co.uk` is a subdomain of `example.co.uk`, not of `co.uk`.
|
|
@@ -100,7 +120,9 @@ export function isApex(manifest: Manifest): boolean {
|
|
|
100
120
|
/** Every hostname the worker answers on — the wrangler routes, in order. */
|
|
101
121
|
export function workerHosts(manifest: Manifest): string[] {
|
|
102
122
|
const { domain } = manifest.shop;
|
|
103
|
-
|
|
123
|
+
// Only a monorepo puts the worker on its own hostname; everything else
|
|
124
|
+
// serves the shop and its API from one origin.
|
|
125
|
+
if (!oneOrigin(manifest.layout)) return [`api.${domain}`];
|
|
104
126
|
return isApex(manifest) ? [domain, `www.${domain}`] : [domain];
|
|
105
127
|
}
|
|
106
128
|
|
|
@@ -145,7 +167,10 @@ export interface Manifest {
|
|
|
145
167
|
* default that is safe to assume.
|
|
146
168
|
*/
|
|
147
169
|
taxRegistered?: boolean | undefined;
|
|
148
|
-
/**
|
|
170
|
+
/**
|
|
171
|
+
* `saastemly.github.io` — only a MONOREPO has a storefront on GitHub
|
|
172
|
+
* Pages. In `app` and `strict` the worker serves it, so this is unused.
|
|
173
|
+
*/
|
|
149
174
|
pagesHost?: string | undefined;
|
|
150
175
|
};
|
|
151
176
|
/** Chosen ids from each group, keyed by group id. */
|
|
@@ -296,7 +321,7 @@ export function validate(manifest: Manifest): string[] {
|
|
|
296
321
|
`DNS at Simply.com cannot host ${workerHosts(manifest)[0]} — a Worker custom domain is created by Cloudflare, in a zone on Cloudflare`,
|
|
297
322
|
);
|
|
298
323
|
}
|
|
299
|
-
if (
|
|
324
|
+
if (!oneOrigin(manifest.layout) && manifest.shop.pagesHost && !/^[a-z0-9-]+\.github\.io$/i.test(manifest.shop.pagesHost)) {
|
|
300
325
|
problems.push(`Pages host "${manifest.shop.pagesHost}" should be <owner>.github.io`);
|
|
301
326
|
}
|
|
302
327
|
return problems;
|
package/src/regenerate.ts
CHANGED
|
@@ -30,6 +30,7 @@ export async function generateCommand(): Promise<number> {
|
|
|
30
30
|
[
|
|
31
31
|
...result.written.map((file) => `${color.green("+")} ${file}`),
|
|
32
32
|
...result.kept.map((file) => `${color.dim("=")} ${file} ${color.dim("(kept)")}`),
|
|
33
|
+
...result.retired.map((file) => `${color.red("-")} ${file} ${color.dim("(retired — no longer generated)")}`),
|
|
33
34
|
].join("\n"),
|
|
34
35
|
);
|
|
35
36
|
return project.manifest.layout === "strict" ? finishStrict(project.root) : 0;
|
package/src/wizard.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import color from "picocolors";
|
|
3
3
|
import { GROUPS, type Group } from "./catalog";
|
|
4
|
-
import { LAYOUTS, type Layout, type Manifest, zoneOf } from "./manifest";
|
|
4
|
+
import { LAYOUTS, type Layout, type Manifest, zoneOf , oneOrigin} from "./manifest";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The forms.
|
|
@@ -98,6 +98,10 @@ async function askGroup(group: Group, previous: string[] | undefined, alsoRequir
|
|
|
98
98
|
export async function runWizard(existing: Manifest | null, layout: Layout): Promise<Manifest> {
|
|
99
99
|
const monorepo = layout === "monorepo";
|
|
100
100
|
const frontend = layout !== "app";
|
|
101
|
+
// Only a monorepo publishes its storefront to GitHub Pages. In `strict`
|
|
102
|
+
// the worker serves it from its own assets, so there is no Pages host to
|
|
103
|
+
// ask for — and asking would imply a second origin that does not exist.
|
|
104
|
+
const onPages = !oneOrigin(layout);
|
|
101
105
|
|
|
102
106
|
const shop = unwrap(
|
|
103
107
|
await p.group(
|
|
@@ -171,7 +175,7 @@ export async function runWizard(existing: Manifest | null, layout: Layout): Prom
|
|
|
171
175
|
initialValue: existing?.shop.locale ?? "",
|
|
172
176
|
validate: (value) => (/^[a-z]{2}(-[A-Z]{2})?$/.test(value.trim()) ? undefined : "like da, or en-GB."),
|
|
173
177
|
}),
|
|
174
|
-
...(
|
|
178
|
+
...(onPages
|
|
175
179
|
? {
|
|
176
180
|
pagesHost: () =>
|
|
177
181
|
p.text({
|
|
@@ -211,7 +215,7 @@ export async function runWizard(existing: Manifest | null, layout: Layout): Prom
|
|
|
211
215
|
locale: shop.locale.trim(),
|
|
212
216
|
taxRegistered: (shop as { taxRegistered?: string }).taxRegistered === "yes",
|
|
213
217
|
zone: (shop as { zone?: string }).zone?.trim().toLowerCase() || undefined,
|
|
214
|
-
pagesHost:
|
|
218
|
+
pagesHost: onPages ? (shop as { pagesHost?: string }).pagesHost?.trim().toLowerCase() || undefined : undefined,
|
|
215
219
|
},
|
|
216
220
|
chosen,
|
|
217
221
|
};
|