@moneydevkit/create 0.3.3 → 0.4.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -9
- package/dist/index.cjs +16 -181
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +15 -181
- package/dist/index.js.map +1 -1
- package/dist/templates/nextjs/app/api/mdk/route.js +1 -0
- package/dist/templates/nextjs/app/api/mdk/route.ts +1 -0
- package/dist/templates/nextjs/app/checkout/[id]/page.js +8 -0
- package/dist/templates/nextjs/app/checkout/[id]/page.tsx +8 -0
- package/dist/templates/readme-sync.test.ts +56 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@ Developer onboarding CLI for Money Dev Kit. This package publishes the interacti
|
|
|
5
5
|
## Getting Started
|
|
6
6
|
|
|
7
7
|
1. Run `npx @moneydevkit/create@latest` from the root of your project. The CLI walks you through login, webhook verification, and writes your secrets to `.env.local` (or a path you pick) while also copying them to the clipboard by default.
|
|
8
|
-
2. If we detect a Next.js app (package.json `next` dependency, `next.config.*`, or an `app
|
|
9
|
-
3. Follow the prompts. When you reach your editor again, `MDK_ACCESS_TOKEN
|
|
8
|
+
2. If we detect a Next.js app (package.json `next` dependency, `next.config.*`, or an `app/` directory), we'll offer to install and scaffold `@moneydevkit/nextjs` for you.
|
|
9
|
+
3. Follow the prompts. When you reach your editor again, `MDK_ACCESS_TOKEN` and `MDK_MNEMONIC` are ready to go.
|
|
10
10
|
|
|
11
11
|
### Customize the flow with flags
|
|
12
12
|
|
|
@@ -16,7 +16,7 @@ Pass any of the options from the table below to skip prompts or run non-interact
|
|
|
16
16
|
npx @moneydevkit/create@latest \
|
|
17
17
|
--dir ./apps/storefront \
|
|
18
18
|
--env-target .env.production \
|
|
19
|
-
--webhook-url https://example.com
|
|
19
|
+
--webhook-url https://example.com \
|
|
20
20
|
--project-name "Storefront" \
|
|
21
21
|
--no-open --no-clipboard
|
|
22
22
|
```
|
|
@@ -41,9 +41,9 @@ The CLI still creates a device code but immediately authorises it using your coo
|
|
|
41
41
|
|
|
42
42
|
## Next.js scaffolding
|
|
43
43
|
|
|
44
|
-
- Auto-detects Next.js via `package.json`, `next.config.*`, or `app
|
|
44
|
+
- Auto-detects Next.js via `package.json`, `next.config.*`, or `app/` directory. If found, you'll be prompted to install and scaffold `@moneydevkit/nextjs`. Requires Next.js 15+ (per SDK peer deps).
|
|
45
45
|
- `--scaffold-nextjs` forces the install/scaffold (useful for CI); if no Next.js app is found, the CLI prints a warning and skips.
|
|
46
|
-
-
|
|
46
|
+
- Always scaffolds App Router files (`app/api/mdk/route.(ts|js)` and `app/checkout/[id]/page.(tsx|js)`).
|
|
47
47
|
- Existing files are left untouched; `next.config.*` is backed up if we need to wrap it with `withMdkCheckout`.
|
|
48
48
|
|
|
49
49
|
## Flags
|
|
@@ -58,7 +58,7 @@ The CLI still creates a device code but immediately authorises it using your coo
|
|
|
58
58
|
| `--no-clipboard` | Do not place secrets on the clipboard. |
|
|
59
59
|
| `--json` | Emit JSON result payloads (no interactive prompts).
|
|
60
60
|
| `--manual-login "<cookie>"` | Use a pre-generated dashboard session cookie instead of device flow. |
|
|
61
|
-
| `--webhook-url "<url>"` | Provide the
|
|
61
|
+
| `--webhook-url "<url>"` | Provide the domain when running in `--manual-login` or `--json` modes. |
|
|
62
62
|
| `--force-new-webhook` | Force creation of a new webhook even if one already exists for the URL. |
|
|
63
63
|
| `--scaffold-nextjs` | Force install + scaffold `@moneydevkit/nextjs` (warns and skips if no Next.js app is detected). |
|
|
64
64
|
|
|
@@ -75,8 +75,25 @@ npm run run:local # talk to a dashboard at http://localhost:3900
|
|
|
75
75
|
|
|
76
76
|
## Releasing to npm
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
All `@moneydevkit/*` packages share a unified version number and are released together.
|
|
79
|
+
|
|
80
|
+
### Beta releases (automatic)
|
|
81
|
+
|
|
82
|
+
Every push to `main` that modifies files in `packages/` triggers the `publish-beta` workflow:
|
|
83
|
+
1. All packages are bumped to the next beta version (e.g., `0.4.0-beta.0` → `0.4.0-beta.1`)
|
|
84
|
+
2. All packages are published to npm with the `beta` tag
|
|
85
|
+
|
|
86
|
+
Install the latest beta with:
|
|
87
|
+
```bash
|
|
88
|
+
npx @moneydevkit/create@beta
|
|
89
|
+
npm install @moneydevkit/nextjs@beta
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Stable releases
|
|
93
|
+
|
|
94
|
+
1. Create a GitHub release with a tag matching the version in package.json (e.g., if package.json has `0.4.0-beta.3`, create tag `v0.4.0`)
|
|
95
|
+
2. The `publish-release` workflow validates, publishes, and bumps to the next minor version
|
|
81
96
|
|
|
82
97
|
Once that workflow succeeds, `npx @moneydevkit/create@latest` automatically downloads the freshly published build.
|
|
98
|
+
|
|
99
|
+
See the [main README](../../README.md#releasing) for version flow examples and error cases.
|
package/dist/index.cjs
CHANGED
|
@@ -234,6 +234,11 @@ function writeFileWithBackup(filePath, content) {
|
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
// src/scaffold/nextjs.ts
|
|
237
|
+
var import_meta = {};
|
|
238
|
+
var templateRoot = new URL("../templates/nextjs/", import_meta.url);
|
|
239
|
+
function readTemplate(relativePath) {
|
|
240
|
+
return import_node_fs4.default.readFileSync(new URL(relativePath, templateRoot), "utf8");
|
|
241
|
+
}
|
|
237
242
|
function findExistingConfig(rootDir, preferred) {
|
|
238
243
|
if (preferred && import_node_fs4.default.existsSync(preferred)) return preferred;
|
|
239
244
|
const candidates = [
|
|
@@ -276,138 +281,12 @@ async function installNextjsPackage(rootDir, packageManager) {
|
|
|
276
281
|
return { installed: true, skipped: false };
|
|
277
282
|
}
|
|
278
283
|
function createAppRouteContent(isTypeScript) {
|
|
279
|
-
|
|
280
|
-
if (ext === "ts") {
|
|
281
|
-
return 'export { POST } from "@moneydevkit/nextjs/server/route";\n';
|
|
282
|
-
}
|
|
283
|
-
return 'export { POST } from "@moneydevkit/nextjs/server/route";\n';
|
|
284
|
+
return readTemplate(`app/api/mdk/route.${isTypeScript ? "ts" : "js"}`);
|
|
284
285
|
}
|
|
285
286
|
function createAppCheckoutPageContent(isTypeScript) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
"",
|
|
290
|
-
'import { Checkout } from "@moneydevkit/nextjs";',
|
|
291
|
-
"",
|
|
292
|
-
"type CheckoutPageProps = { params: { id: string } };",
|
|
293
|
-
"",
|
|
294
|
-
"export default function CheckoutPage({ params }: CheckoutPageProps) {",
|
|
295
|
-
" return <Checkout id={params.id} />;",
|
|
296
|
-
"}",
|
|
297
|
-
""
|
|
298
|
-
].join("\n");
|
|
299
|
-
}
|
|
300
|
-
return [
|
|
301
|
-
'"use client";',
|
|
302
|
-
"",
|
|
303
|
-
'import { Checkout } from "@moneydevkit/nextjs";',
|
|
304
|
-
"",
|
|
305
|
-
"export default function CheckoutPage({ params }) {",
|
|
306
|
-
" return <Checkout id={params.id} />;",
|
|
307
|
-
"}",
|
|
308
|
-
""
|
|
309
|
-
].join("\n");
|
|
310
|
-
}
|
|
311
|
-
function createPagesApiRouteContent(isTypeScript) {
|
|
312
|
-
if (isTypeScript) {
|
|
313
|
-
return [
|
|
314
|
-
'import type { NextApiRequest, NextApiResponse } from "next";',
|
|
315
|
-
'import { POST as appRouteHandler } from "@moneydevkit/nextjs/server/route";',
|
|
316
|
-
"",
|
|
317
|
-
"export default async function handler(req: NextApiRequest, res: NextApiResponse) {",
|
|
318
|
-
' const url = `http://${req.headers.host ?? "localhost"}${req.url ?? "/api/mdk"}`;',
|
|
319
|
-
" const request = new Request(url, {",
|
|
320
|
-
' method: req.method || "POST",',
|
|
321
|
-
" headers: req.headers as Record<string, string>,",
|
|
322
|
-
" body:",
|
|
323
|
-
' req.method === "GET" || req.method === "HEAD"',
|
|
324
|
-
" ? undefined",
|
|
325
|
-
' : typeof req.body === "string"',
|
|
326
|
-
" ? req.body",
|
|
327
|
-
" : JSON.stringify(req.body ?? {}),",
|
|
328
|
-
" });",
|
|
329
|
-
"",
|
|
330
|
-
" const response = await appRouteHandler(request);",
|
|
331
|
-
" res.status(response.status);",
|
|
332
|
-
" response.headers.forEach((value, key) => {",
|
|
333
|
-
" res.setHeader(key, value);",
|
|
334
|
-
" });",
|
|
335
|
-
" const body = await response.arrayBuffer();",
|
|
336
|
-
" res.send(Buffer.from(body));",
|
|
337
|
-
"}",
|
|
338
|
-
""
|
|
339
|
-
].join("\n");
|
|
340
|
-
}
|
|
341
|
-
return [
|
|
342
|
-
'import { POST as appRouteHandler } from "@moneydevkit/nextjs/server/route";',
|
|
343
|
-
"",
|
|
344
|
-
"export default async function handler(req, res) {",
|
|
345
|
-
' const url = `http://${req.headers.host ?? "localhost"}${req.url ?? "/api/mdk"}`;',
|
|
346
|
-
" const request = new Request(url, {",
|
|
347
|
-
' method: req.method || "POST",',
|
|
348
|
-
" headers: req.headers,",
|
|
349
|
-
" body:",
|
|
350
|
-
' req.method === "GET" || req.method === "HEAD"',
|
|
351
|
-
" ? undefined",
|
|
352
|
-
' : typeof req.body === "string"',
|
|
353
|
-
" ? req.body",
|
|
354
|
-
" : JSON.stringify(req.body ?? {}),",
|
|
355
|
-
" });",
|
|
356
|
-
"",
|
|
357
|
-
" const response = await appRouteHandler(request);",
|
|
358
|
-
" res.status(response.status);",
|
|
359
|
-
" response.headers.forEach((value, key) => {",
|
|
360
|
-
" res.setHeader(key, value);",
|
|
361
|
-
" });",
|
|
362
|
-
" const body = await response.arrayBuffer();",
|
|
363
|
-
" res.send(Buffer.from(body));",
|
|
364
|
-
"}",
|
|
365
|
-
""
|
|
366
|
-
].join("\n");
|
|
367
|
-
}
|
|
368
|
-
function createPagesCheckoutContent(isTypeScript) {
|
|
369
|
-
if (isTypeScript) {
|
|
370
|
-
return [
|
|
371
|
-
'"use client";',
|
|
372
|
-
"",
|
|
373
|
-
'import { useRouter } from "next/router";',
|
|
374
|
-
'import { Checkout } from "@moneydevkit/nextjs";',
|
|
375
|
-
"",
|
|
376
|
-
"export default function CheckoutPage() {",
|
|
377
|
-
" const router = useRouter();",
|
|
378
|
-
" const id = Array.isArray(router.query.id)",
|
|
379
|
-
" ? router.query.id[0]",
|
|
380
|
-
" : router.query.id;",
|
|
381
|
-
"",
|
|
382
|
-
" if (!id) {",
|
|
383
|
-
" return null;",
|
|
384
|
-
" }",
|
|
385
|
-
"",
|
|
386
|
-
" return <Checkout id={id as string} />;",
|
|
387
|
-
"}",
|
|
388
|
-
""
|
|
389
|
-
].join("\n");
|
|
390
|
-
}
|
|
391
|
-
return [
|
|
392
|
-
'"use client";',
|
|
393
|
-
"",
|
|
394
|
-
'import { useRouter } from "next/router";',
|
|
395
|
-
'import { Checkout } from "@moneydevkit/nextjs";',
|
|
396
|
-
"",
|
|
397
|
-
"export default function CheckoutPage() {",
|
|
398
|
-
" const router = useRouter();",
|
|
399
|
-
" const id = Array.isArray(router.query.id)",
|
|
400
|
-
" ? router.query.id[0]",
|
|
401
|
-
" : router.query.id;",
|
|
402
|
-
"",
|
|
403
|
-
" if (!id) {",
|
|
404
|
-
" return null;",
|
|
405
|
-
" }",
|
|
406
|
-
"",
|
|
407
|
-
" return <Checkout id={id} />;",
|
|
408
|
-
"}",
|
|
409
|
-
""
|
|
410
|
-
].join("\n");
|
|
287
|
+
return readTemplate(
|
|
288
|
+
`app/checkout/[id]/page.${isTypeScript ? "tsx" : "js"}`
|
|
289
|
+
);
|
|
411
290
|
}
|
|
412
291
|
function isTypeScriptConfig(configPath) {
|
|
413
292
|
return configPath.endsWith(".ts") || configPath.endsWith(".mts");
|
|
@@ -539,39 +418,6 @@ function scaffoldAppRouter(appDir, isTypeScript) {
|
|
|
539
418
|
}
|
|
540
419
|
return { added, skipped };
|
|
541
420
|
}
|
|
542
|
-
function scaffoldPagesRouter(pagesDir, isTypeScript) {
|
|
543
|
-
const added = [];
|
|
544
|
-
const skipped = [];
|
|
545
|
-
const apiPath = import_node_path5.default.join(
|
|
546
|
-
pagesDir,
|
|
547
|
-
"api",
|
|
548
|
-
`mdk.${isTypeScript ? "ts" : "js"}`
|
|
549
|
-
);
|
|
550
|
-
const apiResult = writeFileIfAbsent(
|
|
551
|
-
apiPath,
|
|
552
|
-
createPagesApiRouteContent(isTypeScript)
|
|
553
|
-
);
|
|
554
|
-
if (apiResult.status === "created") {
|
|
555
|
-
added.push(apiResult.path);
|
|
556
|
-
} else {
|
|
557
|
-
skipped.push(apiResult.path);
|
|
558
|
-
}
|
|
559
|
-
const checkoutPath = import_node_path5.default.join(
|
|
560
|
-
pagesDir,
|
|
561
|
-
"checkout",
|
|
562
|
-
`[id].${isTypeScript ? "tsx" : "js"}`
|
|
563
|
-
);
|
|
564
|
-
const checkoutResult = writeFileIfAbsent(
|
|
565
|
-
checkoutPath,
|
|
566
|
-
createPagesCheckoutContent(isTypeScript)
|
|
567
|
-
);
|
|
568
|
-
if (checkoutResult.status === "created") {
|
|
569
|
-
added.push(checkoutResult.path);
|
|
570
|
-
} else {
|
|
571
|
-
skipped.push(checkoutResult.path);
|
|
572
|
-
}
|
|
573
|
-
return { added, skipped };
|
|
574
|
-
}
|
|
575
421
|
async function scaffoldNextJs(options) {
|
|
576
422
|
const { detection, jsonMode, skipInstall } = options;
|
|
577
423
|
if (!detection.rootDir) {
|
|
@@ -588,21 +434,11 @@ async function scaffoldNextJs(options) {
|
|
|
588
434
|
`Could not automatically update ${import_node_path5.default.basename(configPath)} (${configResult.reason}). Please wrap your Next.js config with withMdkCheckout manually.`
|
|
589
435
|
);
|
|
590
436
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
} else if (detection.pagesDir) {
|
|
595
|
-
fileResults = scaffoldPagesRouter(
|
|
596
|
-
detection.pagesDir,
|
|
597
|
-
detection.usesTypeScript
|
|
598
|
-
);
|
|
599
|
-
} else {
|
|
600
|
-
fileResults = scaffoldAppRouter(
|
|
601
|
-
import_node_path5.default.join(rootDir, "app"),
|
|
602
|
-
detection.usesTypeScript
|
|
603
|
-
);
|
|
437
|
+
const appDir = detection.appDir ?? import_node_path5.default.join(rootDir, "app");
|
|
438
|
+
const fileResults = scaffoldAppRouter(appDir, detection.usesTypeScript);
|
|
439
|
+
if (!detection.appDir) {
|
|
604
440
|
warnings.push(
|
|
605
|
-
"No app/
|
|
441
|
+
"No app/ directory detected; created App Router scaffolding in app/."
|
|
606
442
|
);
|
|
607
443
|
}
|
|
608
444
|
if (!jsonMode) {
|
|
@@ -806,7 +642,7 @@ async function runDeviceFlow(options) {
|
|
|
806
642
|
p.note(
|
|
807
643
|
[
|
|
808
644
|
`Device code: ${device.userCode}`,
|
|
809
|
-
`
|
|
645
|
+
`Domain: ${webhookUrl}`,
|
|
810
646
|
"Open the authorization page, click Authorize, then return to this terminal."
|
|
811
647
|
].join("\n"),
|
|
812
648
|
"Authorize this device"
|
|
@@ -962,7 +798,7 @@ async function main() {
|
|
|
962
798
|
}
|
|
963
799
|
while (!webhookUrl) {
|
|
964
800
|
const webhookInput = await p.text({
|
|
965
|
-
message: "
|
|
801
|
+
message: "Domain for your application",
|
|
966
802
|
initialValue: "https://",
|
|
967
803
|
placeholder: "https://yourapp.com",
|
|
968
804
|
validate: (value) => isValidHttpUrl(value?.trim()) ? void 0 : "Enter a valid http(s) URL (e.g. https://yourapp.com)"
|
|
@@ -1029,7 +865,6 @@ async function main() {
|
|
|
1029
865
|
});
|
|
1030
866
|
const updates = {
|
|
1031
867
|
MDK_ACCESS_TOKEN: result.credentials.apiKey,
|
|
1032
|
-
MDK_WEBHOOK_SECRET: result.credentials.webhookSecret,
|
|
1033
868
|
MDK_MNEMONIC: result.mnemonic
|
|
1034
869
|
};
|
|
1035
870
|
ensureEnvFileExists(envPath);
|
|
@@ -1050,7 +885,7 @@ async function main() {
|
|
|
1050
885
|
}
|
|
1051
886
|
if (!flags.noClipboard) {
|
|
1052
887
|
await import_clipboardy.default.write(
|
|
1053
|
-
[`MDK_ACCESS_TOKEN=${updates.MDK_ACCESS_TOKEN}`, `
|
|
888
|
+
[`MDK_ACCESS_TOKEN=${updates.MDK_ACCESS_TOKEN}`, `MDK_MNEMONIC=${updates.MDK_MNEMONIC}`].join(
|
|
1054
889
|
"\n"
|
|
1055
890
|
)
|
|
1056
891
|
);
|