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,25 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import { parseEnv, writeEnv } from "./env.js";
4
+ import { generateSecret } from "./secrets.js";
5
+ export function configureApiEnv(root, shared) {
6
+ const apiEnvPath = path.join(root, "api", ".env");
7
+ if (!fs.existsSync(apiEnvPath))
8
+ return;
9
+ const env = parseEnv(apiEnvPath);
10
+ env.AUTH_SERVER_URL = "http://localhost:5312";
11
+ env.API_SERVICE_TOKEN = shared.apiToken;
12
+ env.JWKS_KID = shared.kid;
13
+ env.COOKIE_SIGNING_KEY = generateSecret(32);
14
+ writeEnv(apiEnvPath, env);
15
+ }
16
+ export function configureWebEnv(root) {
17
+ const webEnvPath = path.join(root, "web", ".env");
18
+ if (!fs.existsSync(webEnvPath))
19
+ return;
20
+ const env = parseEnv(webEnvPath);
21
+ env.VITE_AUTH_SERVER_URL = "http://localhost:5312";
22
+ env.VITE_API_URL = "http://localhost:3000";
23
+ writeEnv(webEnvPath, env);
24
+ }
25
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../../src/core/configure.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAW;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAElD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO;IAEvC,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEjC,GAAG,CAAC,eAAe,GAAG,uBAAuB,CAAC;IAC9C,GAAG,CAAC,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC;IACxC,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC;IAC1B,GAAG,CAAC,kBAAkB,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IAE5C,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAElD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO;IAEvC,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEjC,GAAG,CAAC,oBAAoB,GAAG,uBAAuB,CAAC;IACnD,GAAG,CAAC,YAAY,GAAG,uBAAuB,CAAC;IAE3C,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,35 @@
1
+ import fs from "fs";
2
+ export function parseEnv(filePath) {
3
+ const content = fs.readFileSync(filePath, "utf-8");
4
+ const lines = content.split("\n");
5
+ const env = {};
6
+ for (const line of lines) {
7
+ if (!line || line.startsWith("#"))
8
+ continue;
9
+ const [key, ...rest] = line.split("=");
10
+ if (!key)
11
+ continue;
12
+ env[key.trim()] = rest.join("=").trim();
13
+ }
14
+ return env;
15
+ }
16
+ export function parseEnvString(content) {
17
+ const lines = content.split("\n");
18
+ const env = {};
19
+ for (const line of lines) {
20
+ if (!line || line.startsWith("#"))
21
+ continue;
22
+ const [key, ...rest] = line.split("=");
23
+ if (!key)
24
+ continue;
25
+ env[key.trim()] = rest.join("=").trim();
26
+ }
27
+ return env;
28
+ }
29
+ export function writeEnv(filePath, env) {
30
+ const content = Object.entries(env)
31
+ .map(([k, v]) => `${k}=${v}`)
32
+ .join("\n");
33
+ fs.writeFileSync(filePath, content + "\n");
34
+ }
35
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,MAAM,GAAG,GAA2B,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAE5C,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,MAAM,GAAG,GAA2B,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAE5C,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAEvC,IAAI,CAAC,GAAG;YAAE,SAAS;QAEnB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,QAAgB,EAAE,GAA2B;IACpE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;SAChC,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,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { spawn } from "child_process";
2
+ export function runCommand(command, args, cwd) {
3
+ return new Promise((resolve, reject) => {
4
+ const child = spawn(command, args, {
5
+ stdio: "inherit",
6
+ cwd,
7
+ shell: true,
8
+ });
9
+ child.on("close", (code) => {
10
+ if (code === 0)
11
+ resolve();
12
+ else
13
+ reject(new Error(`${command} failed`));
14
+ });
15
+ });
16
+ }
17
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/core/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,MAAM,UAAU,UAAU,CACxB,OAAe,EACf,IAAc,EACd,GAAW;IAEX,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,KAAK,EAAE,SAAS;YAChB,GAAG;YACH,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;;gBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,SAAS,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,9 @@
1
+ export async function fetchEnvExample() {
2
+ const url = "https://raw.githubusercontent.com/fells-code/seamless-auth-api/main/.env.example";
3
+ const res = await fetch(url);
4
+ if (!res.ok) {
5
+ throw new Error("Failed to fetch auth env.example");
6
+ }
7
+ return await res.text();
8
+ }
9
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/core/fetch.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,GAAG,GACP,kFAAkF,CAAC;IAErF,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { VERSION } from "../index.js";
2
+ export function printHelp() {
3
+ console.log(`
4
+ create-seamless v${VERSION}
5
+
6
+ Seamless Auth CLI — scaffold and manage full-stack authentication systems.
7
+
8
+ ────────────────────────────────────────────
9
+
10
+ USAGE
11
+
12
+ seamless init [project-name]
13
+ seamless check
14
+ seamless --help
15
+ seamless --version
16
+
17
+ ────────────────────────────────────────────
18
+
19
+ COMMANDS
20
+
21
+ init [project-name]
22
+ Scaffold a new Seamless Auth project
23
+
24
+ Without a name:
25
+ • Creates project in current directory
26
+
27
+ With a name:
28
+ • Creates new directory
29
+
30
+ check
31
+ Validate project setup, Docker, and running services
32
+
33
+ ────────────────────────────────────────────
34
+
35
+ BEHAVIOR
36
+
37
+ seamless <project-name>
38
+
39
+ • Shortcut for: seamless init <project-name>
40
+
41
+ ────────────────────────────────────────────
42
+
43
+ WHAT YOU GET
44
+
45
+ • Web application (React starter)
46
+ • API server (Express)
47
+ • SeamlessAuth server (Docker or local)
48
+ • Admin dashboard (Docker or source)
49
+ • Docker Compose setup
50
+
51
+ ────────────────────────────────────────────
52
+
53
+ EXAMPLES
54
+
55
+ seamless init
56
+ → Interactive setup in current directory
57
+
58
+ seamless init my-app
59
+ → Create new project in ./my-app
60
+
61
+ seamless my-app
62
+ → Shortcut for init
63
+
64
+ seamless check
65
+ → Validate your project
66
+
67
+ ────────────────────────────────────────────
68
+
69
+ DOCS
70
+
71
+ https://docs.seamlessauth.com
72
+
73
+ `);
74
+ }
75
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/core/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,CAAC;mBACK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqEzB,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { detectPackageManager } from "./packageManager.js";
4
+ export async function inspectProject(root) {
5
+ const hasPackageJson = fs.existsSync(path.join(root, "package.json"));
6
+ return {
7
+ root,
8
+ packageManager: detectPackageManager(root),
9
+ detected: {
10
+ packageJson: hasPackageJson,
11
+ anything: hasPackageJson,
12
+ },
13
+ };
14
+ }
15
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/core/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,MAAM,cAAc,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;IAEtE,OAAO;QACL,IAAI;QACJ,cAAc,EAAE,oBAAoB,CAAC,IAAI,CAAC;QAC1C,QAAQ,EAAE;YACR,WAAW,EAAE,cAAc;YAC3B,QAAQ,EAAE,cAAc;SACzB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { generateKeyPairSync } from "crypto";
2
+ export function generateJWKS() {
3
+ const { publicKey, privateKey } = generateKeyPairSync("rsa", {
4
+ modulusLength: 2048,
5
+ publicKeyEncoding: {
6
+ type: "spki",
7
+ format: "pem",
8
+ },
9
+ privateKeyEncoding: {
10
+ type: "pkcs8",
11
+ format: "pem",
12
+ },
13
+ });
14
+ return {
15
+ publicKey,
16
+ privateKey,
17
+ };
18
+ }
19
+ //# sourceMappingURL=jwks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwks.js","sourceRoot":"","sources":["../../src/core/jwks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAE7C,MAAM,UAAU,YAAY;IAC1B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,KAAK,EAAE;QAC3D,aAAa,EAAE,IAAI;QACnB,iBAAiB,EAAE;YACjB,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,KAAK;SACd;QACD,kBAAkB,EAAE;YAClB,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,KAAK;SACd;KACF,CAAC,CAAC;IAEH,OAAO;QACL,SAAS;QACT,UAAU;KACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,94 @@
1
+ import kleur from "kleur";
2
+ export function printSuccessOutput(config) {
3
+ const { projectName, webFramework, apiFramework, authMode, useDocker } = config;
4
+ const title = kleur.bold().cyan("SEAMLESS");
5
+ console.log(`
6
+ ╔════════════════════════════════════════╗
7
+ ║ ${title} ║
8
+ ╚════════════════════════════════════════╝
9
+ `);
10
+ console.log(kleur.green("Project initialized successfully.\n"));
11
+ if (projectName) {
12
+ console.log(kleur.dim("Project directory: ") + kleur.bold(projectName));
13
+ console.log(kleur.cyan(`cd ${projectName}\n`));
14
+ }
15
+ console.log(kleur.bold("Included services:\n"));
16
+ if (webFramework) {
17
+ console.log(" • " +
18
+ kleur.white("Web application") +
19
+ kleur.dim(` (${formatFramework(webFramework)})`));
20
+ }
21
+ if (apiFramework) {
22
+ console.log(" • " +
23
+ kleur.white("API server") +
24
+ kleur.dim(` (${formatFramework(apiFramework)})`));
25
+ }
26
+ console.log(" • " +
27
+ kleur.white("Auth server") +
28
+ kleur.dim(authMode === "local" ? " (local source)" : " (Docker image)"));
29
+ console.log(" • " + kleur.white("Admin dashboard") + kleur.dim(" (management UI)"));
30
+ console.log("");
31
+ console.log(kleur.bold("Next steps:\n"));
32
+ if (useDocker) {
33
+ console.log(" 1. Start services");
34
+ console.log(kleur.cyan(" docker compose up\n"));
35
+ console.log(" 2. Create your first admin user");
36
+ console.log(kleur.cyan(" seamless bootstrap-admin\n"));
37
+ console.log(" 3. Complete registration in the browser");
38
+ console.log(kleur.dim(" This grants admin access to the system\n"));
39
+ }
40
+ else {
41
+ if (authMode === "local") {
42
+ console.log(kleur.dim(" # Auth server"));
43
+ console.log(kleur.yellow(" Requires a local PostgreSQL instance running on localhost:5432\n"));
44
+ console.log(" cd auth");
45
+ console.log(" npm install\n");
46
+ console.log(kleur.dim(" # Initialize database"));
47
+ console.log(" npm run db:create");
48
+ console.log(" npm run db:migrate\n");
49
+ console.log(kleur.dim(" # Start auth server"));
50
+ console.log(" npm run dev\n");
51
+ }
52
+ if (apiFramework) {
53
+ console.log(kleur.dim(" # API server"));
54
+ console.log(" cd api && npm install && npm run dev\n");
55
+ }
56
+ if (webFramework) {
57
+ console.log(kleur.dim(" # Web app"));
58
+ console.log(" cd web && npm install && npm run dev\n");
59
+ }
60
+ console.log(" 2. Create your first admin user");
61
+ console.log(kleur.cyan(" seamless bootstrap-admin\n"));
62
+ }
63
+ console.log(kleur.bold("Available services:\n"));
64
+ console.log(" Auth: " + kleur.cyan("http://localhost:5312"));
65
+ if (apiFramework) {
66
+ console.log(" API: " + kleur.cyan("http://localhost:3000"));
67
+ }
68
+ if (webFramework) {
69
+ console.log(" Web: " + kleur.cyan("http://localhost:5173"));
70
+ }
71
+ console.log(" Admin: " + kleur.cyan("http://localhost:5174"));
72
+ console.log("");
73
+ console.log(kleur.bold("Notes:\n"));
74
+ console.log(kleur.dim(" • Web connects to API automatically"));
75
+ console.log(kleur.dim(" • API connects to Auth automatically"));
76
+ console.log(kleur.dim(" • Admin dashboard uses the same auth system"));
77
+ console.log(kleur.dim(" • Bootstrap command provisions the first admin user"));
78
+ console.log(kleur.dim(" • All secrets and keys are pre-configured\n"));
79
+ console.log(kleur.dim("Docs: ") + kleur.cyan("https://docs.seamlessauth.com\n"));
80
+ console.log(kleur.bold().green("Setup complete.\n"));
81
+ }
82
+ function formatFramework(name) {
83
+ const map = {
84
+ react: "React",
85
+ express: "Express",
86
+ angular: "Angular",
87
+ next: "Next.js",
88
+ fastapi: "FastAPI",
89
+ fastify: "Fastify",
90
+ vue: "Vue",
91
+ };
92
+ return map[name] || name;
93
+ }
94
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/core/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ export function detectPackageManager(root) {
4
+ if (fs.existsSync(path.join(root, "pnpm-lock.yaml")))
5
+ return "pnpm";
6
+ if (fs.existsSync(path.join(root, "yarn.lock")))
7
+ return "yarn";
8
+ return "npm";
9
+ }
10
+ //# sourceMappingURL=packageManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packageManager.js","sourceRoot":"","sources":["../../src/core/packageManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACpE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/D,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ import path from "path";
2
+ import { fileURLToPath } from "url";
3
+ const __filename = fileURLToPath(import.meta.url);
4
+ const __dirname = path.dirname(__filename);
5
+ export const PROJECT_ROOT = path.resolve(__dirname, "../../");
6
+ export const TEMPLATE_ROOT = path.join(PROJECT_ROOT, "templates");
7
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAE9D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { randomBytes } from "crypto";
2
+ export function generateSecret(length = 32) {
3
+ return randomBytes(length).toString("hex");
4
+ }
5
+ export function generateKid() {
6
+ return "dev-" + randomBytes(6).toString("hex");
7
+ }
8
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/core/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,UAAU,cAAc,CAAC,MAAM,GAAG,EAAE;IACxC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,47 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { runCommand } from "../../core/exec.js";
4
+ import { writeEnv } from "../../utils/writeEnv.js";
5
+ const AUTH_REPO = "https://github.com/fells-code/seamless-auth-api";
6
+ const AUTH_PORT = 5312;
7
+ export async function generateAuthServer(context, mode) {
8
+ const { root } = context;
9
+ if (mode === "local") {
10
+ await setupLocalAuth(root);
11
+ }
12
+ else {
13
+ await setupDockerAuth(root);
14
+ }
15
+ }
16
+ async function setupLocalAuth(root) {
17
+ const authDir = path.join(root, "auth");
18
+ console.log("Cloning SeamlessAuth server...");
19
+ await runCommand("git", ["clone", AUTH_REPO, "auth"], root);
20
+ console.log("Writing auth environment...");
21
+ writeEnv(authDir, {
22
+ PORT: AUTH_PORT,
23
+ NODE_ENV: "development",
24
+ AUTH_MODE: "server",
25
+ ISSUER: `http://localhost:${AUTH_PORT}`,
26
+ });
27
+ console.log("Auth server ready in /auth");
28
+ }
29
+ async function setupDockerAuth(root) {
30
+ console.log("Creating docker-compose for SeamlessAuth...");
31
+ const dockerCompose = `
32
+ services:
33
+ auth:
34
+ image: ghcr.io/fells-code/seamless-auth-api:v0.1.2
35
+ container_name: seamless-auth
36
+ ports:
37
+ - "5312:5312"
38
+ environment:
39
+ PORT: 5312
40
+ NODE_ENV: development
41
+ AUTH_MODE: server
42
+ ISSUER: http://localhost:5312
43
+ `;
44
+ fs.writeFileSync(path.join(root, "docker-compose.yml"), dockerCompose.trim() + "\n");
45
+ console.log("Docker setup ready.");
46
+ }
47
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/generators/auth/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,MAAM,SAAS,GAAG,iDAAiD,CAAC;AACpE,MAAM,SAAS,GAAG,IAAI,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAY,EACZ,IAAiC;IAEjC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAEzB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAExC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IAE5D,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAE3C,QAAQ,CAAC,OAAO,EAAE;QAChB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,aAAa;QACvB,SAAS,EAAE,QAAQ;QACnB,MAAM,EAAE,oBAAoB,SAAS,EAAE;KACxC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY;IACzC,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAE3D,MAAM,aAAa,GAAG;;;;;;;;;;;;CAYvB,CAAC;IAEA,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,EACrC,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAC5B,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import path from "path";
2
+ import { cloneRepo, removeGitDir, copyEnvExample, } from "../../utils/repoUtils.js";
3
+ const API_STARTER_REPO = "https://github.com/fells-code/seamless-auth-starter-express.git";
4
+ export async function generateExpressStarter(context) {
5
+ const { root } = context;
6
+ const apiDir = path.join(root, "api");
7
+ console.log("Cloning Seamless Auth Express starter...");
8
+ await cloneRepo(API_STARTER_REPO, apiDir);
9
+ removeGitDir(apiDir);
10
+ copyEnvExample(apiDir);
11
+ console.log("API starter ready.");
12
+ }
13
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../../src/generators/backend/express.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,iEAAiE,CAAC;AAEpE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAyB;IACpE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAEzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAEtC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IAExD,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"}
@@ -0,0 +1,43 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { VERSION } from "../../index.js";
4
+ export function generateSeamlessConfig(root, options) {
5
+ const config = {
6
+ version: VERSION,
7
+ projectName: options.projectName || path.basename(root),
8
+ createdAt: new Date().toISOString(),
9
+ services: {
10
+ web: {
11
+ framework: options.webFramework,
12
+ path: "./web",
13
+ },
14
+ api: {
15
+ framework: options.apiFramework,
16
+ path: "./api",
17
+ },
18
+ auth: {
19
+ mode: options.authMode,
20
+ image: options.authMode === "docker"
21
+ ? "ghcr.io/fells-code/seamless-auth-api:latest"
22
+ : null,
23
+ path: options.authMode === "local" ? "./auth" : null,
24
+ },
25
+ admin: {
26
+ mode: options.adminMode,
27
+ image: options.adminMode === "image"
28
+ ? "ghcr.io/fells-code/seamless-auth-admin-dashboard:latest"
29
+ : null,
30
+ path: options.adminMode === "source" ? "./admin" : null,
31
+ },
32
+ database: {
33
+ type: "postgres",
34
+ },
35
+ },
36
+ docker: {
37
+ composeFile: "docker-compose.yml",
38
+ },
39
+ };
40
+ fs.writeFileSync(path.join(root, "seamless.config.json"), JSON.stringify(config, null, 2));
41
+ console.log("Seamless config created.");
42
+ }
43
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/generators/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,sBAAsB,CACpC,IAAY,EACZ,OAMC;IAED,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACvD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAEnC,QAAQ,EAAE;YACR,GAAG,EAAE;gBACH,SAAS,EAAE,OAAO,CAAC,YAAY;gBAC/B,IAAI,EAAE,OAAO;aACd;YACD,GAAG,EAAE;gBACH,SAAS,EAAE,OAAO,CAAC,YAAY;gBAC/B,IAAI,EAAE,OAAO;aACd;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,OAAO,CAAC,QAAQ;gBACtB,KAAK,EACH,OAAO,CAAC,QAAQ,KAAK,QAAQ;oBAC3B,CAAC,CAAC,6CAA6C;oBAC/C,CAAC,CAAC,IAAI;gBACV,IAAI,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;aACrD;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,OAAO,CAAC,SAAS;gBACvB,KAAK,EACH,OAAO,CAAC,SAAS,KAAK,OAAO;oBAC3B,CAAC,CAAC,yDAAyD;oBAC3D,CAAC,CAAC,IAAI;gBACV,IAAI,EAAE,OAAO,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;aACxD;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,UAAU;aACjB;SACF;QAED,MAAM,EAAE;YACN,WAAW,EAAE,oBAAoB;SAClC;KACF,CAAC;IAEF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,EACvC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAChC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;AAC1C,CAAC"}