create-sailor 1.10.0 → 2.0.0
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/README.md +34 -135
- package/dist/index.js +119 -2002
- package/package.json +16 -17
- package/templates/infra/ops/README.md +2 -1
- package/templates/infra/ops/platform-expected.example.json +10 -1
- package/templates/backends/python/README.md +0 -16
- package/templates/backends/python/_shared/__init__.py +0 -5
- package/templates/backends/python/pyproject.toml +0 -13
- package/templates/deploy/railway.toml +0 -13
- package/templates/deploy/vercel.json +0 -37
- package/templates/deploy/wrangler.gateway.toml +0 -11
- package/templates/deploy/wrangler.toml +0 -8
- package/templates/docs/docusaurus/README.md +0 -24
- package/templates/docs/docusaurus/docs/getting-started/develop.md +0 -20
- package/templates/docs/docusaurus/docs/getting-started/install.md +0 -11
- package/templates/docs/docusaurus/docs/intro.md +0 -15
- package/templates/docs/docusaurus/docusaurus.config.ts +0 -66
- package/templates/docs/docusaurus/package.json +0 -44
- package/templates/docs/docusaurus/sidebars.ts +0 -14
- package/templates/docs/docusaurus/src/css/custom.css +0 -22
- package/templates/docs/docusaurus/tsconfig.json +0 -7
- package/templates/docs/fumadocs/README.md +0 -46
- package/templates/docs/fumadocs/app/(home)/page.tsx +0 -22
- package/templates/docs/fumadocs/app/api/search/route.ts +0 -4
- package/templates/docs/fumadocs/app/docs/[[...slug]]/page.tsx +0 -39
- package/templates/docs/fumadocs/app/docs/layout.tsx +0 -11
- package/templates/docs/fumadocs/app/global.css +0 -10
- package/templates/docs/fumadocs/app/layout.tsx +0 -18
- package/templates/docs/fumadocs/content/docs/api.mdx +0 -31
- package/templates/docs/fumadocs/content/docs/concepts.mdx +0 -19
- package/templates/docs/fumadocs/content/docs/getting-started.mdx +0 -56
- package/templates/docs/fumadocs/content/docs/index.mdx +0 -17
- package/templates/docs/fumadocs/content/docs/meta.json +0 -4
- package/templates/docs/fumadocs/lib/source.ts +0 -7
- package/templates/docs/fumadocs/next.config.mjs +0 -20
- package/templates/docs/fumadocs/package.json +0 -33
- package/templates/docs/fumadocs/source.config.ts +0 -17
- package/templates/docs/fumadocs/tsconfig.json +0 -25
- package/templates/docs/mintlify/README.md +0 -25
- package/templates/docs/mintlify/api-reference/introduction.mdx +0 -25
- package/templates/docs/mintlify/introduction.mdx +0 -21
- package/templates/docs/mintlify/mint.json +0 -37
- package/templates/docs/mintlify/package.json +0 -14
- package/templates/docs/mintlify/quickstart.mdx +0 -26
- package/templates/docs/nextra/README.md +0 -35
- package/templates/docs/nextra/app/[[...mdxPath]]/page.tsx +0 -23
- package/templates/docs/nextra/app/layout.tsx +0 -36
- package/templates/docs/nextra/content/_meta.ts +0 -4
- package/templates/docs/nextra/content/getting-started.mdx +0 -35
- package/templates/docs/nextra/content/index.mdx +0 -18
- package/templates/docs/nextra/mdx-components.tsx +0 -10
- package/templates/docs/nextra/next.config.mjs +0 -9
- package/templates/docs/nextra/package.json +0 -25
- package/templates/docs/nextra/tsconfig.json +0 -21
- package/templates/docs/vitepress/.vitepress/config.ts +0 -35
- package/templates/docs/vitepress/README.md +0 -23
- package/templates/docs/vitepress/guide/getting-started.md +0 -26
- package/templates/docs/vitepress/guide/introduction.md +0 -12
- package/templates/docs/vitepress/index.md +0 -23
- package/templates/docs/vitepress/package.json +0 -18
- package/templates/docs/vitepress/tsconfig.json +0 -15
- package/templates/orm/drizzle/README.md +0 -58
- package/templates/orm/drizzle/drizzle.config.ts +0 -16
- package/templates/orm/drizzle/migrations/.gitkeep +0 -0
- package/templates/orm/drizzle/package.json +0 -30
- package/templates/orm/drizzle/src/index.ts +0 -31
- package/templates/orm/drizzle/src/schema/auth.ts +0 -73
- package/templates/orm/drizzle/src/schema/billing.ts +0 -37
- package/templates/orm/drizzle/src/schema/index.ts +0 -3
- package/templates/orm/drizzle/src/schema/tenant.ts +0 -57
- package/templates/orm/drizzle/tsconfig.json +0 -16
- package/templates/workflows/README.md +0 -9
- package/templates/workflows/inngest/README.md +0 -3
- package/templates/workflows/inngest/welcome-email.ts +0 -30
- package/templates/workflows/n8n/README.md +0 -3
- package/templates/workflows/n8n/example-flow.json +0 -6
- package/templates/workflows/pusher/README.md +0 -3
- package/templates/workflows/pusher/events.ts +0 -6
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: home
|
|
3
|
-
|
|
4
|
-
hero:
|
|
5
|
-
name: "{PRODUCT_NAME}"
|
|
6
|
-
text: "Documentation"
|
|
7
|
-
tagline: Built with VitePress
|
|
8
|
-
actions:
|
|
9
|
-
- theme: brand
|
|
10
|
-
text: Get started
|
|
11
|
-
link: /guide/introduction
|
|
12
|
-
- theme: alt
|
|
13
|
-
text: View on GitHub
|
|
14
|
-
link: https://github.com/your-org/your-repo
|
|
15
|
-
|
|
16
|
-
features:
|
|
17
|
-
- title: Fast
|
|
18
|
-
details: Vite-powered dev server with instant HMR.
|
|
19
|
-
- title: Markdown
|
|
20
|
-
details: Write content in markdown with Vue component support.
|
|
21
|
-
- title: SEO friendly
|
|
22
|
-
details: SSG output is statically pre-rendered for search engines.
|
|
23
|
-
---
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nebutra/docs",
|
|
3
|
-
"private": true,
|
|
4
|
-
"version": "0.0.1",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "vitepress dev --port 3001",
|
|
8
|
-
"build": "vitepress build",
|
|
9
|
-
"preview": "vitepress preview --port 3001",
|
|
10
|
-
"typecheck": "tsc --noEmit"
|
|
11
|
-
},
|
|
12
|
-
"devDependencies": {
|
|
13
|
-
"typescript": "^5.9.3",
|
|
14
|
-
"vitepress": "^1.5.0",
|
|
15
|
-
"vue": "^3.5.13"
|
|
16
|
-
},
|
|
17
|
-
"license": "MIT"
|
|
18
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "Bundler",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"resolveJsonModule": true,
|
|
10
|
-
"noEmit": true,
|
|
11
|
-
"types": ["vitepress/client"]
|
|
12
|
-
},
|
|
13
|
-
"include": [".vitepress/**/*.ts", "**/*.md"],
|
|
14
|
-
"exclude": ["node_modules", ".vitepress/dist", ".vitepress/cache"]
|
|
15
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# @nebutra/db-drizzle
|
|
2
|
-
|
|
3
|
-
Opt-in Drizzle ORM access layer. Lives alongside `@nebutra/db` (Prisma).
|
|
4
|
-
|
|
5
|
-
## When to use which
|
|
6
|
-
|
|
7
|
-
| Scenario | Use |
|
|
8
|
-
|---|---|
|
|
9
|
-
| New code, want SQL-shaped query builder | `@nebutra/db-drizzle` |
|
|
10
|
-
| Existing auth / billing / audit / oauth flows | `@nebutra/db` (Prisma — they're built on it) |
|
|
11
|
-
| Migrations + schema source of truth | `@nebutra/db` (Prisma owns schema) |
|
|
12
|
-
|
|
13
|
-
Both connect to the same `DATABASE_URL`. Treat Drizzle's `src/schema/*.ts` as
|
|
14
|
-
**read-mostly mirrors** of the Prisma schema until the dual-ORM era ends.
|
|
15
|
-
|
|
16
|
-
## Setup
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
pnpm --filter @nebutra/db-drizzle db:generate # generate migrations from schema
|
|
20
|
-
pnpm --filter @nebutra/db-drizzle db:push # push schema directly (dev only)
|
|
21
|
-
pnpm --filter @nebutra/db-drizzle db:studio # open Drizzle Studio
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Usage
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
import { db, schema } from "@nebutra/db-drizzle";
|
|
28
|
-
import { eq } from "drizzle-orm";
|
|
29
|
-
|
|
30
|
-
// Read
|
|
31
|
-
const user = await db.query.users.findFirst({
|
|
32
|
-
where: eq(schema.users.email, "alice@example.com"),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Insert
|
|
36
|
-
await db.insert(schema.users).values({
|
|
37
|
-
id: crypto.randomUUID(),
|
|
38
|
-
name: "Alice",
|
|
39
|
-
email: "alice@example.com",
|
|
40
|
-
});
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Schema coverage
|
|
44
|
-
|
|
45
|
-
Currently mirrored (read-safe with the Prisma side):
|
|
46
|
-
|
|
47
|
-
- `auth.user` / `auth.session` / `auth.account` / `auth.verification`
|
|
48
|
-
- `auth.organization` / `auth.member` / `auth.invitation`
|
|
49
|
-
- `public.subscriptions` / `public.usage_ledger`
|
|
50
|
-
|
|
51
|
-
Add more in `src/schema/*.ts` as you migrate features off Prisma. Keep
|
|
52
|
-
column names + types in lock-step with `packages/platform/db/prisma/schema.prisma`.
|
|
53
|
-
|
|
54
|
-
## Migration path (dual-ORM → Drizzle primary)
|
|
55
|
-
|
|
56
|
-
Not on the roadmap until enough new code lands on Drizzle to make the swap
|
|
57
|
-
worth the risk. Until then, write against whichever client matches your use
|
|
58
|
-
case and don't double-write the same table from both.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "drizzle-kit";
|
|
2
|
-
|
|
3
|
-
if (!process.env.DATABASE_URL) {
|
|
4
|
-
throw new Error("DATABASE_URL is not set — required for drizzle-kit");
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export default defineConfig({
|
|
8
|
-
schema: "./src/schema/*.ts",
|
|
9
|
-
out: "./migrations",
|
|
10
|
-
dialect: "postgresql",
|
|
11
|
-
dbCredentials: {
|
|
12
|
-
url: process.env.DATABASE_URL,
|
|
13
|
-
},
|
|
14
|
-
verbose: true,
|
|
15
|
-
strict: true,
|
|
16
|
-
});
|
|
File without changes
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nebutra/db-drizzle",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./src/index.ts",
|
|
7
|
-
"types": "./src/index.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": "./src/index.ts",
|
|
10
|
-
"./schema": "./src/schema/index.ts",
|
|
11
|
-
"./schema/*": "./src/schema/*.ts"
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"db:generate": "drizzle-kit generate",
|
|
15
|
-
"db:migrate": "drizzle-kit migrate",
|
|
16
|
-
"db:push": "drizzle-kit push",
|
|
17
|
-
"db:studio": "drizzle-kit studio",
|
|
18
|
-
"typecheck": "tsc --noEmit"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"drizzle-orm": "^0.36.4",
|
|
22
|
-
"postgres": "^3.4.5"
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"drizzle-kit": "^0.30.1",
|
|
26
|
-
"typescript": "^5.7.2",
|
|
27
|
-
"@types/node": "^22.10.5"
|
|
28
|
-
},
|
|
29
|
-
"license": "MIT"
|
|
30
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { drizzle } from "drizzle-orm/postgres-js";
|
|
2
|
-
import postgres from "postgres";
|
|
3
|
-
import * as schema from "./schema";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @nebutra/db-drizzle — opt-in Drizzle ORM access layer.
|
|
7
|
-
*
|
|
8
|
-
* Lives alongside the primary Prisma client at @nebutra/db. Both connect to
|
|
9
|
-
* the same DATABASE_URL — Drizzle is for new code that wants the
|
|
10
|
-
* lighter-weight, SQL-shaped query builder; Prisma stays as the entry point
|
|
11
|
-
* for the auth / billing / audit packages that were built on top of it.
|
|
12
|
-
*
|
|
13
|
-
* Migration policy: Prisma owns the schema until the dual-ORM era ends.
|
|
14
|
-
* `drizzle-kit generate` here is for *adding* Drizzle-only tables; existing
|
|
15
|
-
* Prisma tables get mirrored into src/schema/*.ts for read access only.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const connectionString = process.env.DATABASE_URL;
|
|
19
|
-
if (!connectionString) {
|
|
20
|
-
throw new Error("[@nebutra/db-drizzle] DATABASE_URL is not set. Drizzle cannot connect.");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const client = postgres(connectionString, {
|
|
24
|
-
max: Number(process.env.DATABASE_POOL_MAX ?? 10),
|
|
25
|
-
idle_timeout: 30,
|
|
26
|
-
prepare: false,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
export const db = drizzle(client, { schema, logger: false });
|
|
30
|
-
export { schema };
|
|
31
|
-
export type Database = typeof db;
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { boolean, pgSchema, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `auth` schema — mirrors the Better Auth tables defined in
|
|
5
|
-
* @nebutra/db's Prisma schema (auth.user / auth.session / auth.account /
|
|
6
|
-
* auth.verification). Drizzle reads from the same physical tables.
|
|
7
|
-
*
|
|
8
|
-
* Adding NEW columns here without a corresponding Prisma change is unsafe —
|
|
9
|
-
* Prisma's generator + RLS policies must stay in sync. Use this file as a
|
|
10
|
-
* read-mostly mirror until Drizzle becomes primary.
|
|
11
|
-
*/
|
|
12
|
-
export const authSchema = pgSchema("auth");
|
|
13
|
-
|
|
14
|
-
export const users = authSchema.table(
|
|
15
|
-
"user",
|
|
16
|
-
{
|
|
17
|
-
id: text("id").primaryKey(),
|
|
18
|
-
name: text("name").notNull(),
|
|
19
|
-
email: text("email").notNull(),
|
|
20
|
-
emailVerified: boolean("email_verified").notNull().default(false),
|
|
21
|
-
image: text("image"),
|
|
22
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
23
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
24
|
-
},
|
|
25
|
-
(t) => ({
|
|
26
|
-
emailIdx: uniqueIndex("user_email_unique").on(t.email),
|
|
27
|
-
}),
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
export const sessions = authSchema.table("session", {
|
|
31
|
-
id: text("id").primaryKey(),
|
|
32
|
-
userId: text("user_id")
|
|
33
|
-
.notNull()
|
|
34
|
-
.references(() => users.id, { onDelete: "cascade" }),
|
|
35
|
-
token: text("token").notNull(),
|
|
36
|
-
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
37
|
-
ipAddress: text("ip_address"),
|
|
38
|
-
userAgent: text("user_agent"),
|
|
39
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
40
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export const accounts = authSchema.table("account", {
|
|
44
|
-
id: text("id").primaryKey(),
|
|
45
|
-
userId: text("user_id")
|
|
46
|
-
.notNull()
|
|
47
|
-
.references(() => users.id, { onDelete: "cascade" }),
|
|
48
|
-
providerId: text("provider_id").notNull(),
|
|
49
|
-
accountId: text("account_id").notNull(),
|
|
50
|
-
accessToken: text("access_token"),
|
|
51
|
-
refreshToken: text("refresh_token"),
|
|
52
|
-
idToken: text("id_token"),
|
|
53
|
-
accessTokenExpiresAt: timestamp("access_token_expires_at", { withTimezone: true }),
|
|
54
|
-
refreshTokenExpiresAt: timestamp("refresh_token_expires_at", { withTimezone: true }),
|
|
55
|
-
scope: text("scope"),
|
|
56
|
-
password: text("password"),
|
|
57
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
58
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
export const verifications = authSchema.table("verification", {
|
|
62
|
-
id: text("id").primaryKey(),
|
|
63
|
-
identifier: text("identifier").notNull(),
|
|
64
|
-
value: text("value").notNull(),
|
|
65
|
-
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
66
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
67
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
export type User = typeof users.$inferSelect;
|
|
71
|
-
export type NewUser = typeof users.$inferInsert;
|
|
72
|
-
export type Session = typeof sessions.$inferSelect;
|
|
73
|
-
export type Account = typeof accounts.$inferSelect;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { integer, jsonb, numeric, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
|
2
|
-
import { organizations } from "./tenant";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Subscription + UsageLedger mirrors for the commerce/billing flow. The
|
|
6
|
-
* Prisma side owns writes; Drizzle is read-mostly for now.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export const subscriptions = pgTable("subscriptions", {
|
|
10
|
-
id: text("id").primaryKey(),
|
|
11
|
-
organizationId: text("organization_id")
|
|
12
|
-
.notNull()
|
|
13
|
-
.references(() => organizations.id, { onDelete: "cascade" }),
|
|
14
|
-
plan: text("plan").notNull(),
|
|
15
|
-
status: text("status").notNull(),
|
|
16
|
-
provider: text("provider").notNull(),
|
|
17
|
-
externalId: text("external_id"),
|
|
18
|
-
seats: integer("seats").notNull().default(1),
|
|
19
|
-
currentPeriodEnd: timestamp("current_period_end", { withTimezone: true }),
|
|
20
|
-
metadata: jsonb("metadata"),
|
|
21
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
22
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const usageLedger = pgTable("usage_ledger", {
|
|
26
|
-
id: text("id").primaryKey(),
|
|
27
|
-
organizationId: text("organization_id")
|
|
28
|
-
.notNull()
|
|
29
|
-
.references(() => organizations.id, { onDelete: "cascade" }),
|
|
30
|
-
meter: text("meter").notNull(),
|
|
31
|
-
quantity: numeric("quantity", { precision: 20, scale: 6 }).notNull(),
|
|
32
|
-
metadata: jsonb("metadata"),
|
|
33
|
-
recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull().defaultNow(),
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
export type Subscription = typeof subscriptions.$inferSelect;
|
|
37
|
-
export type UsageLedgerEntry = typeof usageLedger.$inferSelect;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { pgSchema, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
|
|
2
|
-
import { users } from "./auth";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* `auth.organization` + `auth.member` + `auth.invitation` — Better Auth's
|
|
6
|
-
* tenancy primitives. Mirrors the Prisma BAOrganization / BAMember /
|
|
7
|
-
* BAInvitation models.
|
|
8
|
-
*/
|
|
9
|
-
export const orgSchema = pgSchema("auth");
|
|
10
|
-
|
|
11
|
-
export const organizations = orgSchema.table(
|
|
12
|
-
"organization",
|
|
13
|
-
{
|
|
14
|
-
id: text("id").primaryKey(),
|
|
15
|
-
name: text("name").notNull(),
|
|
16
|
-
slug: text("slug").notNull(),
|
|
17
|
-
logo: text("logo"),
|
|
18
|
-
metadata: text("metadata"),
|
|
19
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
20
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
21
|
-
},
|
|
22
|
-
(t) => ({
|
|
23
|
-
slugIdx: uniqueIndex("organization_slug_unique").on(t.slug),
|
|
24
|
-
}),
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
export const members = orgSchema.table("member", {
|
|
28
|
-
id: text("id").primaryKey(),
|
|
29
|
-
userId: text("user_id")
|
|
30
|
-
.notNull()
|
|
31
|
-
.references(() => users.id, { onDelete: "cascade" }),
|
|
32
|
-
organizationId: text("organization_id")
|
|
33
|
-
.notNull()
|
|
34
|
-
.references(() => organizations.id, { onDelete: "cascade" }),
|
|
35
|
-
role: text("role").notNull().default("member"),
|
|
36
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
export const invitations = orgSchema.table("invitation", {
|
|
40
|
-
id: text("id").primaryKey(),
|
|
41
|
-
email: text("email").notNull(),
|
|
42
|
-
inviterId: text("inviter_id").notNull(),
|
|
43
|
-
organizationId: text("organization_id")
|
|
44
|
-
.notNull()
|
|
45
|
-
.references(() => organizations.id, { onDelete: "cascade" }),
|
|
46
|
-
role: text("role"),
|
|
47
|
-
status: text("status").notNull().default("pending"),
|
|
48
|
-
expiresAt: timestamp("expires_at", { withTimezone: true }),
|
|
49
|
-
token: text("token"),
|
|
50
|
-
acceptedAt: timestamp("accepted_at", { withTimezone: true }),
|
|
51
|
-
declinedAt: timestamp("declined_at", { withTimezone: true }),
|
|
52
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
export type Organization = typeof organizations.$inferSelect;
|
|
56
|
-
export type Member = typeof members.$inferSelect;
|
|
57
|
-
export type Invitation = typeof invitations.$inferSelect;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.base.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "./dist",
|
|
5
|
-
"rootDir": "./src",
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"moduleResolution": "Bundler",
|
|
8
|
-
"target": "ES2022",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"incremental": false
|
|
13
|
-
},
|
|
14
|
-
"include": ["src/**/*.ts", "drizzle.config.ts"],
|
|
15
|
-
"exclude": ["node_modules", "dist", "migrations"]
|
|
16
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# workflows
|
|
2
|
-
|
|
3
|
-
Durable workflow & event-orchestration definitions for `{PRODUCT_NAME}`.
|
|
4
|
-
|
|
5
|
-
| Folder | Purpose |
|
|
6
|
-
|--------|---------|
|
|
7
|
-
| `inngest/` | Inngest functions (durable steps, cron, fan-out) |
|
|
8
|
-
| `n8n/` | n8n flow exports (low-code automations) |
|
|
9
|
-
| `pusher/` | Pusher Channels event maps for real-time fan-out |
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sample Inngest welcome-email function for scaffolds.
|
|
3
|
-
*
|
|
4
|
-
* Production path: swap the step body for `@nebutra/email` once the
|
|
5
|
-
* generated project has a real email provider env (RESEND_API_KEY etc.):
|
|
6
|
-
*
|
|
7
|
-
* import { sendEmail } from "@nebutra/email";
|
|
8
|
-
* await sendEmail({ to: event.data.email, template: "welcome", ... });
|
|
9
|
-
*
|
|
10
|
-
* Until then this is intentionally sample-only — returns the intended
|
|
11
|
-
* recipient so the workflow is testable without sending mail.
|
|
12
|
-
*/
|
|
13
|
-
import { Inngest } from "inngest";
|
|
14
|
-
|
|
15
|
-
export const inngest = new Inngest({ id: "{PRODUCT_NAME}" });
|
|
16
|
-
|
|
17
|
-
export const welcomeEmail = inngest.createFunction(
|
|
18
|
-
{ id: "welcome-email" },
|
|
19
|
-
{ event: "user/created" },
|
|
20
|
-
async ({ event, step }) => {
|
|
21
|
-
await step.run("send-welcome", async () => {
|
|
22
|
-
// Sample-only: do not send until @nebutra/email + provider keys are wired.
|
|
23
|
-
return {
|
|
24
|
-
to: event.data.email,
|
|
25
|
-
status: "sample-only",
|
|
26
|
-
hint: "Replace with sendEmail() from @nebutra/email",
|
|
27
|
-
};
|
|
28
|
-
});
|
|
29
|
-
},
|
|
30
|
-
);
|