@shivaedev/create-app 0.6.5 → 0.6.7
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/CHANGELOG.md +15 -0
- package/README.md +10 -0
- package/dist/appFiles.d.ts +3 -0
- package/dist/appFiles.d.ts.map +1 -0
- package/dist/appFiles.js +21 -0
- package/dist/appFiles.js.map +1 -0
- package/dist/cli.js +65 -65
- package/dist/createApp.d.ts.map +1 -1
- package/dist/createApp.js +18 -11
- package/dist/createApp.js.map +1 -1
- package/dist/packTemplate.d.ts.map +1 -1
- package/dist/packTemplate.js +17 -2
- package/dist/packTemplate.js.map +1 -1
- package/docs/roadmap.md +1 -0
- package/package.json +2 -1
- package/src/appFiles.ts +23 -0
- package/src/createApp.ts +19 -12
- package/src/packTemplate.ts +17 -2
- package/template.json +1 -1
package/dist/createApp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../src/createApp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../src/createApp.ts"],"names":[],"mappings":"AAGA,OAAO,EAAW,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,eAAO,MAAM,SAAS;kBAA8G,OAAO;mLAkDzI,CAAC"}
|
package/dist/createApp.js
CHANGED
|
@@ -3,10 +3,10 @@ import { randomBytes } from "node:crypto";
|
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { Console, Effect, FileSystem, Schema } from "effect";
|
|
5
5
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
6
|
+
import { appFile, databaseName } from "./appFiles.js";
|
|
6
7
|
import { CreateAppError } from "./CreateAppError.js";
|
|
7
8
|
import { commitGit, initializeGit } from "./initializeGit.js";
|
|
8
9
|
import { Template } from "./template.js";
|
|
9
|
-
const decodeName = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Record(Schema.String, Schema.Unknown)));
|
|
10
10
|
export const createApp = Effect.fn("CreateApp.createApp")(function* (folder, templatePath, options) {
|
|
11
11
|
const fs = yield* FileSystem.FileSystem;
|
|
12
12
|
const target = resolve(folder);
|
|
@@ -21,22 +21,29 @@ export const createApp = Effect.fn("CreateApp.createApp")(function* (folder, tem
|
|
|
21
21
|
yield* fs.makeDirectory(target, { recursive: true });
|
|
22
22
|
for (const entry of template) {
|
|
23
23
|
const path = join(target, entry.path);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const source = Buffer.from(entry.content, "base64");
|
|
25
|
+
const content = yield* Effect.try({
|
|
26
|
+
catch: (cause) => new CreateAppError({ message: String(cause) }),
|
|
27
|
+
try: () => ["package.json", ".env.example", "AGENTS.md", "README.md"].includes(entry.path)
|
|
28
|
+
? Buffer.from(appFile(entry.path, source.toString(), name))
|
|
29
|
+
: source,
|
|
30
|
+
});
|
|
29
31
|
yield* fs.makeDirectory(dirname(path), { recursive: true });
|
|
30
|
-
yield* fs.writeFile(path, content);
|
|
32
|
+
yield* fs.writeFile(path, content, { mode: 0o644 });
|
|
33
|
+
yield* fs.chmod(path, 0o644);
|
|
31
34
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.replace(/^[^a-z]/u, "app_$&")
|
|
35
|
-
.slice(0, 58);
|
|
35
|
+
yield* fs.symlink("AGENTS.md", join(target, "CLAUDE.md"));
|
|
36
|
+
const database = databaseName(name);
|
|
36
37
|
yield* fs.writeFileString(join(target, ".env.local"), `DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:55432/${database}_dev\nTEST_DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:55432/${database}_test\nBETTER_AUTH_SECRET=${randomBytes(32).toString("base64url")}\n`, { flag: "wx", mode: 0o600 });
|
|
37
38
|
const initialized = options.git && (yield* initializeGit(target));
|
|
38
39
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
39
40
|
const code = yield* spawner.exitCode(ChildProcess.make("pnpm", ["run", "setup"], { cwd: target, stderr: "inherit", stdout: "inherit" }));
|
|
41
|
+
for (const file of [...template.map((entry) => entry.path), "pnpm-lock.yaml"]) {
|
|
42
|
+
const path = join(target, file);
|
|
43
|
+
if (yield* fs.exists(path)) {
|
|
44
|
+
yield* fs.chmod(path, 0o644);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
40
47
|
if (code !== 0) {
|
|
41
48
|
return yield* new CreateAppError({ message: `pnpm run setup failed (exit ${code}). Run pnpm run setup in ${folder} to retry.` });
|
|
42
49
|
}
|
package/dist/createApp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createApp.js","sourceRoot":"","sources":["../src/createApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,
|
|
1
|
+
{"version":3,"file":"createApp.js","sourceRoot":"","sources":["../src/createApp.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packTemplate.d.ts","sourceRoot":"","sources":["../src/packTemplate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"packTemplate.d.ts","sourceRoot":"","sources":["../src/packTemplate.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAuBpD,eAAO,MAAM,YAAY,oJAsCvB,CAAC"}
|
package/dist/packTemplate.js
CHANGED
|
@@ -3,7 +3,22 @@ import { basename, join } from "node:path";
|
|
|
3
3
|
import { Effect, FileSystem, Schema } from "effect";
|
|
4
4
|
import { CreateAppError } from "#CreateAppError.ts";
|
|
5
5
|
import { prepareFile, Versions } from "#template.ts";
|
|
6
|
-
const
|
|
6
|
+
const appPaths = new Map([
|
|
7
|
+
["app-agents.md", "AGENTS.md"],
|
|
8
|
+
["app-readme.md", "README.md"],
|
|
9
|
+
["pnpm-workspace.copy.yaml", "pnpm-workspace.yaml"],
|
|
10
|
+
]);
|
|
11
|
+
const excluded = new Set([
|
|
12
|
+
"node_modules",
|
|
13
|
+
"dist",
|
|
14
|
+
"coverage",
|
|
15
|
+
"pnpm-lock.yaml",
|
|
16
|
+
".git",
|
|
17
|
+
"published-versions.json",
|
|
18
|
+
"AGENTS.md",
|
|
19
|
+
"CLAUDE.md",
|
|
20
|
+
"README.md",
|
|
21
|
+
]);
|
|
7
22
|
function included(path) {
|
|
8
23
|
return !excluded.has(basename(path)) && (!basename(path).startsWith(".env") || basename(path) === ".env.example");
|
|
9
24
|
}
|
|
@@ -21,7 +36,7 @@ export const packTemplate = Effect.fn("CreateApp.packTemplate")(function* (start
|
|
|
21
36
|
yield* visit(path);
|
|
22
37
|
}
|
|
23
38
|
else {
|
|
24
|
-
const target = path
|
|
39
|
+
const target = appPaths.get(path) ?? path;
|
|
25
40
|
const source = Buffer.from(yield* fs.readFile(join(starter, path)));
|
|
26
41
|
const content = yield* Effect.try({
|
|
27
42
|
catch: (cause) => new CreateAppError({ message: String(cause) }),
|
package/dist/packTemplate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packTemplate.js","sourceRoot":"","sources":["../src/packTemplate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAsB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAiB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEpE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"packTemplate.js","sourceRoot":"","sources":["../src/packTemplate.ts"],"names":[],"mappings":"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"}
|
package/docs/roadmap.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
- Packing snapshots `examples/starter` without local dependencies, build output, lockfiles or environment secrets.
|
|
7
7
|
- Existing nonempty folders are refused before any write or install.
|
|
8
8
|
- Each generated app has a git-ignored local environment with a fresh authentication secret and app-specific development and test database URLs.
|
|
9
|
+
- A generated app has its own named README, framework guidance and linked `CLAUDE.md`, matching example database URLs, and normal non-secret file permissions without template maintenance files or names.
|
|
9
10
|
- The generated app prepares both local databases before development and loads its test database URL from the local environment.
|
|
10
11
|
- The published-starter check runs the packed command's output through typecheck, build and PostgreSQL/authenticated HTTP tests.
|
|
11
12
|
- A generated app gets an initial Git commit outside an enclosing repository when Git is available; `--no-git` opts out.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/create-app",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "Create and install a Platform application from the maintained starter",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/create-app#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"dist",
|
|
33
33
|
"src",
|
|
34
34
|
"!src/**/*.test.ts",
|
|
35
|
+
"!src/**/*.spec.ts",
|
|
35
36
|
"!src/**/test-support",
|
|
36
37
|
"template.json",
|
|
37
38
|
"docs",
|
package/src/appFiles.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
const decodeManifest = Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Record(Schema.String, Schema.Unknown)));
|
|
4
|
+
|
|
5
|
+
export function databaseName(name: string) {
|
|
6
|
+
return name
|
|
7
|
+
.replaceAll(/[.-]/gu, "_")
|
|
8
|
+
.replace(/^[^a-z]/u, "app_$&")
|
|
9
|
+
.slice(0, 58);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function appFile(path: string, content: string, name: string) {
|
|
13
|
+
if (path === "package.json") {
|
|
14
|
+
return `${JSON.stringify({ ...decodeManifest(content), name }, null, "\t")}\n`;
|
|
15
|
+
}
|
|
16
|
+
if (path === ".env.example") {
|
|
17
|
+
return content.replaceAll("starter_dev", `${databaseName(name)}_dev`).replaceAll("starter_test", `${databaseName(name)}_test`);
|
|
18
|
+
}
|
|
19
|
+
if (["AGENTS.md", "README.md"].includes(path)) {
|
|
20
|
+
return content.replaceAll("{{appName}}", name);
|
|
21
|
+
}
|
|
22
|
+
return content;
|
|
23
|
+
}
|
package/src/createApp.ts
CHANGED
|
@@ -3,12 +3,11 @@ import { randomBytes } from "node:crypto";
|
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { Console, Effect, FileSystem, Schema } from "effect";
|
|
5
5
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
6
|
+
import { appFile, databaseName } from "./appFiles.ts";
|
|
6
7
|
import { CreateAppError } from "./CreateAppError.ts";
|
|
7
8
|
import { commitGit, initializeGit } from "./initializeGit.ts";
|
|
8
9
|
import { Template } from "./template.ts";
|
|
9
10
|
|
|
10
|
-
const decodeName = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Record(Schema.String, Schema.Unknown)));
|
|
11
|
-
|
|
12
11
|
export const createApp = Effect.fn("CreateApp.createApp")(function* (folder: string, templatePath: string, options: { readonly git: boolean }) {
|
|
13
12
|
const fs = yield* FileSystem.FileSystem;
|
|
14
13
|
const target = resolve(folder);
|
|
@@ -23,18 +22,20 @@ export const createApp = Effect.fn("CreateApp.createApp")(function* (folder: str
|
|
|
23
22
|
yield* fs.makeDirectory(target, { recursive: true });
|
|
24
23
|
for (const entry of template) {
|
|
25
24
|
const path = join(target, entry.path);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
const source = Buffer.from(entry.content, "base64");
|
|
26
|
+
const content = yield* Effect.try({
|
|
27
|
+
catch: (cause) => new CreateAppError({ message: String(cause) }),
|
|
28
|
+
try: () =>
|
|
29
|
+
["package.json", ".env.example", "AGENTS.md", "README.md"].includes(entry.path)
|
|
30
|
+
? Buffer.from(appFile(entry.path, source.toString(), name))
|
|
31
|
+
: source,
|
|
32
|
+
});
|
|
31
33
|
yield* fs.makeDirectory(dirname(path), { recursive: true });
|
|
32
|
-
yield* fs.writeFile(path, content);
|
|
34
|
+
yield* fs.writeFile(path, content, { mode: 0o644 });
|
|
35
|
+
yield* fs.chmod(path, 0o644);
|
|
33
36
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.replace(/^[^a-z]/u, "app_$&")
|
|
37
|
-
.slice(0, 58);
|
|
37
|
+
yield* fs.symlink("AGENTS.md", join(target, "CLAUDE.md"));
|
|
38
|
+
const database = databaseName(name);
|
|
38
39
|
yield* fs.writeFileString(
|
|
39
40
|
join(target, ".env.local"),
|
|
40
41
|
`DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:55432/${database}_dev\nTEST_DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:55432/${database}_test\nBETTER_AUTH_SECRET=${randomBytes(32).toString("base64url")}\n`,
|
|
@@ -43,6 +44,12 @@ export const createApp = Effect.fn("CreateApp.createApp")(function* (folder: str
|
|
|
43
44
|
const initialized = options.git && (yield* initializeGit(target));
|
|
44
45
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
45
46
|
const code = yield* spawner.exitCode(ChildProcess.make("pnpm", ["run", "setup"], { cwd: target, stderr: "inherit", stdout: "inherit" }));
|
|
47
|
+
for (const file of [...template.map((entry) => entry.path), "pnpm-lock.yaml"]) {
|
|
48
|
+
const path = join(target, file);
|
|
49
|
+
if (yield* fs.exists(path)) {
|
|
50
|
+
yield* fs.chmod(path, 0o644);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
46
53
|
if (code !== 0) {
|
|
47
54
|
return yield* new CreateAppError({ message: `pnpm run setup failed (exit ${code}). Run pnpm run setup in ${folder} to retry.` });
|
|
48
55
|
}
|
package/src/packTemplate.ts
CHANGED
|
@@ -4,7 +4,22 @@ import { Effect, FileSystem, type PlatformError, Schema } from "effect";
|
|
|
4
4
|
import { CreateAppError } from "#CreateAppError.ts";
|
|
5
5
|
import { prepareFile, type Template, Versions } from "#template.ts";
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const appPaths = new Map([
|
|
8
|
+
["app-agents.md", "AGENTS.md"],
|
|
9
|
+
["app-readme.md", "README.md"],
|
|
10
|
+
["pnpm-workspace.copy.yaml", "pnpm-workspace.yaml"],
|
|
11
|
+
]);
|
|
12
|
+
const excluded = new Set([
|
|
13
|
+
"node_modules",
|
|
14
|
+
"dist",
|
|
15
|
+
"coverage",
|
|
16
|
+
"pnpm-lock.yaml",
|
|
17
|
+
".git",
|
|
18
|
+
"published-versions.json",
|
|
19
|
+
"AGENTS.md",
|
|
20
|
+
"CLAUDE.md",
|
|
21
|
+
"README.md",
|
|
22
|
+
]);
|
|
8
23
|
function included(path: string) {
|
|
9
24
|
return !excluded.has(basename(path)) && (!basename(path).startsWith(".env") || basename(path) === ".env.example");
|
|
10
25
|
}
|
|
@@ -24,7 +39,7 @@ export const packTemplate = Effect.fn("CreateApp.packTemplate")(function* (start
|
|
|
24
39
|
if ((yield* fs.stat(join(starter, path))).type === "Directory") {
|
|
25
40
|
yield* visit(path);
|
|
26
41
|
} else {
|
|
27
|
-
const target = path
|
|
42
|
+
const target = appPaths.get(path) ?? path;
|
|
28
43
|
const source = Buffer.from(yield* fs.readFile(join(starter, path)));
|
|
29
44
|
const content = yield* Effect.try({
|
|
30
45
|
catch: (cause) => new CreateAppError({ message: String(cause) }),
|