create-snagset 0.1.7 → 0.1.8
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 +5 -0
- package/dist/index.js +9 -5
- package/dist/scaffold.js +24 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,6 +19,11 @@ bun create snagset my-review # then: bun install && bun start
|
|
|
19
19
|
```
|
|
20
20
|
</details>
|
|
21
21
|
|
|
22
|
+
Already in the folder you want it in — a fresh `git init`, say? Pass `.`
|
|
23
|
+
instead of a name (`pnpm create snagset .`) and skip the `cd`. A `.git`, a
|
|
24
|
+
`.DS_Store` or an editor folder is fine; anything the scaffold would
|
|
25
|
+
overwrite is refused.
|
|
26
|
+
|
|
22
27
|
Bring a Postgres URL — a free Neon or Supabase branch, or a local install — and
|
|
23
28
|
put it in `.env` as `DATABASE_URL`. Open `http://localhost:8080` and create the
|
|
24
29
|
first owner — an instance nobody has claimed shows a setup screen rather than a
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { relative } from "node:path";
|
|
3
|
+
import { packageName, scaffold } from "./scaffold.js";
|
|
3
4
|
/**
|
|
4
5
|
* The bin. Argument handling and exit codes only — everything that touches the
|
|
5
6
|
* filesystem is in `scaffold.ts`, which has no side effects at import time and
|
|
@@ -9,22 +10,25 @@ const target = process.argv[2];
|
|
|
9
10
|
if (!target || target.startsWith("-")) {
|
|
10
11
|
process.stderr.write("usage: create-snagset <directory>\n\n" +
|
|
11
12
|
" pnpm create snagset my-review\n" +
|
|
13
|
+
" pnpm create snagset . (into the directory you are in)\n" +
|
|
12
14
|
" cd my-review && pnpm install && pnpm start\n");
|
|
13
15
|
process.exit(2);
|
|
14
16
|
}
|
|
17
|
+
let dir;
|
|
15
18
|
try {
|
|
16
|
-
scaffold(target);
|
|
19
|
+
dir = scaffold(target);
|
|
17
20
|
}
|
|
18
21
|
catch (e) {
|
|
19
22
|
process.stderr.write(`✗ ${e instanceof Error ? e.message : String(e)}\n`);
|
|
20
23
|
process.exit(2);
|
|
21
24
|
}
|
|
22
|
-
|
|
23
|
-
process.
|
|
25
|
+
// No `cd .` when it was scaffolded where we stand.
|
|
26
|
+
const into = relative(process.cwd(), dir);
|
|
27
|
+
process.stdout.write(`\n ✓ ${packageName(dir)}\n\n` +
|
|
24
28
|
` 1. Put a Postgres URL in .env as DATABASE_URL.\n` +
|
|
25
29
|
` A free Supabase or Neon project works, so does a local install;\n` +
|
|
26
30
|
` .env says which Supabase string goes where.\n\n` +
|
|
27
|
-
` cd ${
|
|
31
|
+
(into ? ` cd ${into}\n` : "") +
|
|
28
32
|
` pnpm install && pnpm start\n\n` +
|
|
29
33
|
` (npm, yarn and bun work the same way.)\n\n` +
|
|
30
34
|
` Then open http://localhost:8080 and create the first owner.\n` +
|
package/dist/scaffold.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join, resolve } from "node:path";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { randomBytes } from "node:crypto";
|
|
5
5
|
/**
|
|
@@ -70,15 +70,35 @@ export const RENAME = {
|
|
|
70
70
|
* A module with side effects at import time cannot be tested; the fix is not a
|
|
71
71
|
* cleverer guard.
|
|
72
72
|
*/
|
|
73
|
+
/**
|
|
74
|
+
* What may already be in the directory. `create-snagset .` runs in a folder
|
|
75
|
+
* somebody made first, and by then it usually holds a `.git` from `git init`
|
|
76
|
+
* or a `.DS_Store` from Finder — refusing those would make `.` useless. None of
|
|
77
|
+
* these is a file the template writes, so nothing here can be overwritten.
|
|
78
|
+
* The list `create-next-app` keeps, minus the files we would write over.
|
|
79
|
+
*/
|
|
80
|
+
export const HARMLESS = new Set([".git", ".DS_Store", "Thumbs.db", ".idea", ".vscode", "LICENSE"]);
|
|
81
|
+
/**
|
|
82
|
+
* The directory's own name, made a valid npm package name. `.` has to resolve
|
|
83
|
+
* first — `create-snagset .` once meant `"name": "."` — and a folder is often
|
|
84
|
+
* called something npm refuses, like `Client Review`.
|
|
85
|
+
*/
|
|
86
|
+
export function packageName(dir) {
|
|
87
|
+
return (basename(dir)
|
|
88
|
+
.toLowerCase()
|
|
89
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
90
|
+
.replace(/^[._-]+|-+$/g, "") || "snagset");
|
|
91
|
+
}
|
|
73
92
|
export function scaffold(target, cwd = process.cwd()) {
|
|
74
93
|
const dir = resolve(cwd, target);
|
|
75
94
|
// A non-empty directory is refused rather than merged into. Merging is how a
|
|
76
95
|
// scaffolder overwrites somebody's `.env`, and there is no undo for that.
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
const clutter = existsSync(dir) ? readdirSync(dir).filter((f) => !HARMLESS.has(f)) : [];
|
|
97
|
+
if (clutter.length > 0) {
|
|
98
|
+
throw new Error(`${target} already exists and is not empty (${clutter.slice(0, 3).join(", ")}${clutter.length > 3 ? ", …" : ""}).`);
|
|
79
99
|
}
|
|
80
100
|
mkdirSync(join(dir, "api"), { recursive: true });
|
|
81
|
-
const name =
|
|
101
|
+
const name = packageName(dir);
|
|
82
102
|
// Pinned to THIS scaffolder's version, so `create-snagset@1.4.2` produces a
|
|
83
103
|
// repo on `@snagset/server@1.4.2`. A caret here would let a fresh scaffold
|
|
84
104
|
// resolve to a server this template has never been run against.
|