create-seamless 0.0.11 → 0.1.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.
Files changed (43) hide show
  1. package/README.md +109 -51
  2. package/dist/commands/init.js +65 -0
  3. package/dist/commands/init.js.map +1 -0
  4. package/dist/core/configure.js +25 -0
  5. package/dist/core/configure.js.map +1 -0
  6. package/dist/core/env.js +35 -0
  7. package/dist/core/env.js.map +1 -0
  8. package/dist/core/exec.js +17 -0
  9. package/dist/core/exec.js.map +1 -0
  10. package/dist/core/fetch.js +9 -0
  11. package/dist/core/fetch.js.map +1 -0
  12. package/dist/core/help.js +56 -0
  13. package/dist/core/help.js.map +1 -0
  14. package/dist/core/inspect.js +15 -0
  15. package/dist/core/inspect.js.map +1 -0
  16. package/dist/core/jwks.js +19 -0
  17. package/dist/core/jwks.js.map +1 -0
  18. package/dist/core/output.js +83 -0
  19. package/dist/core/output.js.map +1 -0
  20. package/dist/core/packageManager.js +10 -0
  21. package/dist/core/packageManager.js.map +1 -0
  22. package/dist/core/paths.js +7 -0
  23. package/dist/core/paths.js.map +1 -0
  24. package/dist/core/secrets.js +8 -0
  25. package/dist/core/secrets.js.map +1 -0
  26. package/dist/generators/auth/auth.js +47 -0
  27. package/dist/generators/auth/auth.js.map +1 -0
  28. package/dist/generators/backend/express.js +13 -0
  29. package/dist/generators/backend/express.js.map +1 -0
  30. package/dist/generators/docker/docker.js +231 -0
  31. package/dist/generators/docker/docker.js.map +1 -0
  32. package/dist/generators/frontend/react.js +13 -0
  33. package/dist/generators/frontend/react.js.map +1 -0
  34. package/dist/index.js +17 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/prompts/projectSetup.js +64 -0
  37. package/dist/prompts/projectSetup.js.map +1 -0
  38. package/dist/utils/repoUtils.js +23 -0
  39. package/dist/utils/repoUtils.js.map +1 -0
  40. package/dist/utils/writeEnv.js +9 -0
  41. package/dist/utils/writeEnv.js.map +1 -0
  42. package/package.json +19 -12
  43. package/index.js +0 -520
