create-seamless 0.1.0 → 0.1.2

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.
Files changed (52) hide show
  1. package/README.md +109 -51
  2. package/dist/commands/bootstrapAdmin.js +96 -0
  3. package/dist/commands/bootstrapAdmin.js.map +1 -0
  4. package/dist/commands/check.js +92 -0
  5. package/dist/commands/check.js.map +1 -0
  6. package/dist/commands/help.js +103 -0
  7. package/dist/commands/help.js.map +1 -0
  8. package/dist/commands/init.js +73 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/core/bootstrapSecret.js +31 -0
  11. package/dist/core/bootstrapSecret.js.map +1 -0
  12. package/dist/core/configure.js +25 -0
  13. package/dist/core/configure.js.map +1 -0
  14. package/dist/core/env.js +35 -0
  15. package/dist/core/env.js.map +1 -0
  16. package/dist/core/exec.js +17 -0
  17. package/dist/core/exec.js.map +1 -0
  18. package/dist/core/fetch.js +9 -0
  19. package/dist/core/fetch.js.map +1 -0
  20. package/dist/core/help.js +75 -0
  21. package/dist/core/help.js.map +1 -0
  22. package/dist/core/inspect.js +15 -0
  23. package/dist/core/inspect.js.map +1 -0
  24. package/dist/core/jwks.js +19 -0
  25. package/dist/core/jwks.js.map +1 -0
  26. package/dist/core/output.js +94 -0
  27. package/dist/core/output.js.map +1 -0
  28. package/dist/core/packageManager.js +10 -0
  29. package/dist/core/packageManager.js.map +1 -0
  30. package/dist/core/paths.js +7 -0
  31. package/dist/core/paths.js.map +1 -0
  32. package/dist/core/secrets.js +8 -0
  33. package/dist/core/secrets.js.map +1 -0
  34. package/dist/generators/auth/auth.js +47 -0
  35. package/dist/generators/auth/auth.js.map +1 -0
  36. package/dist/generators/backend/express.js +13 -0
  37. package/dist/generators/backend/express.js.map +1 -0
  38. package/dist/generators/config/config.js +43 -0
  39. package/dist/generators/config/config.js.map +1 -0
  40. package/dist/generators/docker/docker.js +263 -0
  41. package/dist/generators/docker/docker.js.map +1 -0
  42. package/dist/generators/frontend/react.js +13 -0
  43. package/dist/generators/frontend/react.js.map +1 -0
  44. package/dist/index.js +43 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/prompts/projectSetup.js +73 -0
  47. package/dist/prompts/projectSetup.js.map +1 -0
  48. package/dist/utils/repoUtils.js +23 -0
  49. package/dist/utils/repoUtils.js.map +1 -0
  50. package/dist/utils/writeEnv.js +9 -0
  51. package/dist/utils/writeEnv.js.map +1 -0
  52. package/package.json +7 -5
