@sedim/cli 1.0.1 → 1.0.3
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/dist/index.js +91 -61
- package/package.json +1 -1
- package/CONTRIBUTING.md +0 -385
- package/README.md +0 -298
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/shared/constants.ts
|
|
13
|
-
var SEDIM_DIR, SEDIM_CONFIG_FILE, SEDIM_CONFIG_CACHE, SEDIM_SESSION_FILE, SEDIM_MODULES_DIR, SEDIM_LOGS_DIR, SEDIM_LATEST_LOG, DEFAULT_REGISTRY_URL, MIN_NODE_VERSION, CLI_VERSION;
|
|
13
|
+
var SEDIM_DIR, SEDIM_CONFIG_FILE, SEDIM_CONFIG_CACHE, SEDIM_SESSION_FILE, SEDIM_MODULES_DIR, SEDIM_LOGS_DIR, SEDIM_LATEST_LOG, DEFAULT_REGISTRY_URL, DEFAULT_PACKAGES_URL, MIN_NODE_VERSION, CLI_VERSION;
|
|
14
14
|
var init_constants = __esm({
|
|
15
15
|
"src/shared/constants.ts"() {
|
|
16
16
|
"use strict";
|
|
@@ -22,8 +22,9 @@ var init_constants = __esm({
|
|
|
22
22
|
SEDIM_LOGS_DIR = `${SEDIM_DIR}/logs`;
|
|
23
23
|
SEDIM_LATEST_LOG = `${SEDIM_LOGS_DIR}/latest.log`;
|
|
24
24
|
DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/sedimie/Sedim/main/registry";
|
|
25
|
+
DEFAULT_PACKAGES_URL = "https://raw.githubusercontent.com/sedimie/Sedim/main/packages";
|
|
25
26
|
MIN_NODE_VERSION = 18;
|
|
26
|
-
CLI_VERSION = "1.0.
|
|
27
|
+
CLI_VERSION = "1.0.3";
|
|
27
28
|
}
|
|
28
29
|
});
|
|
29
30
|
|
|
@@ -4254,26 +4255,16 @@ async function classifyConflicts(projectRoot, ctx, filesToCreate, schemaTables)
|
|
|
4254
4255
|
}
|
|
4255
4256
|
|
|
4256
4257
|
// src/thinker/resolve-template.ts
|
|
4257
|
-
|
|
4258
|
+
init_constants();
|
|
4258
4259
|
import path23 from "path";
|
|
4259
4260
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4260
|
-
import { existsSync } from "fs";
|
|
4261
4261
|
var __dirname3 = path23.dirname(fileURLToPath3(import.meta.url));
|
|
4262
|
-
function
|
|
4263
|
-
return path23.resolve(projectRoot, "..", "..", "..", "packages", moduleName, "src");
|
|
4264
|
-
}
|
|
4265
|
-
async function resolveTemplate(templateKey, ctx, selectedFeatures = []) {
|
|
4262
|
+
async function resolveTemplate(templateKey, ctx, selectedFeatures = [], packagesUrl = DEFAULT_PACKAGES_URL) {
|
|
4266
4263
|
const [moduleName, ...rest] = templateKey.split("/");
|
|
4267
4264
|
if (!moduleName || rest.length === 0) {
|
|
4268
4265
|
throw new Error(`Invalid templateKey: "${templateKey}"`);
|
|
4269
4266
|
}
|
|
4270
4267
|
const relPath = rest.join("/");
|
|
4271
|
-
const projectRoot = ctx.projectRoot ?? process.cwd();
|
|
4272
|
-
const packageRoot = getPackageRoot(projectRoot, moduleName);
|
|
4273
|
-
const tryPackageRoot = (levels) => path23.resolve(__dirname3, levels, "packages", moduleName, "src");
|
|
4274
|
-
const packageRoot3 = tryPackageRoot("../../..");
|
|
4275
|
-
const packageRoot4 = tryPackageRoot("../../../../..");
|
|
4276
|
-
const resolvedRoot = existsSync(packageRoot) ? packageRoot : existsSync(packageRoot3) ? packageRoot3 : existsSync(packageRoot4) ? packageRoot4 : packageRoot;
|
|
4277
4268
|
const generatedKeys = {
|
|
4278
4269
|
"ui/pages/login-page": (f) => buildLoginPage(f),
|
|
4279
4270
|
"ui/pages/signup-page": (f) => buildSignupPage(f),
|
|
@@ -4285,58 +4276,60 @@ async function resolveTemplate(templateKey, ctx, selectedFeatures = []) {
|
|
|
4285
4276
|
return generatedKeys[relPath](selectedFeatures, ctx);
|
|
4286
4277
|
}
|
|
4287
4278
|
let content;
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4279
|
+
let found = false;
|
|
4280
|
+
const asIsUrl = `${packagesUrl}/${moduleName}/src/${relPath}`;
|
|
4281
|
+
const asIsFetched = await tryFetch(asIsUrl);
|
|
4282
|
+
if (asIsFetched !== null) {
|
|
4283
|
+
content = asIsFetched;
|
|
4284
|
+
found = true;
|
|
4292
4285
|
} else {
|
|
4293
|
-
const
|
|
4294
|
-
|
|
4295
|
-
const raw = await
|
|
4296
|
-
|
|
4286
|
+
for (const tryExt of ["ts", "tsx", "css", "prisma"]) {
|
|
4287
|
+
const url = `${packagesUrl}/${moduleName}/src/${relPath}.${tryExt}`;
|
|
4288
|
+
const raw = await tryFetch(url);
|
|
4289
|
+
if (raw !== null) {
|
|
4290
|
+
content = raw;
|
|
4291
|
+
found = true;
|
|
4292
|
+
break;
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
if (!found) {
|
|
4297
|
+
const templateAsIs = `${packagesUrl}/${moduleName}/src/templates/${relPath}`;
|
|
4298
|
+
const fetchedAsIs = await tryFetch(templateAsIs);
|
|
4299
|
+
if (fetchedAsIs !== null) {
|
|
4300
|
+
content = fetchedAsIs;
|
|
4301
|
+
found = true;
|
|
4297
4302
|
} else {
|
|
4298
|
-
const
|
|
4299
|
-
const
|
|
4300
|
-
if (
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
content = await readText(sourcePath);
|
|
4304
|
-
content = applySubstitutions(content, ctx, selectedFeatures);
|
|
4305
|
-
} else {
|
|
4306
|
-
content = "";
|
|
4307
|
-
}
|
|
4308
|
-
} else {
|
|
4309
|
-
let found = false;
|
|
4310
|
-
content = "";
|
|
4311
|
-
for (const ext of [".ts", ".tsx", ".css"]) {
|
|
4312
|
-
const sourcePath = path23.join(resolvedRoot, `${relPath}${ext}`);
|
|
4313
|
-
if (await exists(sourcePath)) {
|
|
4314
|
-
const raw = await readText(sourcePath);
|
|
4315
|
-
content = applySubstitutions(raw, ctx, selectedFeatures);
|
|
4316
|
-
found = true;
|
|
4317
|
-
break;
|
|
4318
|
-
}
|
|
4319
|
-
}
|
|
4320
|
-
if (!found) {
|
|
4321
|
-
const sourcePrismaPath = path23.join(resolvedRoot, `${relPath}.prisma`);
|
|
4322
|
-
if (await exists(sourcePrismaPath)) {
|
|
4323
|
-
content = await readText(sourcePrismaPath);
|
|
4324
|
-
} else {
|
|
4325
|
-
throw new Error(
|
|
4326
|
-
`Template not found for key "${templateKey}". Checked:
|
|
4327
|
-
${templatePath}
|
|
4328
|
-
${path23.join(resolvedRoot, relPath)}.[ts|tsx|css]`
|
|
4329
|
-
);
|
|
4330
|
-
}
|
|
4331
|
-
}
|
|
4303
|
+
const templateUrl = `${packagesUrl}/${moduleName}/src/templates/${relPath}.ts`;
|
|
4304
|
+
const fetched = await tryFetch(templateUrl);
|
|
4305
|
+
if (fetched !== null) {
|
|
4306
|
+
content = fetched;
|
|
4307
|
+
found = true;
|
|
4332
4308
|
}
|
|
4333
4309
|
}
|
|
4334
4310
|
}
|
|
4311
|
+
if (!found) {
|
|
4312
|
+
throw new Error(
|
|
4313
|
+
`Template not found for key "${templateKey}". Checked:
|
|
4314
|
+
${packagesUrl}/${moduleName}/src/${relPath}.[ts|tsx|css|prisma]
|
|
4315
|
+
${packagesUrl}/${moduleName}/src/templates/${relPath}.ts`
|
|
4316
|
+
);
|
|
4317
|
+
}
|
|
4318
|
+
content = applySubstitutions(content, ctx, selectedFeatures);
|
|
4335
4319
|
if (!relPath.endsWith(".css") && !relPath.endsWith(".prisma")) {
|
|
4336
4320
|
content = stripRelativeJsExtensions(content);
|
|
4337
4321
|
}
|
|
4338
4322
|
return content;
|
|
4339
4323
|
}
|
|
4324
|
+
async function tryFetch(url) {
|
|
4325
|
+
try {
|
|
4326
|
+
const res = await fetch(url);
|
|
4327
|
+
if (!res.ok) return null;
|
|
4328
|
+
return res.text();
|
|
4329
|
+
} catch {
|
|
4330
|
+
return null;
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4340
4333
|
function stripRelativeJsExtensions(content) {
|
|
4341
4334
|
return content.replace(/(from\s+['"])(\.\.?\/[^'"]*?)\.js(['"])/g, "$1$2$3");
|
|
4342
4335
|
}
|
|
@@ -4411,7 +4404,7 @@ function buildProvidersImport(features) {
|
|
|
4411
4404
|
if (features.includes("oauth-github")) providerFns.push("githubProvider");
|
|
4412
4405
|
if (features.includes("oauth-discord")) providerFns.push("discordProvider");
|
|
4413
4406
|
if (providerFns.length === 0) return "";
|
|
4414
|
-
return `import { ${providerFns.join(", ")} } from './adapters/framework-config.js'`;
|
|
4407
|
+
return `import { ${providerFns.join(", ")} } from './adapters/framework/framework-config.js'`;
|
|
4415
4408
|
}
|
|
4416
4409
|
function buildProvidersConfig(features) {
|
|
4417
4410
|
const lines = [];
|
|
@@ -4475,7 +4468,7 @@ function buildLoginPage(features) {
|
|
|
4475
4468
|
` <p style={{ textAlign: 'center', fontSize: '0.8125rem', color: '${mutedColor}', margin: 0 }}>`
|
|
4476
4469
|
);
|
|
4477
4470
|
body.push(
|
|
4478
|
-
` Don
|
|
4471
|
+
` Don't have an account?{' '}<a href="/signup" style={{ color: '${fgColor}', fontWeight: 600, textDecoration: 'none' }}>Sign up</a>`
|
|
4479
4472
|
);
|
|
4480
4473
|
body.push(` </p>`);
|
|
4481
4474
|
}
|
|
@@ -4640,7 +4633,7 @@ function buildForgotPage(features = []) {
|
|
|
4640
4633
|
const inner = [
|
|
4641
4634
|
` <div style={{ textAlign: 'center' }}>`,
|
|
4642
4635
|
` <h1 style={{ fontSize: '1.5rem', fontWeight: 700, margin: '0 0 0.25rem' }}>Reset password</h1>`,
|
|
4643
|
-
` <p style={{ fontSize: '0.875rem', color: '${mutedColor}', margin: 0 }}>Enter your email and we
|
|
4636
|
+
` <p style={{ fontSize: '0.875rem', color: '${mutedColor}', margin: 0 }}>Enter your email and we'll send a reset link.</p>`,
|
|
4644
4637
|
` </div>`,
|
|
4645
4638
|
` <ForgotPasswordForm />`,
|
|
4646
4639
|
` <p style={{ textAlign: 'center', fontSize: '0.8125rem', margin: 0 }}>`,
|
|
@@ -5017,7 +5010,31 @@ function manifestToPlanConfig(manifest, selectedFeatures, _ctx) {
|
|
|
5017
5010
|
}
|
|
5018
5011
|
|
|
5019
5012
|
// src/thinker/load-plan-config.ts
|
|
5020
|
-
|
|
5013
|
+
init_constants();
|
|
5014
|
+
import { createWriteStream } from "fs";
|
|
5015
|
+
import https from "https";
|
|
5016
|
+
import os from "os";
|
|
5017
|
+
import { pipeline } from "stream";
|
|
5018
|
+
import { promisify } from "util";
|
|
5019
|
+
var streamPipeline = promisify(pipeline);
|
|
5020
|
+
async function downloadToTemp(url, suffix) {
|
|
5021
|
+
const tmpDir = os.tmpdir();
|
|
5022
|
+
const tmpPath = `${tmpDir}/sedim-${suffix}-${Date.now()}.js`;
|
|
5023
|
+
await new Promise((resolve, reject) => {
|
|
5024
|
+
const req = https.get(url, (res) => {
|
|
5025
|
+
if (res.statusCode !== 200) {
|
|
5026
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
5027
|
+
return;
|
|
5028
|
+
}
|
|
5029
|
+
const file = createWriteStream(tmpPath);
|
|
5030
|
+
res.pipe(file);
|
|
5031
|
+
file.on("finish", () => file.close(() => resolve()));
|
|
5032
|
+
});
|
|
5033
|
+
req.on("error", reject);
|
|
5034
|
+
});
|
|
5035
|
+
return tmpPath;
|
|
5036
|
+
}
|
|
5037
|
+
async function loadPlanConfig(moduleName, manifest, ctx, selectedFeatures, packagesUrl = DEFAULT_PACKAGES_URL) {
|
|
5021
5038
|
try {
|
|
5022
5039
|
const fnName = `create${capitalize(moduleName)}PlanConfig`;
|
|
5023
5040
|
const mod = await import(`@sedim/${moduleName}/plan-config`);
|
|
@@ -5027,7 +5044,20 @@ async function loadPlanConfig(moduleName, manifest, ctx, selectedFeatures) {
|
|
|
5027
5044
|
selectedFeatures
|
|
5028
5045
|
);
|
|
5029
5046
|
}
|
|
5030
|
-
} catch
|
|
5047
|
+
} catch {
|
|
5048
|
+
}
|
|
5049
|
+
try {
|
|
5050
|
+
const fnName = `create${capitalize(moduleName)}PlanConfig`;
|
|
5051
|
+
const remoteUrl = `${packagesUrl}/${moduleName}/planConfig/plan-config.js`;
|
|
5052
|
+
const tmpPath = await downloadToTemp(remoteUrl, moduleName);
|
|
5053
|
+
const mod = await import(tmpPath);
|
|
5054
|
+
if (mod && typeof mod[fnName] === "function") {
|
|
5055
|
+
return mod[fnName](
|
|
5056
|
+
ctx,
|
|
5057
|
+
selectedFeatures
|
|
5058
|
+
);
|
|
5059
|
+
}
|
|
5060
|
+
} catch {
|
|
5031
5061
|
}
|
|
5032
5062
|
return manifestToPlanConfig(manifest, selectedFeatures, ctx);
|
|
5033
5063
|
}
|
package/package.json
CHANGED
package/CONTRIBUTING.md
DELETED
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
# Contributing to Sedim
|
|
2
|
-
|
|
3
|
-
Thank you for wanting to contribute. This guide explains everything you need to know to work on the Sedim codebase.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
To start off, you'll need an overview of what's happening in the library, so first going through the readme in full is recommended. Post that, let's try to understand the architecture of the whole library a bit.
|
|
8
|
-
|
|
9
|
-
This is a monorepo, with packages as the `core`, `cli`, `auth`, and other modules to be added in the future.
|
|
10
|
-
`core` contains the shared types between the `cli` and any `module`. The `cli` is built such that any module can seemlessly fit into it and give the same experience to the user.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
## What can you contribute?
|
|
15
|
-
|
|
16
|
-
There are lots of ways to help, no matter your experience level:
|
|
17
|
-
|
|
18
|
-
- **Bug reports and bug fixes** - something is broken, you know how to fix it
|
|
19
|
-
- **New features** - a framework adapter, an ORM adapter, a new module
|
|
20
|
-
- **Feature additions under an existing module** - more auth providers, more UI components, more email transports
|
|
21
|
-
- **UI/UX improvements** - accessibility fixes, better form states, new theme variants
|
|
22
|
-
- **Documentation** - fixing broken links, clarifying confusing sections, writing guides
|
|
23
|
-
- **Feature requests** - you want something that does not exist yet
|
|
24
|
-
- **Testing** - adding tests to existing modules, testing on different platforms
|
|
25
|
-
- **Design** - helping design better auth UI components, visual refinements
|
|
26
|
-
|
|
27
|
-
If you're unsure whether something is worth contributing, just open an issue. We'd rather you ask than guess.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Getting Started
|
|
32
|
-
|
|
33
|
-
### What you need
|
|
34
|
-
|
|
35
|
-
- **Node.js 18+**
|
|
36
|
-
- **pnpm 9+**
|
|
37
|
-
|
|
38
|
-
### Set up the project
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
git clone https://github.com/Sedimie/Sedim.git
|
|
42
|
-
cd Sedim
|
|
43
|
-
pnpm install
|
|
44
|
-
pnpm build
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Run tests
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
pnpm test # all packages
|
|
51
|
-
pnpm --filter @sedim/auth test # auth module only
|
|
52
|
-
pnpm --filter @sedim/cli test # CLI only
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Project Structure
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
Sedim/
|
|
61
|
-
├── packages/
|
|
62
|
-
│ ├── auth/ — the auth module (v0.2.0)
|
|
63
|
-
│ ├── cli/ — the Sedim CLI engine
|
|
64
|
-
│ └── core/ — shared types used by CLI and modules
|
|
65
|
-
├── apps/
|
|
66
|
-
│ ├── playground/ — fixture apps for testing
|
|
67
|
-
│ └── docs/ — VitePress documentation site
|
|
68
|
-
└── registry/
|
|
69
|
-
└── auth/latest.json — module manifest
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## Where things live
|
|
75
|
-
|
|
76
|
-
| Directory | What it is |
|
|
77
|
-
|----------|------------|
|
|
78
|
-
| `packages/auth/src/core/` | Auth logic: hashing, sessions, tokens, PKCE, TOTP, RBAC, ABAC, JWT, email |
|
|
79
|
-
| `packages/auth/src/adapters/framework/` | Framework adapters: Next.js, Express, Hono |
|
|
80
|
-
| `packages/auth/src/adapters/` | ORM adapters: Drizzle, Prisma |
|
|
81
|
-
| `packages/auth/src/ui/` | React components: forms, auth-client, use-auth hook |
|
|
82
|
-
| `packages/auth/src/ui/themed/` | CSS token files for themed UI (modern, minimal, colorful) |
|
|
83
|
-
| `packages/auth/src/templates/` | Templates with variable substitution for stamped files |
|
|
84
|
-
| `packages/auth/src/schema/` | Database schemas for Drizzle and Prisma |
|
|
85
|
-
| `packages/cli/src/` | CLI commands, detector, thinker, writer, showbaby, config |
|
|
86
|
-
| `registry/auth/latest.json` | Module manifest that describes what gets stamped |
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## How Stamping Works
|
|
91
|
-
|
|
92
|
-
When a user runs `sedim add auth`, the CLI reads from `packages/auth/src/` and stamps the selected files into the user's project. The user owns those files forever - they are not a runtime dependency.
|
|
93
|
-
|
|
94
|
-
This means one rule you should never break: **do not add imports from `@sedim/auth` into stamped files**. Stamped files run in the user's project, which may not have `@sedim/auth` installed.
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## How the CLI Works
|
|
99
|
-
|
|
100
|
-
When you run `sedim add auth`, the CLI moves through four stages:
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
detector → thinker → writer
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
**1. Detector** (`packages/cli/src/detector/`)
|
|
107
|
-
Reads the user's project files and produces a `DetectedContext`: framework, ORM, database, language, module system, and project structure. This is what drives every decision downstream.
|
|
108
|
-
|
|
109
|
-
**2. Thinker** (`packages/cli/src/thinker/`)
|
|
110
|
-
`load-plan-config.ts` tries to load the module's own `plan-config.ts` via dynamic import. If it exists, it calls `createAuthPlanConfig(ctx, selectedFeatures)` to get a rich, framework-aware plan. If not, it falls back to a generic manifest-based planner.
|
|
111
|
-
|
|
112
|
-
`build-plan.ts` takes the plan config and selected features and produces an `InstallPlan`: what files to create, what to inject where, what dependencies to install, what env vars to add.
|
|
113
|
-
|
|
114
|
-
**3. Writer** (`packages/cli/src/writer/`)
|
|
115
|
-
`apply-plan.ts` executes the approved plan. It writes files (`write-file.ts`), injects imports and code snippets (`inject-imports.ts`, `inject-code.ts`), and updates `.env` (`update-env.ts`).
|
|
116
|
-
|
|
117
|
-
The session (`packages/cli/src/session/`) saves progress after each stage. If the process is interrupted, `sedim continue auth` picks up from where it left off.
|
|
118
|
-
|
|
119
|
-
**The plan-config is the module interface**
|
|
120
|
-
Each module's `plan-config.ts` is the contract between the module and the CLI. It exports a function that takes `DetectedContext` and `selectedFeatures[]` and returns a `PlanConfig` that describes exactly what to stamp. The CLI never needs to know anything specific about a module - it just reads the plan config and executes it.
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## Ways to Contribute
|
|
125
|
-
|
|
126
|
-
### Fix a bug
|
|
127
|
-
|
|
128
|
-
If you found a bug, open an issue with the label `bug`. If you want to fix it yourself:
|
|
129
|
-
|
|
130
|
-
1. Check the issue to make sure it is confirmed
|
|
131
|
-
2. Fork the repo and create a branch from `main`
|
|
132
|
-
3. Fix it
|
|
133
|
-
4. Run `pnpm biome check .` to check formatting
|
|
134
|
-
5. Open a PR against `main`
|
|
135
|
-
|
|
136
|
-
### Add a framework adapter
|
|
137
|
-
|
|
138
|
-
The auth module currently supports Next.js, Express, and Hono. Adding a new framework adapter (e.g., Fastify, SvelteKit) is a great way to expand Sedim's reach.
|
|
139
|
-
|
|
140
|
-
Steps:
|
|
141
|
-
|
|
142
|
-
1. Create `packages/auth/src/adapters/framework/<framework>.ts` - look at `express.ts` or `hono.ts` as your reference
|
|
143
|
-
2. Implement the `DatabaseAdapter` interface and wire in all auth operations from `operations.ts`
|
|
144
|
-
3. Add the new framework to the detector in `packages/cli/src/detector/detect-framework.ts`
|
|
145
|
-
4. Add route and middleware templates in `packages/auth/src/templates/`
|
|
146
|
-
5. Test it with a new playground fixture or extend an existing one
|
|
147
|
-
6. Update the manifest in `registry/auth/latest.json`
|
|
148
|
-
|
|
149
|
-
### Add an ORM adapter
|
|
150
|
-
|
|
151
|
-
Drizzle and Prisma are currently supported. To add a new ORM (e.g., Prisma but for a different database, or a different ORM library):
|
|
152
|
-
|
|
153
|
-
1. Create `packages/auth/src/adapters/<orm>.ts`
|
|
154
|
-
2. Implement the `DatabaseAdapter` interface - look at `drizzle.ts` and `prisma.ts` for the shape
|
|
155
|
-
3. Add the new ORM detection in `packages/cli/src/detector/detect-orm.ts`
|
|
156
|
-
4. Add the schema template for the new ORM in `packages/auth/src/schema/`
|
|
157
|
-
5. Test it with the playground fixtures
|
|
158
|
-
6. Update the manifest
|
|
159
|
-
|
|
160
|
-
### Add a new module
|
|
161
|
-
|
|
162
|
-
Sedim is designed to support any feature module, not just auth. A module lives in `packages/<module-name>/` with its own `plan-config.ts` that tells the CLI what to stamp.
|
|
163
|
-
|
|
164
|
-
Steps:
|
|
165
|
-
|
|
166
|
-
1. Create `packages/<module-name>/src/` with your module source
|
|
167
|
-
2. Create `packages/<module-name>/src/plan-config.ts` exporting `create<ModuleName>PlanConfig`
|
|
168
|
-
3. Create `registry/<module-name>/latest.json` with the module manifest
|
|
169
|
-
4. The CLI will automatically pick it up via `load-plan-config.ts`
|
|
170
|
-
|
|
171
|
-
See the auth module's `plan-config.ts` as a reference - it maps feature selections to template keys and output paths.
|
|
172
|
-
|
|
173
|
-
### Add more features to the auth module
|
|
174
|
-
|
|
175
|
-
You can add to the auth module without building a whole new adapter:
|
|
176
|
-
|
|
177
|
-
- **New auth provider** (e.g., Apple OAuth, Microsoft OAuth) - add the provider to `framework-config.ts`, add PKCE flow to `operations.ts`, add UI button
|
|
178
|
-
- **New email transport** (e.g., Mailgun, AWS SES beyond the current setup) - extend `email-transport.ts`
|
|
179
|
-
- **New UI component** - add to `packages/auth/src/ui/` and wire it into `plan-config.ts`
|
|
180
|
-
- **New theme variant** - create a new CSS token file in `packages/auth/src/ui/themed/`
|
|
181
|
-
- **New database feature** - add to the schema files in `packages/auth/src/schema/`
|
|
182
|
-
|
|
183
|
-
Steps:
|
|
184
|
-
|
|
185
|
-
1. Add the feature code in the appropriate directory
|
|
186
|
-
2. Update `plan-config.ts` to include the new files when the feature is selected
|
|
187
|
-
3. Update `registry/auth/latest.json` if adding new features that change what gets stamped
|
|
188
|
-
4. Add tests
|
|
189
|
-
5. Test with `sedim add auth` in a playground fixture
|
|
190
|
-
|
|
191
|
-
### Improve the CLI
|
|
192
|
-
|
|
193
|
-
The CLI is in `packages/cli/src/`. You can work on:
|
|
194
|
-
|
|
195
|
-
- New commands (`src/commands/`)
|
|
196
|
-
- New detector strategies for frameworks, ORMs, or databases (`src/detector/`)
|
|
197
|
-
- Improving the thinker / planning engine (`src/thinker/`)
|
|
198
|
-
- Improving the writer / file operations (`src/writer/`)
|
|
199
|
-
- Improving the UX, prompts, spinners, and summaries (`src/showbaby/`)
|
|
200
|
-
|
|
201
|
-
### Improve documentation
|
|
202
|
-
|
|
203
|
-
The docs live in `apps/docs/`. If you find a broken link, an unclear explanation, or a missing guide, fix it. The docs are just Markdown files - you can edit them directly.
|
|
204
|
-
|
|
205
|
-
### Improve UI / accessibility
|
|
206
|
-
|
|
207
|
-
The auth module's UI components are in `packages/auth/src/ui/`. If you want to improve them:
|
|
208
|
-
|
|
209
|
-
- Accessibility: ARIA labels, keyboard navigation, focus management, screen reader support
|
|
210
|
-
- UX: better error states, loading states, form validation messages
|
|
211
|
-
- Design: visual refinements to the themed components, new theme variants
|
|
212
|
-
|
|
213
|
-
### Suggest a feature
|
|
214
|
-
|
|
215
|
-
Open an issue with the label `enhancement` or `feature-request`. Describe what you want to build, why it would be useful, and if possible, how you would approach it. For big features, it's good to discuss before implementing.
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## Playground Fixtures
|
|
220
|
-
|
|
221
|
-
Fixtures are real apps in `apps/playground/` that the CLI is tested against. Each fixture is a minimal project with a specific stack.
|
|
222
|
-
|
|
223
|
-
Current fixtures:
|
|
224
|
-
|
|
225
|
-
| Fixture | Stack |
|
|
226
|
-
|---------|-------|
|
|
227
|
-
| `nextjs-drizzle-ts` | Next.js + Drizzle + TypeScript |
|
|
228
|
-
| `express-prisma-ts` | Express + Prisma + TypeScript |
|
|
229
|
-
| `hono-no-orm-js` | Hono + plain JS, no ORM |
|
|
230
|
-
| `nextjs-existing-auth` | Next.js with existing next-auth (tests conflict detection) |
|
|
231
|
-
|
|
232
|
-
To add a new fixture:
|
|
233
|
-
|
|
234
|
-
1. Create the project structure in `apps/playground/<fixture-name>/`
|
|
235
|
-
2. Add a minimal `sedim.config.ts` and the minimum files needed for the framework
|
|
236
|
-
3. Run through the full `sedim add auth` flow to verify it works
|
|
237
|
-
4. Test with `sedim diff auth` and `sedim add auth --dry-run` before running for real
|
|
238
|
-
|
|
239
|
-
To run a fixture test:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
# Initialize
|
|
243
|
-
pnpm --filter @sedim/cli exec tsx src/index.ts init --force --cwd apps/playground/nextjs-drizzle-ts
|
|
244
|
-
|
|
245
|
-
# Preview what would be stamped
|
|
246
|
-
pnpm --filter @sedim/cli exec tsx src/index.ts diff auth --cwd apps/playground/nextjs-drizzle-ts
|
|
247
|
-
|
|
248
|
-
# Actually stamp
|
|
249
|
-
pnpm --filter @sedim/cli exec tsx src/index.ts add auth --cwd apps/playground/nextjs-drizzle-ts
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
To reset a fixture:
|
|
253
|
-
|
|
254
|
-
```bash
|
|
255
|
-
rm apps/playground/<fixture-name>/sedim.config.ts
|
|
256
|
-
rm -rf apps/playground/<fixture-name>/src/sedim/
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Do not push any code changes that you do in the playground except setting up a new fixture. It's only for proof of work and testing integration locally instead of having to do npm link each time changes are made.
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Testing
|
|
264
|
-
|
|
265
|
-
### Auth module tests
|
|
266
|
-
|
|
267
|
-
Tests are in `packages/auth/src/__tests__/`. Run them with:
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
cd packages/auth
|
|
271
|
-
pnpm test
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
To add a new test:
|
|
275
|
-
|
|
276
|
-
1. Create `packages/auth/src/__tests__/your-feature.test.ts`
|
|
277
|
-
2. Use `mock-db.ts` for the `DatabaseAdapter`
|
|
278
|
-
3. Import from the actual source files, not from stamped paths
|
|
279
|
-
|
|
280
|
-
### CLI tests
|
|
281
|
-
|
|
282
|
-
CLI tests are in `packages/cli/src/__tests__/` or similar. Run them with:
|
|
283
|
-
|
|
284
|
-
```bash
|
|
285
|
-
cd packages/cli
|
|
286
|
-
pnpm test
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
### TypeScript must pass
|
|
290
|
-
|
|
291
|
-
Before submitting any PR:
|
|
292
|
-
|
|
293
|
-
```bash
|
|
294
|
-
cd packages/auth
|
|
295
|
-
npx tsc --noEmit --skipLibCheck
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
All non-template source must compile without errors. Only files with `{{PLACEHOLDERS}}` (template files) are allowed to have deliberate TS errors.
|
|
299
|
-
|
|
300
|
-
---
|
|
301
|
-
|
|
302
|
-
## Code Style
|
|
303
|
-
|
|
304
|
-
- **TypeScript** - strict mode, no `any`, narrow properly
|
|
305
|
-
- **Vitest** for all tests
|
|
306
|
-
- **Biome** for linting and formatting
|
|
307
|
-
|
|
308
|
-
Run Biome before committing:
|
|
309
|
-
|
|
310
|
-
```bash
|
|
311
|
-
pnpm biome check .
|
|
312
|
-
pnpm biome format --write .
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
Biome runs in CI. PRs that fail Biome checks will be blocked.
|
|
316
|
-
|
|
317
|
-
---
|
|
318
|
-
|
|
319
|
-
## Commit Messages
|
|
320
|
-
|
|
321
|
-
Use the `[type](scope)` format:
|
|
322
|
-
|
|
323
|
-
```
|
|
324
|
-
[CLI](commands) : add interactive confirm prompt before stamping
|
|
325
|
-
[AUTH](core) : add Apple OAuth provider support
|
|
326
|
-
[CLI](detector) : add SvelteKit framework detection
|
|
327
|
-
[AUTH](ui) : fix keyboard navigation on LoginForm
|
|
328
|
-
[DOCS] : add guide for setting up OAuth providers
|
|
329
|
-
[PLAYGROUND] : add Fastify fixture
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
Valid scope options:
|
|
333
|
-
|
|
334
|
-
| Scope | Where |
|
|
335
|
-
|-------|-------|
|
|
336
|
-
| `core` | packages/auth/src/core/ |
|
|
337
|
-
| `adapters` | packages/auth/src/adapters/ |
|
|
338
|
-
| `ui` | packages/auth/src/ui/ |
|
|
339
|
-
| `templates` | packages/auth/src/templates/ |
|
|
340
|
-
| `schema` | packages/auth/src/schema/ |
|
|
341
|
-
| `plan-config` | packages/auth/src/plan-config.ts |
|
|
342
|
-
| `thinker` | packages/cli/src/thinker/ |
|
|
343
|
-
| `writer` | packages/cli/src/writer/ |
|
|
344
|
-
| `detector` | packages/cli/src/detector/ |
|
|
345
|
-
| `showbaby` | packages/cli/src/showbaby/ |
|
|
346
|
-
| `commands` | packages/cli/src/commands/ |
|
|
347
|
-
| `docs` | apps/docs/ |
|
|
348
|
-
| `registry` | registry/ |
|
|
349
|
-
|
|
350
|
-
---
|
|
351
|
-
|
|
352
|
-
## Opening an Issue
|
|
353
|
-
|
|
354
|
-
If you find a bug or want to suggest a feature:
|
|
355
|
-
|
|
356
|
-
1. Search first to check if it already exists
|
|
357
|
-
2. For bugs: include what you expected, what happened, and steps to reproduce
|
|
358
|
-
3. For features: describe what you want to build and why it would help
|
|
359
|
-
|
|
360
|
-
Use the issue templates if they are available. Good issues get faster responses.
|
|
361
|
-
|
|
362
|
-
---
|
|
363
|
-
|
|
364
|
-
## Opening a Pull Request
|
|
365
|
-
|
|
366
|
-
1. Fork the repo and create a branch from `main`
|
|
367
|
-
2. Run `pnpm biome check .` and fix any issues
|
|
368
|
-
3. Make your changes
|
|
369
|
-
4. Test them - run the relevant fixture or tests
|
|
370
|
-
5. Push and open a PR against `main`
|
|
371
|
-
6. Describe what changed and why in the PR body
|
|
372
|
-
|
|
373
|
-
For big changes (a new framework adapter, a new module, a significant feature), open an issue first to discuss before doing the work. This saves you from building something that might need a different approach.
|
|
374
|
-
|
|
375
|
-
PRs are reviewed within a few days.
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
## Questions?
|
|
380
|
-
|
|
381
|
-
Open an issue at https://github.com/Sedimie/Sedim or drop a message on Discord.
|
|
382
|
-
|
|
383
|
-
---
|
|
384
|
-
|
|
385
|
-
*Last updated: 2026-05-24*
|
package/README.md
DELETED
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
# Sedim
|
|
2
|
-

|
|
3
|
-
|
|
4
|
-
[](https://discord.com/invite/H7yutstM)
|
|
5
|
-
[](https://github.com/Sedimie/Sedim)
|
|
6
|
-
[](https://www.npmjs.com/package/@sedim/cli)
|
|
7
|
-
[](./LICENSE)
|
|
8
|
-
|
|
9
|
-
**Install complete features. Own every line.**
|
|
10
|
-
|
|
11
|
-
Sedim is an open-source codegen CLI that stamps full-stack modules into your project, with out of the box working defaults. No runtime dependencies, no black boxes - every stamped file is readable, editable, and owned by you. Skip the 80% work done repetetively for just the 20% customizations on top.
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install -g @sedim/cli
|
|
15
|
-
|
|
16
|
-
sedim init # detects your stack
|
|
17
|
-
sedim add auth # stamps auth into your project
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
The first POC for the stamping model is the Auth Module. Currently supports NextJS ( full stack ) ,Hono and Express (with react and vue frontends).
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## See It In Action
|
|
25
|
-
|
|
26
|
-
<!-- Replace with your actual YouTube embed or linked thumbnail -->
|
|
27
|
-
[](https://www.youtube.com/watch?v=YOUR_VIDEO_ID)
|
|
28
|
-
|
|
29
|
-
> 10-minute walkthrough - init, auth install, OAuth, TOTP, UI themes, and customization.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Quick Start
|
|
34
|
-
|
|
35
|
-
**Requirements:** Node ≥ 18, an existing project with a supported framework and ORM.
|
|
36
|
-
|
|
37
|
-
### 1. Install the CLI
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
npm install -g @sedim/cli
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### 2. Initialise your project
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
cd my-project
|
|
47
|
-
sedim init
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Sedim detects your framework, ORM, and language and writes a `sedim.config.ts`. If anything is detected incorrectly, edit the config file directly.
|
|
51
|
-
|
|
52
|
-
### 3. Add auth
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
sedim add auth
|
|
56
|
-
```
|
|
57
|
-
`Before writing the module directly, you can either run plan, diff or dry-run commands for the module as well!`
|
|
58
|
-
|
|
59
|
-
The CLI walks you through:
|
|
60
|
-
|
|
61
|
-
- **Environment detection** : confirms your framework, ORM, and language
|
|
62
|
-
- **Feature selection** : email/password, OAuth providers, TOTP, magic links, JWT, RBAC/ABAC
|
|
63
|
-
- **Frontend style** : headless, Tailwind styled, or themed with CSS tokens
|
|
64
|
-
- **Confirm the plan** : review exactly what files will be stamped before anything is written
|
|
65
|
-
- **Stamp** : files land in `src/sedim/auth/`
|
|
66
|
-
- **Environment variables** : add them on the spot or copy the printed list to your `.env`
|
|
67
|
-
### 4. Migrate and run
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# Drizzle
|
|
71
|
-
npx drizzle-kit push
|
|
72
|
-
|
|
73
|
-
# or Prisma
|
|
74
|
-
npx prisma migrate dev --name add_auth
|
|
75
|
-
|
|
76
|
-
npm run dev
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## What Gets Stamped
|
|
82
|
-
|
|
83
|
-
Running `sedim add auth` generates this structure in your project. You own every file.
|
|
84
|
-
|
|
85
|
-
The exact files that get stamped depend on the features you select during `sedim add auth` - OAuth providers, TOTP, magic links, JWT, and UI tier all gate which files are written. The structure below shows the full set of possible files; your install will include only the ones your selections require.
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
src/sedim/auth/
|
|
89
|
-
├── core/
|
|
90
|
-
│ ├── hash-password.ts — Argon2id password hashing
|
|
91
|
-
│ ├── generate-token.ts — session tokens, OTP codes, backup codes, PKCE verifiers
|
|
92
|
-
│ ├── session.ts — session building and sliding-window validation
|
|
93
|
-
│ ├── pkce.ts — RFC 7636 PKCE (S256 only)
|
|
94
|
-
│ ├── totp.ts — RFC 6238 TOTP (Google Authenticator compatible)
|
|
95
|
-
│ ├── totp-crypto.ts — AES-256-GCM encryption for TOTP secrets
|
|
96
|
-
│ ├── rate-limit.ts — sliding-window rate limiter
|
|
97
|
-
│ ├── rbac.ts — role-based access control
|
|
98
|
-
│ ├── abac.ts — attribute-based access control
|
|
99
|
-
│ ├── jwt.ts — hybrid JWT (short-lived signed + DB-backed refresh)
|
|
100
|
-
│ ├── oidc.ts — OIDC discovery and id_token validation
|
|
101
|
-
│ └── email-transport.ts — multi-transport email (nodemailer/resend/postmark/ses)
|
|
102
|
-
├── adapters/
|
|
103
|
-
│ ├── framework/
|
|
104
|
-
│ │ ├── nextjs.ts — Next.js App Router handler factory
|
|
105
|
-
│ │ ├── express.ts — Express router
|
|
106
|
-
│ │ ├── hono.ts — Hono route registration
|
|
107
|
-
│ │ ├── operations.ts — all auth operations (login, signup, OAuth, TOTP, etc.)
|
|
108
|
-
│ │ └── framework-config.ts — OAuth provider configuration
|
|
109
|
-
│ ├── drizzle.ts — Drizzle ORM adapter
|
|
110
|
-
│ ├── prisma.ts — Prisma ORM adapter
|
|
111
|
-
│ └── types.ts — DatabaseAdapter interface and types
|
|
112
|
-
├── ui/
|
|
113
|
-
│ ├── auth-client.ts — client-side auth fetch utilities
|
|
114
|
-
│ ├── use-auth.ts — React hook for auth state
|
|
115
|
-
│ ├── headless/ — unstyled, logic-only components
|
|
116
|
-
│ │ ├── LoginForm.tsx
|
|
117
|
-
│ │ ├── SignupForm.tsx
|
|
118
|
-
│ │ ├── ForgotPasswordForm.tsx
|
|
119
|
-
│ │ ├── ResetPasswordForm.tsx
|
|
120
|
-
│ │ ├── MagicLinkForm.tsx
|
|
121
|
-
│ │ ├── OAuthButton.tsx
|
|
122
|
-
│ │ └── TotpVerifyForm.tsx
|
|
123
|
-
│ ├── tailwind/ — Tailwind-styled components
|
|
124
|
-
│ └── themed/ — pre-built themes with CSS tokens
|
|
125
|
-
│ ├── modern-tokens.css — glassmorphism theme
|
|
126
|
-
│ ├── minimal-tokens.css — neumorphism theme
|
|
127
|
-
│ └── colorful-tokens.css — neubrutalism theme
|
|
128
|
-
├── emails/
|
|
129
|
-
│ └── email-verification.ts — email template for verification
|
|
130
|
-
├── schema.ts — Drizzle schema (users, sessions, oauth_accounts, etc.)
|
|
131
|
-
└── index.ts — module barrel export
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
The stamped auth route handler lands at `src/app/api/auth/[...all]/route.ts` (Next.js) or equivalent for other frameworks.
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## Auth Module
|
|
139
|
-
|
|
140
|
-
Auth is the first Sedim module. It ships with everything, none of it is a black box.
|
|
141
|
-
|
|
142
|
-
[Screencast from 2026-05-24 17-31-01.webm](https://github.com/user-attachments/assets/7f444748-d0bf-4329-a4cc-60507ae8b4df)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
### Features
|
|
146
|
-
|
|
147
|
-
| Feature | Detail |
|
|
148
|
-
|---|---|
|
|
149
|
-
| **Password auth** | Argon2id (OWASP params), account lockout after 10 failed attempts |
|
|
150
|
-
| **Session management** | SHA-256 hashed tokens, httpOnly cookies, full revocation |
|
|
151
|
-
| **OAuth** | Google, GitHub, Discord : PKCE (RFC 7636) on all flows |
|
|
152
|
-
| **TOTP** | RFC 6238, AES-256-GCM encrypted secrets at rest, backup codes |
|
|
153
|
-
| **Magic links** | No email enumeration, supports SMTP / Resend / Postmark / SES |
|
|
154
|
-
| **JWT** | Hybrid: short-lived signed JWTs + DB-backed refresh tokens |
|
|
155
|
-
| **RBAC / ABAC** | Role and attribute-based access control middleware |
|
|
156
|
-
| **Rate limiting** | Sliding window, in-memory or Redis store |
|
|
157
|
-
|
|
158
|
-
### Stack Support
|
|
159
|
-
|
|
160
|
-
| Framework | Drizzle | Prisma |
|
|
161
|
-
|-----------|:-------:|:------:|
|
|
162
|
-
| Next.js (App Router) | ✓ | ✓ |
|
|
163
|
-
| Express | ✓ | ✓ |
|
|
164
|
-
| Hono | ✓ | ✓ |
|
|
165
|
-
|
|
166
|
-
| Email provider | Supported |
|
|
167
|
-
|---|:---:|
|
|
168
|
-
| Nodemailer (SMTP) | ✓ |
|
|
169
|
-
| Resend | ✓ |
|
|
170
|
-
| Postmark | ✓ |
|
|
171
|
-
| AWS SES | ✓ |
|
|
172
|
-
|
|
173
|
-
### UI Tiers
|
|
174
|
-
|
|
175
|
-
Three levels so you use your own design system or ship immediately.
|
|
176
|
-
|
|
177
|
-
[Screencast from 2026-05-24 17-36-47.webm](https://github.com/user-attachments/assets/2c910cd5-8de8-4468-a2fd-db5011edd8d2)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
**Headless** - zero CSS, pure logic and markup. Bring your own styles.
|
|
181
|
-
|
|
182
|
-
**Tailwind** - fully styled with Tailwind classes, works with your existing Tailwind config.
|
|
183
|
-
|
|
184
|
-
**Themed** - pre-built themes with CSS tokens. Currently ships `minimal` and `glass`.
|
|
185
|
-
|
|
186
|
-
### Environment Variables
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
# Required
|
|
190
|
-
AUTH_SECRET= # min 32 chars, used for session signing
|
|
191
|
-
DATABASE_URL= # your database connection string
|
|
192
|
-
|
|
193
|
-
# OAuth - add only the providers you selected
|
|
194
|
-
GOOGLE_CLIENT_ID=
|
|
195
|
-
GOOGLE_CLIENT_SECRET=
|
|
196
|
-
GITHUB_CLIENT_ID=
|
|
197
|
-
GITHUB_CLIENT_SECRET=
|
|
198
|
-
DISCORD_CLIENT_ID=
|
|
199
|
-
DISCORD_CLIENT_SECRET=
|
|
200
|
-
|
|
201
|
-
# Email - add only the provider you selected
|
|
202
|
-
SMTP_HOST=
|
|
203
|
-
SMTP_PORT=
|
|
204
|
-
SMTP_USER=
|
|
205
|
-
SMTP_PASS=
|
|
206
|
-
RESEND_API_KEY=
|
|
207
|
-
POSTMARK_API_KEY=
|
|
208
|
-
AWS_ACCESS_KEY_ID=
|
|
209
|
-
AWS_SECRET_ACCESS_KEY=
|
|
210
|
-
AWS_SES_REGION=
|
|
211
|
-
|
|
212
|
-
# Optional
|
|
213
|
-
REDIS_URL= # if using Redis for rate limiting or sessions
|
|
214
|
-
TOTP_ENCRYPTION_KEY= # required if TOTP is enabled, 32-byte hex
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## Architecture
|
|
220
|
-
|
|
221
|
-
Sedim uses a **stamp model**, not a runtime SDK:
|
|
222
|
-
|
|
223
|
-
```
|
|
224
|
-
sedim add auth → generates files into src/sedim/auth/
|
|
225
|
-
(standalone forever, no sedim dependency at runtime)
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
The CLI has four components:
|
|
229
|
-
|
|
230
|
-
| Component | What it does |
|
|
231
|
-
|---|---|
|
|
232
|
-
| **Detector** | Reads your project, framework, ORM, language, existing config |
|
|
233
|
-
| **Planner (Thinker)** | Combines the module manifest with your feature selections into a stamp plan |
|
|
234
|
-
| **Writer** | Executes the plan, generates files, migrations, env var list |
|
|
235
|
-
| **Showbaby** | Shows you exactly what was stamped and what to do next |
|
|
236
|
-
|
|
237
|
-
Every module is described by a **manifest** (`registry/<module>/latest.json`) - a declarative spec of every file the module can stamp, what features gate each file, and what environment variables are required. The CLI reads the manifest, applies your choices, and stamps only what you need.
|
|
238
|
-
|
|
239
|
-
```mermaid
|
|
240
|
-
flowchart LR
|
|
241
|
-
Dev["Developer\nruns: sedim add auth"] --> Detector
|
|
242
|
-
Detector --> Thinker
|
|
243
|
-
RegistryJSON["Registry\nregistry/auth/latest.json"] --> Thinker
|
|
244
|
-
Thinker --> Writer
|
|
245
|
-
Writer --> StampedFiles["src/sedim/auth/\nuser-owned stamped files"]
|
|
246
|
-
|
|
247
|
-
RegistryJSON --> Dev
|
|
248
|
-
|
|
249
|
-
Thinker --> Plan["InstallPlan\napproved by user"]
|
|
250
|
-
Plan --> Writer
|
|
251
|
-
|
|
252
|
-
style Dev fill:#1a1a1a,color:#ffffff
|
|
253
|
-
style StampedFiles fill:#1a1a1a,color:#ffffff
|
|
254
|
-
style RegistryJSON fill:#333,color:#fff
|
|
255
|
-
style Plan fill:#333,color:#fff
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
The module source lives in `packages/<module>/src/` - this is where auth logic, UI components, adapters, and templates live. The CLI reads from here when stamping. `packages/core/` holds shared TypeScript types used by both the CLI and all modules.
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
## Registry
|
|
263
|
-
|
|
264
|
-
Module manifests live in the [`registry/`](https://github.com/Sedimie/Sedim/tree/main/registry) directory. The CLI uses the local registry during development and falls back to the GitHub raw URL for published releases.
|
|
265
|
-
|
|
266
|
-
**Available modules:**
|
|
267
|
-
|
|
268
|
-
| Module | Status |
|
|
269
|
-
|---|---|
|
|
270
|
-
| `auth` | Available |
|
|
271
|
-
| `notifications` | On the roadmap |
|
|
272
|
-
| `chat` | On the roadmap |
|
|
273
|
-
| `WebRTC` | On the roadmap |
|
|
274
|
-
| `WalletAdapters` | On the roadmap |
|
|
275
|
-
| `ai-rag` | On the roadmap |
|
|
276
|
-
| `payments` | On the roadmap |
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
## Philosophy
|
|
280
|
-
|
|
281
|
-
Most tools give you an API to call. Customization is what's keeping modularizing full stack features at bay, but with codegen model, you own the code, and hence customize it however much you want. This is not just a library to cut your grunt work, you can learn the overall implementations it uses to be able to basically use the full stack features as boilerplate code.
|
|
282
|
-
|
|
283
|
-
When you run `sedim add auth`, you get the auth system, not a dependency on one. The files live in your repo, show up in your git history, and bend to whatever you need them to do. Sedim writes the first version. Everything after that is yours.
|
|
284
|
-
|
|
285
|
-
*The best code is code you own.*
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
AI Agentic coding is another thing that this might clash with, but an AI tool might hallucinate and give 90% accuracy, leave out security considerations and make it tough to customize while also using up 3 hours and a considerable amount of tokens. This allows you to skip directly to the customizations part, with 100% hit-rate since it's static codegen, and 0 cost for the grunt work with upto date security standards being followed. Use AI tools on top of this to speed you up and make your workflow unbelievably fast.
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
### Check out the docs
|
|
293
|
-
Full documentation - customization guides, adapter references, module authoring, and escape hatches - is at [sedim.dev/docs](https://sedim.dev/docs).
|
|
294
|
-
|
|
295
|
-
### Contributions
|
|
296
|
-
To add a framework adapter, ORM adapter, or new module, see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
297
|
-
|
|
298
|
-
The module spec and adapter interface are documented there - adding a new adapter for a supported module takes a few hours once you understand the pattern.
|