package/README.md CHANGED
@@ -3,85 +3,142 @@
3
3
  [![License: AGPL-3.0-only](https://img.shields.io/badge/License-AGPL3-yellow.svg)](LICENSE)
4
4
  [![npm version](https://img.shields.io/npm/v/create-seamless.svg?style=flat)](https://www.npmjs.com/package/create-seamless)
5
5
 
6
- `create-seamless` is a project scaffolding tool for building applications with **Seamless Auth**, an open source, passwordless authentication system.
6
+ `create-seamless` is a CLI for bootstrapping applications with Seamless Auth, an open source, passwordless authentication system.
7
7
 
8
- It provisions a local, production-shaped development environment that can include:
8
+ It guides you through creating a fully working authentication stack with a web app, API, and auth server that are already connected and ready to run.
9
9
 
10
- - The Seamless Auth open source server
11
- - A starter web application
12
- - A starter API server
10
+ ---
11
+
12
+ ## Getting started
13
+
14
+ Run the CLI with `npx`:
15
+
16
+ ```bash
17
+ npx create-seamless my-app
18
+ ```
19
+
20
+ Or run it in your current directory:
21
+
22
+ ```bash
23
+ npx create-seamless
24
+ ```
13
25
 
14
- The generated project is fully local and requires no hosted services or external accounts to run.
26
+ You’ll be guided through a short setup process where you can choose:
27
+
28
+ - Whether to create a web application
29
+ - Whether to create an API server
30
+ - How to run the auth server (local or Docker)
31
+ - Whether to run everything with Docker
15
32
 
16
33
  ---
17
34
 
18
- ## What this creates
35
+ ## What gets created
19
36
 
20
- Depending on the flags provided, `create-seamless` scaffolds a local project with the following structure:
37
+ Depending on your selections, the CLI generates a project like this:
21
38
 
22
39
  ```text
23
40
  my-app/
24
- ├─ auth/ # Seamless Auth OSS server
25
- ├─ web/ # Starter web application (optional)
26
- ├─ api/ # Starter API server (optional)
41
+ ├─ auth/ # Seamless Auth server (optional)
42
+ ├─ web/ # React web application (optional)
43
+ ├─ api/ # Express API server (optional)
44
+ ├─ docker-compose.yml (optional)
27
45
  └─ README.md
28
46
  ```
29
47
 
30
- Each service is independently runnable and preconfigured to work together using local URLs and environment variables.
48
+ All services are preconfigured to work together.
31
49
 
32
- The intended development workflow is to run each service in its own terminal:
50
+ - Web calls the API
51
+ - API communicates with the auth server
52
+ - Auth manages sessions and tokens
33
53
 
34
- ```bash
35
- # terminal 1
36
- cd auth && npm run dev
54
+ No manual wiring is required.
55
+
56
+ ---
57
+
58
+ ## Running your project
37
59
 
38
- # terminal 2
39
- cd api && npm run dev
60
+ ### Option 1: Docker
40
61
 
41
- # terminal 3
42
- cd web && npm run dev
62
+ If you choose Docker during setup:
63
+
64
+ ```bash
65
+ docker compose up
43
66
  ```
44
67
 
68
+ This starts:
69
+
70
+ - PostgreSQL
71
+ - Auth server
72
+ - API server
73
+ - Web app
74
+
75
+ All services are configured to communicate correctly inside the container network.
76
+
45
77
  ---
46
78
 
47
- ## Usage
79
+ ### Option 2: Local development
80
+
81
+ If you choose to run locally:
82
+
83
+ #### 1. Start PostgreSQL
84
+
85
+ Make sure you have a local PostgreSQL instance running on port `5432`.
86
+
87
+ ---
48
88
 
49
- Run via `npx`:
89
+ #### 2. Start the auth server
50
90
 
51
91
  ```bash
52
- npx create-seamless my-app
92
+ cd auth
93
+ npm install
94
+
95
+ npm run db:create
96
+ npm run db:migrate
97
+
98
+ npm run dev
53
99
  ```
54
100
 
55
- By default, this scaffolds the full local stack:
101
+ ---
56
102
 
57
- - Seamless Auth server
58
- - Web application
59
- - API server
103
+ #### 3. Start the API
104
+
105
+ ```bash
106
+ cd api
107
+ npm install
108
+ npm run dev
109
+ ```
110
+
111
+ ---
112
+
113
+ #### 4. Start the web app
114
+
115
+ ```bash
116
+ cd web
117
+ npm install
118
+ npm run dev
119
+ ```
60
120
 
61
121
  ---
62
122
 
63
- ## CLI options
123
+ ## What is configured for you
124
+
125
+ create-seamless handles the parts that are usually difficult to get right:
64
126
 
65
- | Flag | Description |
66
- | ------------- | -------------------------------------------- |
67
- | `--auth` | Include the Seamless Auth open source server |
68
- | `--web` | Include the starter web application |
69
- | `--api` | Include the starter API server |
70
- | `--install` | Automatically install dependencies |
71
- | `--no-git` | Skip git initialization |
72
- | `--auth-port` | Auth server port (default: 3000) |
73
- | `--api-port` | API server port (default: 4000) |
74
- | `--web-port` | Web dev server port (default: 5173) |
127
+ - Shared API service tokens
128
+ - JWT signing configuration
129
+ - JWKS key generation for production mode
130
+ - Cross-service environment variables
131
+ - CORS and cookie-based session handling
75
132
 
76
- If no component flags are provided, all components are included.
133
+ Everything is aligned across services so the system works immediately after setup.
77
134
 
78
135
  ---
79
136
 
80
137
  ## Included projects
81
138
 
82
- `create-seamless` pulls directly from the following open source repositories:
139
+ create-seamless pulls from the following repositories:
83
140
 
84
- - Seamless Auth Server
141
+ - Seamless Auth API
85
142
  [https://github.com/fells-code/seamless-auth-api](https://github.com/fells-code/seamless-auth-api)
86
143
 
87
144
  - Seamless Auth React Starter
@@ -90,29 +147,29 @@ If no component flags are provided, all components are included.
90
147
  - Seamless Auth API Starter
91
148
  [https://github.com/fells-code/seamless-auth-starter-express](https://github.com/fells-code/seamless-auth-starter-express)
92
149
 
93
- Each repository can be used independently, but `create-seamless` wires them together for local development out of the box.
150
+ Each project can be used independently, but the CLI connects them into a working system.
94
151
 
95
152
  ---
96
153
 
97
154
  ## Documentation
98
155
 
99
- Full documentation for Seamless Auth, including architecture, configuration, and deployment guidance, is available at:
156
+ Full documentation is available at:
100
157
 
101
- [https://seamlessauth.com/docs](https://seamlessauth.com/docs)
158
+ [https://docs.seamlessauth.com](https://docs.seamlessauth.com)
102
159
 
103
160
  ---
104
161
 
105
162
  ## Philosophy
106
163
 
107
- Seamless Auth is designed around:
164
+ Seamless Auth is built around a few principles:
108
165
 
109
166
  - Passwordless authentication only
110
- - Embedded auth (no redirects or callbacks)
111
- - Self-hosted, open source foundations
167
+ - No redirects or third-party auth providers
168
+ - Self-hosted by default
112
169
  - Production-shaped local development
113
- - Minimal assumptions and explicit configuration
170
+ - Explicit configuration over hidden behavior
114
171
 
115
- `create-seamless` exists to make getting started with this model straightforward and repeatable.
172
+ create-seamless exists to make this setup fast and repeatable.
116
173
 
117
174
  ---
118
175
 
@@ -120,12 +177,13 @@ Seamless Auth is designed around:
120
177
 
121
178
  - Node.js 18 or newer
122
179
  - npm or pnpm
180
+ - Docker (optional)
123
181
 
124
182
  ---
125
183
 
126
184
  ## License
127
185
 
128
- **AGPL-3.0-only** © 2026 Fells Code LLC
186
+ AGPL-3.0-only © 2026 Fells Code LLC
129
187
 
130
188
  This license ensures:
131
189
 
@@ -133,4 +191,4 @@ This license ensures:
133
191
  - freedom to self-host and modify
134
192
  - sustainability of the managed service offering
135
193
 
136
- See [`LICENSE`](./LICENSE) for details.
194
+ See `LICENSE` for details.
@@ -0,0 +1,65 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import { runProjectSetupPrompts } from "../prompts/projectSetup.js";
4
+ import { generateReactStarter } from "../generators/frontend/react.js";
5
+ import { generateExpressStarter } from "../generators/backend/express.js";
6
+ import { generateAuthServer } from "../generators/auth/auth.js";
7
+ import { configureApiEnv, configureWebEnv } from "../core/configure.js";
8
+ import { configureAuthLocalEnv, generateDockerCompose, } from "../generators/docker/docker.js";
9
+ import { printSuccessOutput } from "../core/output.js";
10
+ export async function runCLI(projectName) {
11
+ const cwd = process.cwd();
12
+ let root = cwd;
13
+ if (projectName) {
14
+ root = path.join(cwd, projectName);
15
+ if (fs.existsSync(root)) {
16
+ throw new Error(`Directory already exists: ${projectName}`);
17
+ }
18
+ fs.mkdirSync(root);
19
+ console.log(`Creating project in ${root}`);
20
+ }
21
+ const files = fs.readdirSync(root);
22
+ const isEmpty = files.length === 0;
23
+ if (!isEmpty) {
24
+ console.log("Existing project detected.");
25
+ console.log("Integration flow coming next.");
26
+ return;
27
+ }
28
+ const answers = await runProjectSetupPrompts();
29
+ if (answers.web && answers.webFramework === "react") {
30
+ await generateReactStarter({ root });
31
+ }
32
+ if (answers.api && answers.apiFramework === "express") {
33
+ await generateExpressStarter({ root });
34
+ }
35
+ let sharedConfig = {};
36
+ if (answers.authMode === "local") {
37
+ await generateAuthServer({ root }, "local");
38
+ sharedConfig = await configureAuthLocalEnv(root);
39
+ }
40
+ if (answers.useDocker) {
41
+ const dockerShared = await generateDockerCompose(root, {
42
+ authMode: answers.authMode,
43
+ includeApi: answers.api,
44
+ includeWeb: answers.web,
45
+ });
46
+ if (answers.authMode === "docker") {
47
+ sharedConfig = dockerShared;
48
+ }
49
+ }
50
+ if (answers.api) {
51
+ configureApiEnv(root, sharedConfig);
52
+ }
53
+ if (answers.web) {
54
+ configureWebEnv(root);
55
+ }
56
+ printSuccessOutput({
57
+ projectName,
58
+ root,
59
+ webFramework: answers.webFramework,
60
+ apiFramework: answers.apiFramework,
61
+ authMode: answers.authMode,
62
+ useDocker: answers.useDocker,
63
+ });
64
+ }
65
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -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,56 @@
1
+ export function printHelp() {
2
+ console.log(`
3
+ create-seamless
4
+
5
+ Seamless Auth CLI — scaffold and integrate passwordless authentication.
6
+
7
+ ────────────────────────────────────────────
8
+
9
+ USAGE
10
+
11
+ npx create-seamless
12
+ npx create-seamless <project-name>
13
+ npx create-seamless -h
14
+ npx create-seamless --help
15
+
16
+ ────────────────────────────────────────────
17
+
18
+ BEHAVIOR
19
+
20
+ npx create-seamless
21
+
22
+ Without a name:
23
+ • If directory is empty → create a new project
24
+
25
+ npx create-seamless <project-name>
26
+
27
+ With a name:
28
+ • Creates a new directory
29
+
30
+ ────────────────────────────────────────────
31
+
32
+ WHAT YOU CAN BUILD
33
+
34
+ • A web application starter with Seamless Auth
35
+ • An API server starter with Seamless Auth
36
+ • SeamlessAuth server (local or Docker)
37
+
38
+ ────────────────────────────────────────────
39
+
40
+ EXAMPLES
41
+
42
+ npx create-seamless
43
+ → Interactive setup in current directory
44
+
45
+ npx create-seamless my-app
46
+ → Create new project in ./my-app
47
+
48
+ ────────────────────────────────────────────
49
+
50
+ DOCS
51
+
52
+ https://docs.seamlessauth.com
53
+
54
+ `);
55
+ }
56
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/core/help.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDb,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,83 @@
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("✔ Your SeamlessAuth project is ready.\n"));
11
+ if (projectName) {
12
+ console.log(kleur.dim("Project created in: ") + kleur.bold(projectName));
13
+ console.log(kleur.cyan(`cd ${projectName}\n`));
14
+ }
15
+ console.log(kleur.bold("Project includes:\n"));
16
+ if (webFramework) {
17
+ console.log(" • " +
18
+ kleur.white("Web app") +
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("");
30
+ console.log(kleur.bold("Getting started:\n"));
31
+ if (useDocker) {
32
+ console.log(kleur.cyan(" docker compose up\n"));
33
+ }
34
+ else {
35
+ if (authMode === "local") {
36
+ console.log(kleur.dim("# Auth server"));
37
+ console.log(kleur.yellow(" ⚠ Requires a local PostgreSQL instance running on localhost, port 5432\n"));
38
+ console.log(" cd auth");
39
+ console.log(" npm install\n");
40
+ console.log(kleur.dim(" # Initialize database"));
41
+ console.log(" npm run db:create");
42
+ console.log(" npm run db:migrate\n");
43
+ console.log(kleur.dim(" # Start auth server"));
44
+ console.log(" npm run dev\n");
45
+ }
46
+ if (apiFramework) {
47
+ console.log(kleur.dim("# API server"));
48
+ console.log(" cd api && npm install && npm run dev\n");
49
+ }
50
+ if (webFramework) {
51
+ console.log(kleur.dim("# Web app"));
52
+ console.log(" cd web && npm install && npm run dev\n");
53
+ }
54
+ }
55
+ console.log(kleur.bold("Available services:\n"));
56
+ console.log(" Auth: " + kleur.cyan("http://localhost:5312"));
57
+ if (apiFramework) {
58
+ console.log(" API: " + kleur.cyan("http://localhost:3000"));
59
+ }
60
+ if (webFramework) {
61
+ console.log(" Web: " + kleur.cyan("http://localhost:5173"));
62
+ }
63
+ console.log("");
64
+ console.log(kleur.bold("Notes:\n"));
65
+ console.log(kleur.dim(" • Web connects to API automatically"));
66
+ console.log(kleur.dim(" • API connects to Auth automatically"));
67
+ console.log(kleur.dim(" • All secrets and keys are pre-configured\n"));
68
+ console.log(kleur.dim("Docs: ") + kleur.cyan("https://docs.seamlessauth.com\n"));
69
+ console.log(kleur.bold().green("Happy hacking. 🚀\n"));
70
+ }
71
+ function formatFramework(name) {
72
+ const map = {
73
+ react: "React",
74
+ express: "Express",
75
+ angular: "Angular",
76
+ next: "Next.js",
77
+ fastapi: "FastAPI",
78
+ fastify: "Fastify",
79
+ vue: "Vue",
80
+ };
81
+ return map[name] || name;
82
+ }
83
+ //# 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