@@ -0,0 +1,263 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { fetchEnvExample } from "../../core/fetch.js";
4
+ import { parseEnv, parseEnvString } from "../../core/env.js";
5
+ import { generateSecret } from "../../core/secrets.js";
6
+ import { generateJWKS } from "../../core/jwks.js";
7
+ export async function generateDockerCompose(root, options) {
8
+ const { compose, shared } = await buildCompose(options, root);
9
+ fs.writeFileSync(path.join(root, "docker-compose.yml"), compose.trim() + "\n");
10
+ console.log("Docker compose created.");
11
+ return shared;
12
+ }
13
+ async function buildCompose(options, root) {
14
+ const { authMode, adminMode, includeAdmin } = options;
15
+ const { service: authBlock, shared } = await authService(authMode, root);
16
+ return {
17
+ compose: `
18
+ services:
19
+ db:
20
+ image: postgres:16
21
+ container_name: seamless-db
22
+ ports:
23
+ - "5432:5432"
24
+ environment:
25
+ POSTGRES_USER: myuser
26
+ POSTGRES_PASSWORD: mypassword
27
+ POSTGRES_DB: postgres
28
+ volumes:
29
+ - pgdata:/var/lib/postgresql/data
30
+
31
+ ${authBlock}
32
+
33
+ ${apiService(shared)}
34
+
35
+ ${webService()}
36
+
37
+ ${includeAdmin ? adminService(adminMode) : ""}
38
+
39
+ volumes:
40
+ pgdata:
41
+ `,
42
+ shared,
43
+ };
44
+ }
45
+ async function authService(mode, root) {
46
+ if (mode === "local") {
47
+ const shared = await configureAuthLocalEnv(root);
48
+ return {
49
+ service: `
50
+ auth:
51
+ container_name: seamless-auth
52
+ build:
53
+ context: ./auth
54
+ dockerfile: Dockerfile.dev
55
+ ports:
56
+ - "5312:5312"
57
+ env_file:
58
+ - ./auth/.env
59
+ environment:
60
+ DB_HOST: db
61
+ ISSUER: http://auth:5312
62
+ volumes:
63
+ - ./auth:/app
64
+ - /app/node_modules
65
+ depends_on:
66
+ - db
67
+ `,
68
+ shared,
69
+ };
70
+ }
71
+ return await authServiceDocker();
72
+ }
73
+ function apiService(shared) {
74
+ return `
75
+ api:
76
+ container_name: api
77
+ build: ./api
78
+ ports:
79
+ - "3000:3000"
80
+ env_file:
81
+ - ./api/.env
82
+ environment:
83
+ AUTH_SERVER_URL: http://auth:5312
84
+ UI_ORIGINS: http://localhost:5173,http://localhost:5174
85
+ DB_HOST: db
86
+ API_SERVICE_TOKEN: ${shared.apiToken}
87
+ JWKS_KID: ${shared.kid}
88
+ volumes:
89
+ - ./api:/app
90
+ - /app/node_modules
91
+ depends_on:
92
+ - db
93
+ - auth
94
+ `;
95
+ }
96
+ function webService() {
97
+ return `
98
+ web:
99
+ container_name: web
100
+ build: ./web
101
+ ports:
102
+ - "5173:80"
103
+ environment:
104
+ API_URL: http://localhost:3000/
105
+ volumes:
106
+ - ./web:/app
107
+ - /app/node_modules
108
+ depends_on:
109
+ - api
110
+ `;
111
+ }
112
+ async function authServiceDocker() {
113
+ const raw = await fetchEnvExample();
114
+ const parsed = parseEnvString(raw);
115
+ const { env, shared } = buildAuthEnv(parsed, "docker");
116
+ const envBlock = envToDockerBlock(env);
117
+ return {
118
+ service: `
119
+ auth:
120
+ image: ghcr.io/fells-code/seamless-auth-api:latest
121
+ container_name: seamless-auth
122
+ ports:
123
+ - "5312:5312"
124
+ environment:
125
+ ${envBlock}
126
+ depends_on:
127
+ - db
128
+ `,
129
+ shared,
130
+ };
131
+ }
132
+ function adminService(mode) {
133
+ if (mode === "source") {
134
+ return `
135
+ admin:
136
+ container_name: admin
137
+ build: ./admin
138
+ ports:
139
+ - "5174:80"
140
+ environment:
141
+ API_URL: http://localhost:3000/
142
+ AUTH_MODE: server
143
+ volumes:
144
+ - ./admin:/app
145
+ - /app/node_modules
146
+ depends_on:
147
+ - api
148
+ `;
149
+ }
150
+ return `
151
+ admin:
152
+ image: ghcr.io/fells-code/seamless-auth-admin-dashboard:latest
153
+ container_name: admin
154
+ ports:
155
+ - "5174:80"
156
+ environment:
157
+ API_URL: http://localhost:3000/
158
+ depends_on:
159
+ - api
160
+ `;
161
+ }
162
+ function buildAuthEnv(env, mode) {
163
+ const apiToken = generateSecret(32);
164
+ const bootstrapSecret = generateSecret(32);
165
+ env.SEAMLESS_BOOTSTRAP_ENABLED = "true";
166
+ env.SEAMLESS_BOOTSTRAP_SECRET = bootstrapSecret;
167
+ env.PORT = "5312";
168
+ env.NODE_ENV = "development";
169
+ env.AUTH_MODE = "server";
170
+ env.ISSUER = "http://auth:5312";
171
+ env.DB_HOST = mode === "docker" ? "db" : "localhost";
172
+ env.DB_PORT = "5432";
173
+ env.API_SERVICE_TOKEN = apiToken;
174
+ let kid = "main";
175
+ env.JWKS_ACTIVE_KID = kid;
176
+ if (mode === "docker") {
177
+ const jwks = buildJWKSConfig();
178
+ kid = jwks.kid;
179
+ env.SEAMLESS_JWKS_ACTIVE_KID = jwks.kid;
180
+ env.JWKS_ACTIVE_KID = jwks.kid;
181
+ env[`SEAMLESS_JWKS_KEY_${jwks.kid}_PRIVATE`] = jwks.privateKey;
182
+ env.JWKS_PUBLIC_KEYS = jwks.publicJwksJson;
183
+ }
184
+ env.APP_ORIGINS = "http://localhost:3000";
185
+ env.ORIGINS = "http://localhost:5173";
186
+ return {
187
+ env,
188
+ shared: {
189
+ apiToken,
190
+ kid,
191
+ bootstrapSecret,
192
+ },
193
+ };
194
+ }
195
+ export function envToDockerBlock(env) {
196
+ return Object.entries(env)
197
+ .map(([k, v]) => {
198
+ if (v.includes("\n")) {
199
+ return ` ${k}: |\n${indentMultiline(v, 8)}`;
200
+ }
201
+ return ` ${k}: ${v}`;
202
+ })
203
+ .join("\n");
204
+ }
205
+ function indentMultiline(value, spaces) {
206
+ const indent = " ".repeat(spaces);
207
+ return value
208
+ .split("\n")
209
+ .map((line) => `${indent}${line}`)
210
+ .join("\n");
211
+ }
212
+ export function buildJWKSConfig() {
213
+ const kid = "main";
214
+ const { publicKey, privateKey } = generateJWKS();
215
+ return {
216
+ kid,
217
+ privateKey,
218
+ publicKey,
219
+ publicJwksJson: JSON.stringify({
220
+ keys: [
221
+ {
222
+ kid,
223
+ pem: publicKey,
224
+ },
225
+ ],
226
+ }, null, 2),
227
+ };
228
+ }
229
+ export async function configureAuthLocalEnv(root) {
230
+ const authDir = path.join(root, "auth");
231
+ const envExamplePath = path.join(authDir, ".env.example");
232
+ const envPath = path.join(authDir, ".env");
233
+ if (!fs.existsSync(envExamplePath)) {
234
+ throw new Error(".env.example not found in auth directory");
235
+ }
236
+ const raw = fs.readFileSync(envExamplePath, "utf-8");
237
+ const parsed = parseEnvString(raw);
238
+ const { env, shared } = buildAuthEnv(parsed, "local");
239
+ writeEnvFile(envPath, env);
240
+ return shared;
241
+ }
242
+ function writeEnvFile(filePath, env) {
243
+ const content = Object.entries(env)
244
+ .map(([k, v]) => {
245
+ if (v.includes("\n")) {
246
+ return `${k}="${escapeMultiline(v)}"`;
247
+ }
248
+ return `${k}=${v}`;
249
+ })
250
+ .join("\n");
251
+ fs.writeFileSync(filePath, content + "\n");
252
+ }
253
+ function escapeMultiline(value) {
254
+ return value.replace(/\n/g, "\\n");
255
+ }
256
+ export function extractSharedFromExistingEnv(root) {
257
+ const env = parseEnv(path.join(root, "auth", ".env"));
258
+ return {
259
+ apiToken: env.API_SERVICE_TOKEN,
260
+ kid: env.JWKS_ACTIVE_KID || "main",
261
+ };
262
+ }
263
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../../src/generators/docker/docker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import path from "path";
2
+ import { cloneRepo, removeGitDir, copyEnvExample, } from "../../utils/repoUtils.js";
3
+ const WEB_STARTER_REPO = "https://github.com/fells-code/seamless-auth-starter-react.git";
4
+ export async function generateReactStarter(context) {
5
+ const { root } = context;
6
+ const webDir = path.join(root, "web");
7
+ console.log("Cloning Seamless Auth React starter...");
8
+ await cloneRepo(WEB_STARTER_REPO, webDir);
9
+ removeGitDir(webDir);
10
+ copyEnvExample(webDir);
11
+ console.log("Web starter ready.");
12
+ }
13
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../../src/generators/frontend/react.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,cAAc,GACf,MAAM,0BAA0B,CAAC;AAElC,MAAM,gBAAgB,GACpB,+DAA+D,CAAC;AAElE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAyB;IAClE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAEtC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IAEtD,MAAM,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAE1C,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AACpC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+ import { runCLI } from "./commands/init.js";
3
+ import { runCheck } from "./commands/check.js";
4
+ import { printHelp } from "./commands/help.js";
5
+ import pkg from "../package.json" with { type: "json" };
6
+ import { runBootstrapAdmin } from "./commands/bootstrapAdmin.js";
7
+ export const VERSION = pkg.version;
8
+ const args = process.argv.slice(2);
9
+ const command = args[0];
10
+ async function main() {
11
+ if (!command) {
12
+ printHelp();
13
+ return;
14
+ }
15
+ if (command === "-h" || command === "--help") {
16
+ printHelp();
17
+ return;
18
+ }
19
+ if (command === "-v" || command === "--version") {
20
+ console.log(VERSION);
21
+ return;
22
+ }
23
+ if (command === "init") {
24
+ const projectName = args[1];
25
+ await runCLI(projectName);
26
+ return;
27
+ }
28
+ if (command === "check") {
29
+ await runCheck();
30
+ return;
31
+ }
32
+ if (command === "bootstrap-admin") {
33
+ const email = args[1];
34
+ await runBootstrapAdmin(email);
35
+ return;
36
+ }
37
+ await runCLI(command);
38
+ }
39
+ main().catch((err) => {
40
+ console.error("Error:", err.message);
41
+ process.exit(1);
42
+ });
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,GAAG,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEjE,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;AACnC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAExB,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7C,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,QAAQ,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,iBAAiB,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { confirm, select } from "@clack/prompts";
2
+ export async function runProjectSetupPrompts() {
3
+ const webFramework = (await select({
4
+ message: "Web framework",
5
+ options: [
6
+ { value: "react", label: "React (Vite)" },
7
+ { value: "next", label: "Next.js (coming soon)", disabled: true },
8
+ ],
9
+ }));
10
+ const apiFramework = (await select({
11
+ message: "Backend framework",
12
+ options: [
13
+ { value: "express", label: "Express" },
14
+ { value: "fastify", label: "Fastify (coming soon)", disabled: true },
15
+ { value: "fastAPI", label: "FastAPI (coming soon)", disabled: true },
16
+ { value: "axum", label: "Rust Axum (coming soon)", disabled: true },
17
+ ],
18
+ }));
19
+ const authMode = (await select({
20
+ message: "How would you like to run SeamlessAuth?",
21
+ options: [
22
+ {
23
+ value: "docker",
24
+ label: "Docker container (recommended)",
25
+ },
26
+ {
27
+ value: "local",
28
+ label: "Local dev server (advanced)",
29
+ },
30
+ ],
31
+ }));
32
+ const includeAdmin = await confirm({
33
+ message: "Include Admin Dashboard?",
34
+ initialValue: true,
35
+ });
36
+ let adminMode = "image";
37
+ if (includeAdmin) {
38
+ adminMode = (await select({
39
+ message: "Admin dashboard source",
40
+ options: [
41
+ {
42
+ value: "image",
43
+ label: "Use official Docker image (recommended)",
44
+ },
45
+ {
46
+ value: "source",
47
+ label: "Clone repo for modification",
48
+ },
49
+ ],
50
+ }));
51
+ }
52
+ let useDocker = true;
53
+ if (authMode === "local") {
54
+ const confirmDocker = await confirm({
55
+ message: "Auth server still requires Docker for full stack. Enable Docker?",
56
+ initialValue: true,
57
+ });
58
+ if (!confirmDocker) {
59
+ console.log("\nDocker is required for full seamless stack. Enabling automatically.\n");
60
+ }
61
+ }
62
+ return {
63
+ web: true,
64
+ webFramework,
65
+ api: true,
66
+ apiFramework,
67
+ authMode,
68
+ useDocker: true,
69
+ includeAdmin,
70
+ adminMode,
71
+ };
72
+ }
73
+ //# sourceMappingURL=projectSetup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectSetup.js","sourceRoot":"","sources":["../../src/prompts/projectSetup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAOjD,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,MAAM,YAAY,GAAG,CAAC,MAAM,MAAM,CAAC;QACjC,OAAO,EAAE,eAAe;QACxB,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE;YACzC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,IAAI,EAAE;SAClE;KACF,CAAC,CAAiB,CAAC;IAEpB,MAAM,YAAY,GAAG,CAAC,MAAM,MAAM,CAAC;QACjC,OAAO,EAAE,mBAAmB;QAC5B,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACtC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,IAAI,EAAE;YACpE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE,QAAQ,EAAE,IAAI,EAAE;YACpE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,yBAAyB,EAAE,QAAQ,EAAE,IAAI,EAAE;SACpE;KACF,CAAC,CAAiB,CAAC;IAEpB,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC;QAC7B,OAAO,EAAE,yCAAyC;QAClD,OAAO,EAAE;YACP;gBACE,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,gCAAgC;aACxC;YACD;gBACE,KAAK,EAAE,OAAO;gBACd,KAAK,EAAE,6BAA6B;aACrC;SACF;KACF,CAAC,CAAa,CAAC;IAEhB,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC;QACjC,OAAO,EAAE,0BAA0B;QACnC,YAAY,EAAE,IAAI;KACnB,CAAC,CAAC;IAEH,IAAI,SAAS,GAAc,OAAO,CAAC;IAEnC,IAAI,YAAY,EAAE,CAAC;QACjB,SAAS,GAAG,CAAC,MAAM,MAAM,CAAC;YACxB,OAAO,EAAE,wBAAwB;YACjC,OAAO,EAAE;gBACP;oBACE,KAAK,EAAE,OAAO;oBACd,KAAK,EAAE,yCAAyC;iBACjD;gBACD;oBACE,KAAK,EAAE,QAAQ;oBACf,KAAK,EAAE,6BAA6B;iBACrC;aACF;SACF,CAAC,CAAc,CAAC;IACnB,CAAC;IAED,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC;YAClC,OAAO,EACL,kEAAkE;YACpE,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CACT,yEAAyE,CAC1E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,EAAE,IAAI;QACT,YAAY;QAEZ,GAAG,EAAE,IAAI;QACT,YAAY;QAEZ,QAAQ;QACR,SAAS,EAAE,IAAI;QAEf,YAAY;QACZ,SAAS;KACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { runCommand } from "../core/exec.js";
4
+ export async function cloneRepo(repoUrl, dest) {
5
+ const parentDir = path.dirname(dest);
6
+ const folderName = path.basename(dest);
7
+ fs.mkdirSync(parentDir, { recursive: true });
8
+ await runCommand("git", ["clone", "--depth", "1", repoUrl, folderName], parentDir);
9
+ }
10
+ export function removeGitDir(projectRoot) {
11
+ const gitDir = path.join(projectRoot, ".git");
12
+ if (fs.existsSync(gitDir)) {
13
+ fs.rmSync(gitDir, { recursive: true, force: true });
14
+ }
15
+ }
16
+ export function copyEnvExample(projectRoot) {
17
+ const envExample = path.join(projectRoot, ".env.example");
18
+ const env = path.join(projectRoot, ".env");
19
+ if (fs.existsSync(envExample) && !fs.existsSync(env)) {
20
+ fs.copyFileSync(envExample, env);
21
+ }
22
+ }
23
+ //# sourceMappingURL=repoUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repoUtils.js","sourceRoot":"","sources":["../../src/utils/repoUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEvC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,UAAU,CACd,KAAK,EACL,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,CAAC,EAC9C,SAAS,CACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAE3C,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ export function writeEnv(dir, values) {
4
+ const env = Object.entries(values)
5
+ .map(([k, v]) => `${k}=${v}`)
6
+ .join("\n");
7
+ fs.writeFileSync(path.join(dir, ".env"), env + "\n");
8
+ }
9
+ //# sourceMappingURL=writeEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeEnv.js","sourceRoot":"","sources":["../../src/utils/writeEnv.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,MAA2B;IAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAC/B,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;SAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC;AACvD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-seamless",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "The starter script for Seamless Auth",
5
5
  "homepage": "https://github.com/fells-code/create-seamless#readme",
6
6
  "bugs": {
@@ -13,15 +13,17 @@
13
13
  "license": "AGPL-3.0-only",
14
14
  "author": "Fells Code, LLC",
15
15
  "bin": {
16
- "create-seamless": "dist/index.js"
16
+ "create-seamless": "dist/index.js",
17
+ "seamless": "dist/index.js"
17
18
  },
18
19
  "type": "module",
19
20
  "scripts": {
20
21
  "build": "tsc",
21
22
  "dev": "tsx src/index.ts",
22
- "clean": "rm -rf dist"
23
+ "clean": "rm -rf dist",
24
+ "prepublishOnly": "npm run build"
23
25
  },
24
- "main": "index.js",
26
+ "main": "dist/index.js",
25
27
  "files": [
26
28
  "dist",
27
29
  "templates",
@@ -39,4 +41,4 @@
39
41
  "tsx": "^4.21.0",
40
42
  "typescript": "^5.9.3"
41
43
  }
42
- }
44
+ }