@murumets-ee/create 0.1.3 → 0.1.5
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/cli.js +158 -36
- package/dist/index.js +149 -27
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as e,b as
|
|
2
|
+
import{a as e,b as g,c as f,d as p,e as T}from"./chunk-ZAX4VH4C.js";import*as u from"@clack/prompts";import w from"picocolors";import*as s from"@clack/prompts";function I(t){let n={},r=t.slice(2);for(let o=0;o<r.length;o++){let l=r[o];if(l==="--mode"&&r[o+1]){let c=r[++o];(c==="single"||c==="multi")&&(n.mode=c)}else l==="--install"?n.install=!0:l==="--no-install"?n.install=!1:!l.startsWith("-")&&!n.name&&(n.name=l)}return n}async function S(t){let n=I(process.argv),r=n.name??t;if(r&&n.mode&&n.install!==void 0)return{name:r,mode:n.mode,installDeps:n.install};s.intro("@murumets-ee/create");let o=r??await s.text({message:"Project name:",placeholder:"my-project",validate:b=>{if(!b)return"Project name is required";if(!/^[a-z0-9-]+$/.test(b))return"Use lowercase letters, numbers, and hyphens only"}});if(s.isCancel(o))return s.cancel("Cancelled."),null;let l=n.mode??await s.select({message:"App setup:",options:[{value:"single",label:"Single app",hint:"everything in one Next.js project"},{value:"multi",label:"Admin + Frontend",hint:"two apps in a pnpm workspace"}]});if(s.isCancel(l))return s.cancel("Cancelled."),null;let c=n.install??await s.confirm({message:"Install dependencies?",initialValue:!0});return s.isCancel(c)?(s.cancel("Cancelled."),null):{name:o,mode:l,installDeps:c}}import{join as N}from"path";import{join as m}from"path";async function E(t,n){await e(m(t,"lib/auth.ts"),`import { getToolkitApp } from './app'
|
|
3
3
|
import { getAuth } from '@murumets-ee/auth'
|
|
4
4
|
|
|
5
5
|
await getToolkitApp()
|
|
@@ -249,7 +249,7 @@ export async function createFirstAdmin(formData: FormData) {
|
|
|
249
249
|
|
|
250
250
|
return { ok: true, email: adminUser.user.email }
|
|
251
251
|
}
|
|
252
|
-
`)}import{join as
|
|
252
|
+
`)}import{join as d}from"path";async function P(t,n){let{name:r}=n;await e(d(t,".env.example"),`DATABASE_URL=postgresql://${r}:${r}_dev_password@localhost:5432/${r}_dev
|
|
253
253
|
BETTER_AUTH_SECRET=dev-secret-change-me-in-production-min-32-chars
|
|
254
254
|
BETTER_AUTH_URL=http://localhost:3000
|
|
255
255
|
LOG_LEVEL=debug
|
|
@@ -259,14 +259,94 @@ RESEND_API_KEY=
|
|
|
259
259
|
RESEND_WEBHOOK_SECRET=
|
|
260
260
|
MAIL_FROM=noreply@example.com
|
|
261
261
|
CSAT_SECRET=
|
|
262
|
-
`),await
|
|
263
|
-
|
|
264
|
-
|
|
262
|
+
`),await e(d(t,".dockerignore"),`# Dependencies (installed inside Docker)
|
|
263
|
+
node_modules/
|
|
264
|
+
.pnpm-store/
|
|
265
265
|
|
|
266
|
-
#
|
|
267
|
-
.
|
|
266
|
+
# Build outputs (rebuilt inside Docker)
|
|
267
|
+
.next/
|
|
268
|
+
out/
|
|
269
|
+
dist/
|
|
270
|
+
|
|
271
|
+
# Git
|
|
272
|
+
.git/
|
|
273
|
+
.gitignore
|
|
274
|
+
|
|
275
|
+
# Environment files (pass via docker run --env-file)
|
|
276
|
+
.env
|
|
277
|
+
.env.*
|
|
268
278
|
!.env.example
|
|
269
|
-
|
|
279
|
+
|
|
280
|
+
# Docker files
|
|
281
|
+
Dockerfile*
|
|
282
|
+
.dockerignore
|
|
283
|
+
docker-compose*.yml
|
|
284
|
+
|
|
285
|
+
# Tests
|
|
286
|
+
coverage/
|
|
287
|
+
**/*.test.*
|
|
288
|
+
**/*.spec.*
|
|
289
|
+
**/vitest.config.*
|
|
290
|
+
docker-compose.test.yml
|
|
291
|
+
|
|
292
|
+
# Development tooling
|
|
293
|
+
.vscode/
|
|
294
|
+
.idea/
|
|
295
|
+
.turbo/
|
|
296
|
+
.cache/
|
|
297
|
+
*.tsbuildinfo
|
|
298
|
+
|
|
299
|
+
# Documentation
|
|
300
|
+
*.md
|
|
301
|
+
docs/
|
|
302
|
+
|
|
303
|
+
# OS files
|
|
304
|
+
.DS_Store
|
|
305
|
+
Thumbs.db
|
|
306
|
+
`),await e(d(t,"Dockerfile"),`# --- Base image ---
|
|
307
|
+
# Node 22 LTS (Debian slim \u2014 glibc required for sharp image optimization)
|
|
308
|
+
FROM node:22-slim AS base
|
|
309
|
+
|
|
310
|
+
# --- Stage 1: Install dependencies ---
|
|
311
|
+
FROM base AS deps
|
|
312
|
+
WORKDIR /app
|
|
313
|
+
RUN corepack enable pnpm
|
|
314
|
+
COPY package.json pnpm-lock.yaml ./
|
|
315
|
+
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \\
|
|
316
|
+
pnpm install --frozen-lockfile
|
|
317
|
+
|
|
318
|
+
# --- Stage 2: Build the application ---
|
|
319
|
+
FROM base AS builder
|
|
320
|
+
WORKDIR /app
|
|
321
|
+
RUN corepack enable pnpm
|
|
322
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
323
|
+
COPY . .
|
|
324
|
+
ENV NODE_ENV=production
|
|
325
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
326
|
+
RUN pnpm build
|
|
327
|
+
|
|
328
|
+
# --- Stage 3: Production runner ---
|
|
329
|
+
FROM base AS runner
|
|
330
|
+
WORKDIR /app
|
|
331
|
+
ENV NODE_ENV=production
|
|
332
|
+
ENV PORT=3000
|
|
333
|
+
ENV HOSTNAME=0.0.0.0
|
|
334
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
335
|
+
|
|
336
|
+
# Copy standalone output (includes server.js + traced node_modules)
|
|
337
|
+
COPY --from=builder --chown=node:node /app/.next/standalone ./
|
|
338
|
+
# Copy static assets (JS/CSS chunks \u2014 excluded from standalone trace)
|
|
339
|
+
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
|
|
340
|
+
# Copy public assets (favicon, robots.txt, images)
|
|
341
|
+
COPY --from=builder --chown=node:node /app/public ./public
|
|
342
|
+
# Copy migrations (applied at app startup by the toolkit migration runner)
|
|
343
|
+
COPY --from=builder --chown=node:node /app/migrations ./migrations
|
|
344
|
+
|
|
345
|
+
# Run as non-root user
|
|
346
|
+
USER node
|
|
347
|
+
EXPOSE 3000
|
|
348
|
+
CMD ["node", "server.js"]
|
|
349
|
+
`),await e(d(t,"docker-compose.yml"),`services:
|
|
270
350
|
postgres:
|
|
271
351
|
image: postgres:17-alpine
|
|
272
352
|
container_name: ${r}-postgres
|
|
@@ -288,9 +368,51 @@ generated/
|
|
|
288
368
|
volumes:
|
|
289
369
|
postgres_data:
|
|
290
370
|
name: ${r}_postgres_data
|
|
291
|
-
`)
|
|
371
|
+
`),await e(d(t,"docker-compose.prod.yml"),`services:
|
|
372
|
+
app:
|
|
373
|
+
build: .
|
|
374
|
+
restart: unless-stopped
|
|
375
|
+
env_file: .env
|
|
376
|
+
depends_on:
|
|
377
|
+
postgres:
|
|
378
|
+
condition: service_healthy
|
|
379
|
+
ports:
|
|
380
|
+
- "3000:3000"
|
|
381
|
+
networks:
|
|
382
|
+
- internal
|
|
383
|
+
|
|
384
|
+
postgres:
|
|
385
|
+
image: postgres:17-alpine
|
|
386
|
+
restart: unless-stopped
|
|
387
|
+
environment:
|
|
388
|
+
POSTGRES_USER: ${r}
|
|
389
|
+
POSTGRES_PASSWORD: \${DB_PASSWORD}
|
|
390
|
+
POSTGRES_DB: ${r}
|
|
391
|
+
volumes:
|
|
392
|
+
- postgres_data:/var/lib/postgresql/data
|
|
393
|
+
healthcheck:
|
|
394
|
+
test: ["CMD-SHELL", "pg_isready -U ${r} -d ${r}"]
|
|
395
|
+
interval: 10s
|
|
396
|
+
timeout: 5s
|
|
397
|
+
retries: 5
|
|
398
|
+
networks:
|
|
399
|
+
- internal
|
|
400
|
+
|
|
401
|
+
volumes:
|
|
402
|
+
postgres_data:
|
|
403
|
+
|
|
404
|
+
networks:
|
|
405
|
+
internal:
|
|
406
|
+
`),await T(d(t,".gitignore"),`
|
|
407
|
+
# Toolkit generated files
|
|
408
|
+
generated/
|
|
409
|
+
|
|
410
|
+
# Environment
|
|
411
|
+
.env*
|
|
412
|
+
!.env.example
|
|
413
|
+
`)}import{join as k}from"path";async function z(t,n){await e(k(t,"entities/index.ts"),`export { Article } from './article'
|
|
292
414
|
export { Category } from './category'
|
|
293
|
-
`),await e(
|
|
415
|
+
`),await e(k(t,"entities/article.ts"),`import { behavior, defineEntity, field } from '@murumets-ee/entity'
|
|
294
416
|
|
|
295
417
|
export const Article = defineEntity({
|
|
296
418
|
name: 'article',
|
|
@@ -321,7 +443,7 @@ export const Article = defineEntity({
|
|
|
321
443
|
delete: 'group.admin',
|
|
322
444
|
},
|
|
323
445
|
})
|
|
324
|
-
`),await e(
|
|
446
|
+
`),await e(k(t,"entities/category.ts"),`import { defineEntity, field } from '@murumets-ee/entity'
|
|
325
447
|
|
|
326
448
|
export const Category = defineEntity({
|
|
327
449
|
name: 'category',
|
|
@@ -338,13 +460,13 @@ export const Category = defineEntity({
|
|
|
338
460
|
delete: 'group.admin',
|
|
339
461
|
},
|
|
340
462
|
})
|
|
341
|
-
`)}import{join as
|
|
463
|
+
`)}import{join as R}from"path";async function C(t,n){await e(R(t,"i18n/routing.ts"),`import { defineRouting } from 'next-intl/routing'
|
|
342
464
|
|
|
343
465
|
export const routing = defineRouting({
|
|
344
466
|
locales: ['en'],
|
|
345
467
|
defaultLocale: 'en',
|
|
346
468
|
})
|
|
347
|
-
`),await e(
|
|
469
|
+
`),await e(R(t,"i18n/request.ts"),`import { getRequestConfig } from 'next-intl/server'
|
|
348
470
|
import { hasLocale } from 'next-intl'
|
|
349
471
|
import { routing } from './routing'
|
|
350
472
|
import { getAuthMessages } from '@murumets-ee/auth-ui/i18n'
|
|
@@ -364,7 +486,7 @@ export default getRequestConfig(async ({ requestLocale }) => {
|
|
|
364
486
|
},
|
|
365
487
|
}
|
|
366
488
|
})
|
|
367
|
-
`)}import{mkdir as
|
|
489
|
+
`)}import{mkdir as L}from"fs/promises";import{join as a}from"path";var i={myorgCore:"0.1.0",myorgDb:"0.1.0",myorgEntity:"0.1.0",myorgLogging:"0.1.0",myorgAuth:"0.1.0",myorgAuthUi:"0.1.0",myorgAdminUi:"0.1.0",myorgContent:"0.1.0",myorgContentApi:"0.1.0",myorgSettings:"0.1.0",myorgStorage:"0.1.0",myorgMedia:"0.1.0",myorgTaxonomy:"0.1.0",myorgQueue:"0.1.0",myorgMail:"0.1.0",myorgTicketing:"0.1.0",myorgTicketingUi:"0.1.0",myorgEditor:"0.1.0",myorgBlocks:"0.1.0",myorgTokens:"0.1.0",myorgUi:"0.1.0",myorgCli:"0.1.0",betterAuth:"1.4.0",drizzleOrm:"0.45.1",nextIntl:"4.8.2",nextThemes:"0.4.6",lucideReact:"0.563.0",postgres:"3.4.5",reactHookForm:"7.71.1",hookformResolvers:"5.2.2",zod:"3.24.1",drizzleKit:"0.27.2",tsx:"4.19.2",babelReactCompiler:"1.0.0"};async function _(t,n,r){await F(t,n),r?.("Workspace root created"),r?.("Creating admin app..."),await B(t,n),r?.("Admin app created"),r?.("Creating web app..."),await H(t,n),r?.("Web app created"),await D(t,n),r?.("Shared config package created")}async function F(t,n){let{name:r}=n;await L(t,{recursive:!0}),await e(a(t,"pnpm-workspace.yaml"),`packages:
|
|
368
490
|
- 'packages/*'
|
|
369
491
|
- 'apps/*'
|
|
370
492
|
|
|
@@ -435,7 +557,7 @@ CSAT_SECRET=
|
|
|
435
557
|
volumes:
|
|
436
558
|
postgres_data:
|
|
437
559
|
name: ${r}_postgres_data
|
|
438
|
-
`)}async function
|
|
560
|
+
`)}async function D(t,n){let{name:r}=n,o=a(t,"packages/config");await e(a(o,"package.json"),`${JSON.stringify({name:`@${r}/config`,version:"0.1.0",private:!0,type:"module",exports:{".":"./toolkit.config.ts","./entities":"./entities/index.ts","./entities/*":"./entities/*","./app":"./lib/app.ts","./auth":"./lib/auth.ts","./auth-client":"./lib/auth-client.ts"},dependencies:{"@murumets-ee/core":`^${i.myorgCore}`,"@murumets-ee/db":`^${i.myorgDb}`,"@murumets-ee/entity":`^${i.myorgEntity}`,"@murumets-ee/logging":`^${i.myorgLogging}`,"@murumets-ee/auth":`^${i.myorgAuth}`,"better-auth":`^${i.betterAuth}`,"drizzle-orm":`^${i.drizzleOrm}`,postgres:`^${i.postgres}`,zod:`^${i.zod}`}},null,2)}
|
|
439
561
|
`),await e(a(o,"tsconfig.json"),`${JSON.stringify({compilerOptions:{target:"ES2022",module:"ESNext",moduleResolution:"Bundler",strict:!0,esModuleInterop:!0,skipLibCheck:!0,resolveJsonModule:!0},include:["**/*.ts"]},null,2)}
|
|
440
562
|
`),await e(a(o,"toolkit.config.ts"),`import { auth } from '@murumets-ee/auth/plugin'
|
|
441
563
|
import { content } from '@murumets-ee/content/plugin'
|
|
@@ -703,7 +825,7 @@ async function resetDb() {
|
|
|
703
825
|
}
|
|
704
826
|
|
|
705
827
|
resetDb().catch(console.error)
|
|
706
|
-
`)}async function
|
|
828
|
+
`)}async function B(t,n){let{name:r}=n,o=a(t,"apps/admin");await L(a(t,"apps"),{recursive:!0}),p(`pnpm create next-app@${"16"} ${o} --typescript --tailwind --no-eslint --app --no-src-dir --turbopack --react-compiler --skip-install --import-alias "@/*"`),await f(o,["app/page.tsx","app/page.module.css","app/fonts","README.md","pnpm-workspace.yaml"]),await g(a(o,"package.json"),{dependencies:{[`@${r}/config`]:"workspace:*","@murumets-ee/auth-ui":`^${i.myorgAuthUi}`,"better-auth":`^${i.betterAuth}`,"next-intl":`^${i.nextIntl}`,"next-themes":`^${i.nextThemes}`,"lucide-react":`^${i.lucideReact}`,"react-hook-form":`^${i.reactHookForm}`,"@hookform/resolvers":`^${i.hookformResolvers}`,zod:`^${i.zod}`},devDependencies:{"babel-plugin-react-compiler":i.babelReactCompiler}});let{appendToFile:l}=await import("./utils-VX57GKZX.js");await l(a(o,".gitignore"),`
|
|
707
829
|
# Environment
|
|
708
830
|
.env*
|
|
709
831
|
!.env.example
|
|
@@ -1251,7 +1373,7 @@ export async function createFirstAdmin(formData: FormData) {
|
|
|
1251
1373
|
|
|
1252
1374
|
return { ok: true, email: adminUser.user.email }
|
|
1253
1375
|
}
|
|
1254
|
-
`)}async function
|
|
1376
|
+
`)}async function H(t,n){let{name:r}=n,o=a(t,"apps/web");p(`pnpm create next-app@${"16"} ${o} --typescript --tailwind --no-eslint --app --no-src-dir --turbopack --react-compiler --skip-install --import-alias "@/*"`),await f(o,["app/page.tsx","app/page.module.css","app/fonts","README.md","pnpm-workspace.yaml"]),await g(a(o,"package.json"),{dependencies:{[`@${r}/config`]:"workspace:*","@murumets-ee/core":`^${i.myorgCore}`,"@murumets-ee/auth-ui":`^${i.myorgAuthUi}`,"next-intl":`^${i.nextIntl}`,"next-themes":`^${i.nextThemes}`,"lucide-react":`^${i.lucideReact}`},devDependencies:{"babel-plugin-react-compiler":i.babelReactCompiler}});let{appendToFile:l}=await import("./utils-VX57GKZX.js");await l(a(o,".gitignore"),`
|
|
1255
1377
|
# Environment
|
|
1256
1378
|
.env*
|
|
1257
1379
|
!.env.example
|
|
@@ -1539,7 +1661,7 @@ export default async function HomePage() {
|
|
|
1539
1661
|
</div>
|
|
1540
1662
|
)
|
|
1541
1663
|
}
|
|
1542
|
-
`)}import{join as
|
|
1664
|
+
`)}import{join as h}from"path";async function $(t,n){let{name:r}=n;await e(h(t,"next.config.ts"),`import type { NextConfig } from 'next'
|
|
1543
1665
|
import createNextIntlPlugin from 'next-intl/plugin'
|
|
1544
1666
|
|
|
1545
1667
|
const withNextIntl = createNextIntlPlugin('./i18n/request.ts')
|
|
@@ -1564,7 +1686,7 @@ const nextConfig: NextConfig = {
|
|
|
1564
1686
|
}
|
|
1565
1687
|
|
|
1566
1688
|
export default withNextIntl(nextConfig)
|
|
1567
|
-
`),await e(
|
|
1689
|
+
`),await e(h(t,"proxy.ts"),`import { NextRequest, NextResponse } from 'next/server'
|
|
1568
1690
|
import createMiddleware from 'next-intl/middleware'
|
|
1569
1691
|
import { routing } from './i18n/routing'
|
|
1570
1692
|
|
|
@@ -1595,12 +1717,12 @@ export function proxy(request: NextRequest) {
|
|
|
1595
1717
|
export const config = {
|
|
1596
1718
|
matcher: '/((?!api|_next|_vercel|.*\\\\..*).*)',
|
|
1597
1719
|
}
|
|
1598
|
-
`),await e(
|
|
1720
|
+
`),await e(h(t,"app/layout.tsx"),`import './globals.css'
|
|
1599
1721
|
|
|
1600
1722
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
1601
1723
|
return children
|
|
1602
1724
|
}
|
|
1603
|
-
`),await e(
|
|
1725
|
+
`),await e(h(t,"app/[locale]/layout.tsx"),`import type { Metadata } from 'next'
|
|
1604
1726
|
import { Geist, Geist_Mono } from 'next/font/google'
|
|
1605
1727
|
import { NextIntlClientProvider } from 'next-intl'
|
|
1606
1728
|
import { getMessages } from 'next-intl/server'
|
|
@@ -1649,7 +1771,7 @@ export default async function LocaleLayout({
|
|
|
1649
1771
|
</html>
|
|
1650
1772
|
)
|
|
1651
1773
|
}
|
|
1652
|
-
`),await e(
|
|
1774
|
+
`),await e(h(t,"app/[locale]/page.tsx"),`import { createQueryClient } from '@murumets-ee/core/clients'
|
|
1653
1775
|
import { Article, Category } from '@/entities'
|
|
1654
1776
|
import { getToolkitApp } from '@/lib/app'
|
|
1655
1777
|
|
|
@@ -1713,13 +1835,13 @@ export default async function HomePage() {
|
|
|
1713
1835
|
</div>
|
|
1714
1836
|
)
|
|
1715
1837
|
}
|
|
1716
|
-
`)}import{join as
|
|
1838
|
+
`)}import{join as A}from"path";async function M(t,n){await e(A(t,"scripts/generate-schema.ts"),`import { execSync } from 'node:child_process'
|
|
1717
1839
|
execSync('npx @murumets-ee/cli generate', { stdio: 'inherit', cwd: import.meta.dirname + '/..' })
|
|
1718
|
-
`),await e(
|
|
1840
|
+
`),await e(A(t,"scripts/migrate.ts"),`import { execSync } from 'node:child_process'
|
|
1719
1841
|
execSync('npx @murumets-ee/cli migrate', { stdio: 'inherit', cwd: import.meta.dirname + '/..' })
|
|
1720
|
-
`),await e(
|
|
1842
|
+
`),await e(A(t,"scripts/reset-db.ts"),`import { execSync } from 'node:child_process'
|
|
1721
1843
|
execSync('npx @murumets-ee/cli reset --force', { stdio: 'inherit', cwd: import.meta.dirname + '/..' })
|
|
1722
|
-
`)}import{join as
|
|
1844
|
+
`)}import{join as y}from"path";async function O(t,n){let{name:r}=n;await e(y(t,"app/globals.css"),`@import "tailwindcss";
|
|
1723
1845
|
@source "../node_modules/@murumets-ee/auth-ui/dist";
|
|
1724
1846
|
|
|
1725
1847
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
@@ -1746,7 +1868,7 @@ body {
|
|
|
1746
1868
|
color: var(--foreground);
|
|
1747
1869
|
font-family: Arial, Helvetica, sans-serif;
|
|
1748
1870
|
}
|
|
1749
|
-
`),await e(
|
|
1871
|
+
`),await e(y(t,"app/theme-provider.tsx"),`'use client'
|
|
1750
1872
|
|
|
1751
1873
|
import { ThemeProvider as NextThemesProvider } from 'next-themes'
|
|
1752
1874
|
import type { ReactNode } from 'react'
|
|
@@ -1763,7 +1885,7 @@ export function ThemeProvider({ children }: { children: ReactNode }) {
|
|
|
1763
1885
|
</NextThemesProvider>
|
|
1764
1886
|
)
|
|
1765
1887
|
}
|
|
1766
|
-
`),await e(
|
|
1888
|
+
`),await e(y(t,"app/theme-toggle.tsx"),`'use client'
|
|
1767
1889
|
|
|
1768
1890
|
import { useTheme } from 'next-themes'
|
|
1769
1891
|
import { useState, useEffect } from 'react'
|
|
@@ -1790,7 +1912,7 @@ export function ThemeToggle() {
|
|
|
1790
1912
|
</button>
|
|
1791
1913
|
)
|
|
1792
1914
|
}
|
|
1793
|
-
`),await e(
|
|
1915
|
+
`),await e(y(t,"app/nav-header.tsx"),`'use client'
|
|
1794
1916
|
|
|
1795
1917
|
import Link from 'next/link'
|
|
1796
1918
|
import { usePathname } from 'next/navigation'
|
|
@@ -1834,7 +1956,7 @@ export function NavHeader() {
|
|
|
1834
1956
|
</header>
|
|
1835
1957
|
)
|
|
1836
1958
|
}
|
|
1837
|
-
`)}import{join as
|
|
1959
|
+
`)}import{join as x}from"path";async function q(t,n){let{name:r}=n;await e(x(t,"toolkit.config.ts"),`import { auth } from '@murumets-ee/auth/plugin'
|
|
1838
1960
|
import { content } from '@murumets-ee/content/plugin'
|
|
1839
1961
|
import { defineConfig } from '@murumets-ee/core'
|
|
1840
1962
|
import { mail, ResendMailProvider } from '@murumets-ee/mail'
|
|
@@ -1886,7 +2008,7 @@ export default defineConfig({
|
|
|
1886
2008
|
],
|
|
1887
2009
|
projectRoot: import.meta.dirname,
|
|
1888
2010
|
})
|
|
1889
|
-
`),await e(
|
|
2011
|
+
`),await e(x(t,"lib/app.ts"),`import { createApp, setApp, type ToolkitApp } from '@murumets-ee/core'
|
|
1890
2012
|
import config from '../toolkit.config'
|
|
1891
2013
|
|
|
1892
2014
|
let appInstance: ToolkitApp | null = null
|
|
@@ -1900,7 +2022,7 @@ export async function getToolkitApp(): Promise<ToolkitApp> {
|
|
|
1900
2022
|
}
|
|
1901
2023
|
return appInstance
|
|
1902
2024
|
}
|
|
1903
|
-
`),await e(
|
|
2025
|
+
`),await e(x(t,"drizzle.config.ts"),`import type { Config } from 'drizzle-kit'
|
|
1904
2026
|
|
|
1905
2027
|
if (!process.env.DATABASE_URL) {
|
|
1906
2028
|
throw new Error('DATABASE_URL environment variable is required')
|
|
@@ -1914,7 +2036,7 @@ export default {
|
|
|
1914
2036
|
url: process.env.DATABASE_URL,
|
|
1915
2037
|
},
|
|
1916
2038
|
} satisfies Config
|
|
1917
|
-
`),await e(
|
|
2039
|
+
`),await e(x(t,"auth.config.ts"),`import { betterAuth } from 'better-auth'
|
|
1918
2040
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
|
1919
2041
|
import { admin } from 'better-auth/plugins'
|
|
1920
2042
|
import { organization } from 'better-auth/plugins/organization'
|
|
@@ -1932,8 +2054,8 @@ export const auth = betterAuth({
|
|
|
1932
2054
|
organization(),
|
|
1933
2055
|
],
|
|
1934
2056
|
})
|
|
1935
|
-
`),await e(
|
|
2057
|
+
`),await e(x(t,"generated/auth-schema.ts"),`// This file is generated by better-auth CLI.
|
|
1936
2058
|
// Run: npx @better-auth/cli generate --config auth.config.ts -y
|
|
1937
2059
|
export {}
|
|
1938
|
-
`)}async function
|
|
1939
|
-
`),"Next steps"),
|
|
2060
|
+
`)}async function U(t,n){t.mode==="single"?await W(t,n):await j(t,n)}async function W(t,n){let r=N(process.cwd(),t.name);n?.("Creating Next.js app..."),p(`pnpm create next-app@${"16"} ${t.name} --typescript --tailwind --no-eslint --app --no-src-dir --turbopack --react-compiler --skip-install --import-alias "@/*"`),await f(r,["app/page.tsx","app/page.module.css","app/fonts","README.md"]),await g(N(r,"package.json"),{type:"module",dependencies:{"@murumets-ee/core":`^${i.myorgCore}`,"@murumets-ee/db":`^${i.myorgDb}`,"@murumets-ee/entity":`^${i.myorgEntity}`,"@murumets-ee/logging":`^${i.myorgLogging}`,"@murumets-ee/auth":`^${i.myorgAuth}`,"@murumets-ee/auth-ui":`^${i.myorgAuthUi}`,"@murumets-ee/admin-ui":`^${i.myorgAdminUi}`,"@murumets-ee/content":`^${i.myorgContent}`,"@murumets-ee/settings":`^${i.myorgSettings}`,"@murumets-ee/storage":`^${i.myorgStorage}`,"@murumets-ee/media":`^${i.myorgMedia}`,"@murumets-ee/taxonomy":`^${i.myorgTaxonomy}`,"@murumets-ee/queue":`^${i.myorgQueue}`,"@murumets-ee/mail":`^${i.myorgMail}`,"@murumets-ee/ticketing":`^${i.myorgTicketing}`,"@murumets-ee/ticketing-ui":`^${i.myorgTicketingUi}`,"@murumets-ee/tokens":`^${i.myorgTokens}`,"better-auth":`^${i.betterAuth}`,"drizzle-orm":`^${i.drizzleOrm}`,"next-intl":`^${i.nextIntl}`,"next-themes":`^${i.nextThemes}`,"lucide-react":`^${i.lucideReact}`,postgres:`^${i.postgres}`,"react-hook-form":`^${i.reactHookForm}`,"@hookform/resolvers":`^${i.hookformResolvers}`,zod:`^${i.zod}`},devDependencies:{"drizzle-kit":`^${i.drizzleKit}`,tsx:`^${i.tsx}`,"babel-plugin-react-compiler":i.babelReactCompiler},scripts:{"db:generate":"tsx --env-file=.env scripts/generate-schema.ts","db:migrate:generate":"drizzle-kit generate","db:migrate":"tsx --env-file=.env scripts/migrate.ts","db:reset":"tsx --env-file=.env scripts/reset-db.ts"}}),n?.("Adding toolkit files..."),await P(r,t),await z(r,t),await q(r,t),await E(r,t),await C(r,t),await $(r,t),await O(r,t),await M(r,t),t.installDeps&&(n?.("Installing dependencies..."),p("pnpm install",{cwd:r}))}async function j(t,n){let r=N(process.cwd(),t.name);n?.("Creating workspace..."),await _(r,t,n),t.installDeps&&(n?.("Installing dependencies..."),p("pnpm install",{cwd:r}))}async function G(){let t=process.argv[2],n=await S(t);if(!n)return;let r=u.spinner();try{r.start("Creating Next.js app..."),await U(n,b=>{r.stop(`${w.green("\u2713")} Done`),r.start(b)}),r.stop(`${w.green("\u2713")} Done`);let l=n.mode==="multi"?"packages/config/auth.config.ts":"auth.config.ts",c=[`cd ${n.name}`,"docker compose up -d","cp .env.example .env",`npx @better-auth/cli generate --config ${l} -y`,"pnpm db:generate","npx @murumets-ee/cli admin-api:init","pnpm db:generate","pnpm db:migrate:generate","pnpm db:migrate","pnpm dev","# Visit /setup to create your first admin user"];u.note(c.join(`
|
|
2061
|
+
`),"Next steps"),u.outro(`${w.green("Success!")} Your project is ready.`)}catch(o){r.stop(w.red("Failed.")),u.log.error(o instanceof Error?o.message:String(o)),process.exit(1)}}G();
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e,b as
|
|
1
|
+
import{a as e,b as c,c as u,d as l,e as y}from"./chunk-CUB6XFPE.js";import{join as v}from"path";import{join as s}from"path";async function w(t,n){await e(s(t,"lib/auth.ts"),`import { getToolkitApp } from './app'
|
|
2
2
|
import { getAuth } from '@murumets-ee/auth'
|
|
3
3
|
|
|
4
4
|
await getToolkitApp()
|
|
@@ -248,7 +248,7 @@ export async function createFirstAdmin(formData: FormData) {
|
|
|
248
248
|
|
|
249
249
|
return { ok: true, email: adminUser.user.email }
|
|
250
250
|
}
|
|
251
|
-
`)}import{join as
|
|
251
|
+
`)}import{join as m}from"path";async function k(t,n){let{name:r}=n;await e(m(t,".env.example"),`DATABASE_URL=postgresql://${r}:${r}_dev_password@localhost:5432/${r}_dev
|
|
252
252
|
BETTER_AUTH_SECRET=dev-secret-change-me-in-production-min-32-chars
|
|
253
253
|
BETTER_AUTH_URL=http://localhost:3000
|
|
254
254
|
LOG_LEVEL=debug
|
|
@@ -258,14 +258,94 @@ RESEND_API_KEY=
|
|
|
258
258
|
RESEND_WEBHOOK_SECRET=
|
|
259
259
|
MAIL_FROM=noreply@example.com
|
|
260
260
|
CSAT_SECRET=
|
|
261
|
-
`),await
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
`),await e(m(t,".dockerignore"),`# Dependencies (installed inside Docker)
|
|
262
|
+
node_modules/
|
|
263
|
+
.pnpm-store/
|
|
264
264
|
|
|
265
|
-
#
|
|
266
|
-
.
|
|
265
|
+
# Build outputs (rebuilt inside Docker)
|
|
266
|
+
.next/
|
|
267
|
+
out/
|
|
268
|
+
dist/
|
|
269
|
+
|
|
270
|
+
# Git
|
|
271
|
+
.git/
|
|
272
|
+
.gitignore
|
|
273
|
+
|
|
274
|
+
# Environment files (pass via docker run --env-file)
|
|
275
|
+
.env
|
|
276
|
+
.env.*
|
|
267
277
|
!.env.example
|
|
268
|
-
|
|
278
|
+
|
|
279
|
+
# Docker files
|
|
280
|
+
Dockerfile*
|
|
281
|
+
.dockerignore
|
|
282
|
+
docker-compose*.yml
|
|
283
|
+
|
|
284
|
+
# Tests
|
|
285
|
+
coverage/
|
|
286
|
+
**/*.test.*
|
|
287
|
+
**/*.spec.*
|
|
288
|
+
**/vitest.config.*
|
|
289
|
+
docker-compose.test.yml
|
|
290
|
+
|
|
291
|
+
# Development tooling
|
|
292
|
+
.vscode/
|
|
293
|
+
.idea/
|
|
294
|
+
.turbo/
|
|
295
|
+
.cache/
|
|
296
|
+
*.tsbuildinfo
|
|
297
|
+
|
|
298
|
+
# Documentation
|
|
299
|
+
*.md
|
|
300
|
+
docs/
|
|
301
|
+
|
|
302
|
+
# OS files
|
|
303
|
+
.DS_Store
|
|
304
|
+
Thumbs.db
|
|
305
|
+
`),await e(m(t,"Dockerfile"),`# --- Base image ---
|
|
306
|
+
# Node 22 LTS (Debian slim \u2014 glibc required for sharp image optimization)
|
|
307
|
+
FROM node:22-slim AS base
|
|
308
|
+
|
|
309
|
+
# --- Stage 1: Install dependencies ---
|
|
310
|
+
FROM base AS deps
|
|
311
|
+
WORKDIR /app
|
|
312
|
+
RUN corepack enable pnpm
|
|
313
|
+
COPY package.json pnpm-lock.yaml ./
|
|
314
|
+
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \\
|
|
315
|
+
pnpm install --frozen-lockfile
|
|
316
|
+
|
|
317
|
+
# --- Stage 2: Build the application ---
|
|
318
|
+
FROM base AS builder
|
|
319
|
+
WORKDIR /app
|
|
320
|
+
RUN corepack enable pnpm
|
|
321
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
322
|
+
COPY . .
|
|
323
|
+
ENV NODE_ENV=production
|
|
324
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
325
|
+
RUN pnpm build
|
|
326
|
+
|
|
327
|
+
# --- Stage 3: Production runner ---
|
|
328
|
+
FROM base AS runner
|
|
329
|
+
WORKDIR /app
|
|
330
|
+
ENV NODE_ENV=production
|
|
331
|
+
ENV PORT=3000
|
|
332
|
+
ENV HOSTNAME=0.0.0.0
|
|
333
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
334
|
+
|
|
335
|
+
# Copy standalone output (includes server.js + traced node_modules)
|
|
336
|
+
COPY --from=builder --chown=node:node /app/.next/standalone ./
|
|
337
|
+
# Copy static assets (JS/CSS chunks \u2014 excluded from standalone trace)
|
|
338
|
+
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
|
|
339
|
+
# Copy public assets (favicon, robots.txt, images)
|
|
340
|
+
COPY --from=builder --chown=node:node /app/public ./public
|
|
341
|
+
# Copy migrations (applied at app startup by the toolkit migration runner)
|
|
342
|
+
COPY --from=builder --chown=node:node /app/migrations ./migrations
|
|
343
|
+
|
|
344
|
+
# Run as non-root user
|
|
345
|
+
USER node
|
|
346
|
+
EXPOSE 3000
|
|
347
|
+
CMD ["node", "server.js"]
|
|
348
|
+
`),await e(m(t,"docker-compose.yml"),`services:
|
|
269
349
|
postgres:
|
|
270
350
|
image: postgres:17-alpine
|
|
271
351
|
container_name: ${r}-postgres
|
|
@@ -287,6 +367,48 @@ generated/
|
|
|
287
367
|
volumes:
|
|
288
368
|
postgres_data:
|
|
289
369
|
name: ${r}_postgres_data
|
|
370
|
+
`),await e(m(t,"docker-compose.prod.yml"),`services:
|
|
371
|
+
app:
|
|
372
|
+
build: .
|
|
373
|
+
restart: unless-stopped
|
|
374
|
+
env_file: .env
|
|
375
|
+
depends_on:
|
|
376
|
+
postgres:
|
|
377
|
+
condition: service_healthy
|
|
378
|
+
ports:
|
|
379
|
+
- "3000:3000"
|
|
380
|
+
networks:
|
|
381
|
+
- internal
|
|
382
|
+
|
|
383
|
+
postgres:
|
|
384
|
+
image: postgres:17-alpine
|
|
385
|
+
restart: unless-stopped
|
|
386
|
+
environment:
|
|
387
|
+
POSTGRES_USER: ${r}
|
|
388
|
+
POSTGRES_PASSWORD: \${DB_PASSWORD}
|
|
389
|
+
POSTGRES_DB: ${r}
|
|
390
|
+
volumes:
|
|
391
|
+
- postgres_data:/var/lib/postgresql/data
|
|
392
|
+
healthcheck:
|
|
393
|
+
test: ["CMD-SHELL", "pg_isready -U ${r} -d ${r}"]
|
|
394
|
+
interval: 10s
|
|
395
|
+
timeout: 5s
|
|
396
|
+
retries: 5
|
|
397
|
+
networks:
|
|
398
|
+
- internal
|
|
399
|
+
|
|
400
|
+
volumes:
|
|
401
|
+
postgres_data:
|
|
402
|
+
|
|
403
|
+
networks:
|
|
404
|
+
internal:
|
|
405
|
+
`),await y(m(t,".gitignore"),`
|
|
406
|
+
# Toolkit generated files
|
|
407
|
+
generated/
|
|
408
|
+
|
|
409
|
+
# Environment
|
|
410
|
+
.env*
|
|
411
|
+
!.env.example
|
|
290
412
|
`)}import{join as x}from"path";async function A(t,n){await e(x(t,"entities/index.ts"),`export { Article } from './article'
|
|
291
413
|
export { Category } from './category'
|
|
292
414
|
`),await e(x(t,"entities/article.ts"),`import { behavior, defineEntity, field } from '@murumets-ee/entity'
|
|
@@ -363,7 +485,7 @@ export default getRequestConfig(async ({ requestLocale }) => {
|
|
|
363
485
|
},
|
|
364
486
|
}
|
|
365
487
|
})
|
|
366
|
-
`)}import{mkdir as
|
|
488
|
+
`)}import{mkdir as S}from"fs/promises";import{join as o}from"path";var i={myorgCore:"0.1.0",myorgDb:"0.1.0",myorgEntity:"0.1.0",myorgLogging:"0.1.0",myorgAuth:"0.1.0",myorgAuthUi:"0.1.0",myorgAdminUi:"0.1.0",myorgContent:"0.1.0",myorgContentApi:"0.1.0",myorgSettings:"0.1.0",myorgStorage:"0.1.0",myorgMedia:"0.1.0",myorgTaxonomy:"0.1.0",myorgQueue:"0.1.0",myorgMail:"0.1.0",myorgTicketing:"0.1.0",myorgTicketingUi:"0.1.0",myorgEditor:"0.1.0",myorgBlocks:"0.1.0",myorgTokens:"0.1.0",myorgUi:"0.1.0",myorgCli:"0.1.0",betterAuth:"1.4.0",drizzleOrm:"0.45.1",nextIntl:"4.8.2",nextThemes:"0.4.6",lucideReact:"0.563.0",postgres:"3.4.5",reactHookForm:"7.71.1",hookformResolvers:"5.2.2",zod:"3.24.1",drizzleKit:"0.27.2",tsx:"4.19.2",babelReactCompiler:"1.0.0"};async function E(t,n,r){await L(t,n),r?.("Workspace root created"),r?.("Creating admin app..."),await $(t,n),r?.("Admin app created"),r?.("Creating web app..."),await M(t,n),r?.("Web app created"),await _(t,n),r?.("Shared config package created")}async function L(t,n){let{name:r}=n;await S(t,{recursive:!0}),await e(o(t,"pnpm-workspace.yaml"),`packages:
|
|
367
489
|
- 'packages/*'
|
|
368
490
|
- 'apps/*'
|
|
369
491
|
|
|
@@ -702,7 +824,7 @@ async function resetDb() {
|
|
|
702
824
|
}
|
|
703
825
|
|
|
704
826
|
resetDb().catch(console.error)
|
|
705
|
-
`)}async function $(t,n){let{name:r}=n,a=o(t,"apps/admin");await
|
|
827
|
+
`)}async function $(t,n){let{name:r}=n,a=o(t,"apps/admin");await S(o(t,"apps"),{recursive:!0}),l(`pnpm create next-app@${"16"} ${a} --typescript --tailwind --no-eslint --app --no-src-dir --turbopack --react-compiler --skip-install --import-alias "@/*"`),await u(a,["app/page.tsx","app/page.module.css","app/fonts","README.md","pnpm-workspace.yaml"]),await c(o(a,"package.json"),{dependencies:{[`@${r}/config`]:"workspace:*","@murumets-ee/auth-ui":`^${i.myorgAuthUi}`,"better-auth":`^${i.betterAuth}`,"next-intl":`^${i.nextIntl}`,"next-themes":`^${i.nextThemes}`,"lucide-react":`^${i.lucideReact}`,"react-hook-form":`^${i.reactHookForm}`,"@hookform/resolvers":`^${i.hookformResolvers}`,zod:`^${i.zod}`},devDependencies:{"babel-plugin-react-compiler":i.babelReactCompiler}});let{appendToFile:h}=await import("./utils-42K2ZGUL.js");await h(o(a,".gitignore"),`
|
|
706
828
|
# Environment
|
|
707
829
|
.env*
|
|
708
830
|
!.env.example
|
|
@@ -1250,7 +1372,7 @@ export async function createFirstAdmin(formData: FormData) {
|
|
|
1250
1372
|
|
|
1251
1373
|
return { ok: true, email: adminUser.user.email }
|
|
1252
1374
|
}
|
|
1253
|
-
`)}async function M(t,n){let{name:r}=n,a=o(t,"apps/web");
|
|
1375
|
+
`)}async function M(t,n){let{name:r}=n,a=o(t,"apps/web");l(`pnpm create next-app@${"16"} ${a} --typescript --tailwind --no-eslint --app --no-src-dir --turbopack --react-compiler --skip-install --import-alias "@/*"`),await u(a,["app/page.tsx","app/page.module.css","app/fonts","README.md","pnpm-workspace.yaml"]),await c(o(a,"package.json"),{dependencies:{[`@${r}/config`]:"workspace:*","@murumets-ee/core":`^${i.myorgCore}`,"@murumets-ee/auth-ui":`^${i.myorgAuthUi}`,"next-intl":`^${i.nextIntl}`,"next-themes":`^${i.nextThemes}`,"lucide-react":`^${i.lucideReact}`},devDependencies:{"babel-plugin-react-compiler":i.babelReactCompiler}});let{appendToFile:h}=await import("./utils-42K2ZGUL.js");await h(o(a,".gitignore"),`
|
|
1254
1376
|
# Environment
|
|
1255
1377
|
.env*
|
|
1256
1378
|
!.env.example
|
|
@@ -1538,7 +1660,7 @@ export default async function HomePage() {
|
|
|
1538
1660
|
</div>
|
|
1539
1661
|
)
|
|
1540
1662
|
}
|
|
1541
|
-
`)}import{join as
|
|
1663
|
+
`)}import{join as p}from"path";async function P(t,n){let{name:r}=n;await e(p(t,"next.config.ts"),`import type { NextConfig } from 'next'
|
|
1542
1664
|
import createNextIntlPlugin from 'next-intl/plugin'
|
|
1543
1665
|
|
|
1544
1666
|
const withNextIntl = createNextIntlPlugin('./i18n/request.ts')
|
|
@@ -1563,7 +1685,7 @@ const nextConfig: NextConfig = {
|
|
|
1563
1685
|
}
|
|
1564
1686
|
|
|
1565
1687
|
export default withNextIntl(nextConfig)
|
|
1566
|
-
`),await e(
|
|
1688
|
+
`),await e(p(t,"proxy.ts"),`import { NextRequest, NextResponse } from 'next/server'
|
|
1567
1689
|
import createMiddleware from 'next-intl/middleware'
|
|
1568
1690
|
import { routing } from './i18n/routing'
|
|
1569
1691
|
|
|
@@ -1594,12 +1716,12 @@ export function proxy(request: NextRequest) {
|
|
|
1594
1716
|
export const config = {
|
|
1595
1717
|
matcher: '/((?!api|_next|_vercel|.*\\\\..*).*)',
|
|
1596
1718
|
}
|
|
1597
|
-
`),await e(
|
|
1719
|
+
`),await e(p(t,"app/layout.tsx"),`import './globals.css'
|
|
1598
1720
|
|
|
1599
1721
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
1600
1722
|
return children
|
|
1601
1723
|
}
|
|
1602
|
-
`),await e(
|
|
1724
|
+
`),await e(p(t,"app/[locale]/layout.tsx"),`import type { Metadata } from 'next'
|
|
1603
1725
|
import { Geist, Geist_Mono } from 'next/font/google'
|
|
1604
1726
|
import { NextIntlClientProvider } from 'next-intl'
|
|
1605
1727
|
import { getMessages } from 'next-intl/server'
|
|
@@ -1648,7 +1770,7 @@ export default async function LocaleLayout({
|
|
|
1648
1770
|
</html>
|
|
1649
1771
|
)
|
|
1650
1772
|
}
|
|
1651
|
-
`),await e(
|
|
1773
|
+
`),await e(p(t,"app/[locale]/page.tsx"),`import { createQueryClient } from '@murumets-ee/core/clients'
|
|
1652
1774
|
import { Article, Category } from '@/entities'
|
|
1653
1775
|
import { getToolkitApp } from '@/lib/app'
|
|
1654
1776
|
|
|
@@ -1712,13 +1834,13 @@ export default async function HomePage() {
|
|
|
1712
1834
|
</div>
|
|
1713
1835
|
)
|
|
1714
1836
|
}
|
|
1715
|
-
`)}import{join as b}from"path";async function
|
|
1837
|
+
`)}import{join as b}from"path";async function z(t,n){await e(b(t,"scripts/generate-schema.ts"),`import { execSync } from 'node:child_process'
|
|
1716
1838
|
execSync('npx @murumets-ee/cli generate', { stdio: 'inherit', cwd: import.meta.dirname + '/..' })
|
|
1717
1839
|
`),await e(b(t,"scripts/migrate.ts"),`import { execSync } from 'node:child_process'
|
|
1718
1840
|
execSync('npx @murumets-ee/cli migrate', { stdio: 'inherit', cwd: import.meta.dirname + '/..' })
|
|
1719
1841
|
`),await e(b(t,"scripts/reset-db.ts"),`import { execSync } from 'node:child_process'
|
|
1720
1842
|
execSync('npx @murumets-ee/cli reset --force', { stdio: 'inherit', cwd: import.meta.dirname + '/..' })
|
|
1721
|
-
`)}import{join as
|
|
1843
|
+
`)}import{join as f}from"path";async function R(t,n){let{name:r}=n;await e(f(t,"app/globals.css"),`@import "tailwindcss";
|
|
1722
1844
|
@source "../node_modules/@murumets-ee/auth-ui/dist";
|
|
1723
1845
|
|
|
1724
1846
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
@@ -1745,7 +1867,7 @@ body {
|
|
|
1745
1867
|
color: var(--foreground);
|
|
1746
1868
|
font-family: Arial, Helvetica, sans-serif;
|
|
1747
1869
|
}
|
|
1748
|
-
`),await e(
|
|
1870
|
+
`),await e(f(t,"app/theme-provider.tsx"),`'use client'
|
|
1749
1871
|
|
|
1750
1872
|
import { ThemeProvider as NextThemesProvider } from 'next-themes'
|
|
1751
1873
|
import type { ReactNode } from 'react'
|
|
@@ -1762,7 +1884,7 @@ export function ThemeProvider({ children }: { children: ReactNode }) {
|
|
|
1762
1884
|
</NextThemesProvider>
|
|
1763
1885
|
)
|
|
1764
1886
|
}
|
|
1765
|
-
`),await e(
|
|
1887
|
+
`),await e(f(t,"app/theme-toggle.tsx"),`'use client'
|
|
1766
1888
|
|
|
1767
1889
|
import { useTheme } from 'next-themes'
|
|
1768
1890
|
import { useState, useEffect } from 'react'
|
|
@@ -1789,7 +1911,7 @@ export function ThemeToggle() {
|
|
|
1789
1911
|
</button>
|
|
1790
1912
|
)
|
|
1791
1913
|
}
|
|
1792
|
-
`),await e(
|
|
1914
|
+
`),await e(f(t,"app/nav-header.tsx"),`'use client'
|
|
1793
1915
|
|
|
1794
1916
|
import Link from 'next/link'
|
|
1795
1917
|
import { usePathname } from 'next/navigation'
|
|
@@ -1833,7 +1955,7 @@ export function NavHeader() {
|
|
|
1833
1955
|
</header>
|
|
1834
1956
|
)
|
|
1835
1957
|
}
|
|
1836
|
-
`)}import{join as
|
|
1958
|
+
`)}import{join as d}from"path";async function C(t,n){let{name:r}=n;await e(d(t,"toolkit.config.ts"),`import { auth } from '@murumets-ee/auth/plugin'
|
|
1837
1959
|
import { content } from '@murumets-ee/content/plugin'
|
|
1838
1960
|
import { defineConfig } from '@murumets-ee/core'
|
|
1839
1961
|
import { mail, ResendMailProvider } from '@murumets-ee/mail'
|
|
@@ -1885,7 +2007,7 @@ export default defineConfig({
|
|
|
1885
2007
|
],
|
|
1886
2008
|
projectRoot: import.meta.dirname,
|
|
1887
2009
|
})
|
|
1888
|
-
`),await e(
|
|
2010
|
+
`),await e(d(t,"lib/app.ts"),`import { createApp, setApp, type ToolkitApp } from '@murumets-ee/core'
|
|
1889
2011
|
import config from '../toolkit.config'
|
|
1890
2012
|
|
|
1891
2013
|
let appInstance: ToolkitApp | null = null
|
|
@@ -1899,7 +2021,7 @@ export async function getToolkitApp(): Promise<ToolkitApp> {
|
|
|
1899
2021
|
}
|
|
1900
2022
|
return appInstance
|
|
1901
2023
|
}
|
|
1902
|
-
`),await e(
|
|
2024
|
+
`),await e(d(t,"drizzle.config.ts"),`import type { Config } from 'drizzle-kit'
|
|
1903
2025
|
|
|
1904
2026
|
if (!process.env.DATABASE_URL) {
|
|
1905
2027
|
throw new Error('DATABASE_URL environment variable is required')
|
|
@@ -1913,7 +2035,7 @@ export default {
|
|
|
1913
2035
|
url: process.env.DATABASE_URL,
|
|
1914
2036
|
},
|
|
1915
2037
|
} satisfies Config
|
|
1916
|
-
`),await e(
|
|
2038
|
+
`),await e(d(t,"auth.config.ts"),`import { betterAuth } from 'better-auth'
|
|
1917
2039
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
|
1918
2040
|
import { admin } from 'better-auth/plugins'
|
|
1919
2041
|
import { organization } from 'better-auth/plugins/organization'
|
|
@@ -1931,7 +2053,7 @@ export const auth = betterAuth({
|
|
|
1931
2053
|
organization(),
|
|
1932
2054
|
],
|
|
1933
2055
|
})
|
|
1934
|
-
`),await e(
|
|
2056
|
+
`),await e(d(t,"generated/auth-schema.ts"),`// This file is generated by better-auth CLI.
|
|
1935
2057
|
// Run: npx @better-auth/cli generate --config auth.config.ts -y
|
|
1936
2058
|
export {}
|
|
1937
|
-
`)}async function
|
|
2059
|
+
`)}async function O(t,n){t.mode==="single"?await q(t,n):await U(t,n)}async function q(t,n){let r=v(process.cwd(),t.name);n?.("Creating Next.js app..."),l(`pnpm create next-app@${"16"} ${t.name} --typescript --tailwind --no-eslint --app --no-src-dir --turbopack --react-compiler --skip-install --import-alias "@/*"`),await u(r,["app/page.tsx","app/page.module.css","app/fonts","README.md"]),await c(v(r,"package.json"),{type:"module",dependencies:{"@murumets-ee/core":`^${i.myorgCore}`,"@murumets-ee/db":`^${i.myorgDb}`,"@murumets-ee/entity":`^${i.myorgEntity}`,"@murumets-ee/logging":`^${i.myorgLogging}`,"@murumets-ee/auth":`^${i.myorgAuth}`,"@murumets-ee/auth-ui":`^${i.myorgAuthUi}`,"@murumets-ee/admin-ui":`^${i.myorgAdminUi}`,"@murumets-ee/content":`^${i.myorgContent}`,"@murumets-ee/settings":`^${i.myorgSettings}`,"@murumets-ee/storage":`^${i.myorgStorage}`,"@murumets-ee/media":`^${i.myorgMedia}`,"@murumets-ee/taxonomy":`^${i.myorgTaxonomy}`,"@murumets-ee/queue":`^${i.myorgQueue}`,"@murumets-ee/mail":`^${i.myorgMail}`,"@murumets-ee/ticketing":`^${i.myorgTicketing}`,"@murumets-ee/ticketing-ui":`^${i.myorgTicketingUi}`,"@murumets-ee/tokens":`^${i.myorgTokens}`,"better-auth":`^${i.betterAuth}`,"drizzle-orm":`^${i.drizzleOrm}`,"next-intl":`^${i.nextIntl}`,"next-themes":`^${i.nextThemes}`,"lucide-react":`^${i.lucideReact}`,postgres:`^${i.postgres}`,"react-hook-form":`^${i.reactHookForm}`,"@hookform/resolvers":`^${i.hookformResolvers}`,zod:`^${i.zod}`},devDependencies:{"drizzle-kit":`^${i.drizzleKit}`,tsx:`^${i.tsx}`,"babel-plugin-react-compiler":i.babelReactCompiler},scripts:{"db:generate":"tsx --env-file=.env scripts/generate-schema.ts","db:migrate:generate":"drizzle-kit generate","db:migrate":"tsx --env-file=.env scripts/migrate.ts","db:reset":"tsx --env-file=.env scripts/reset-db.ts"}}),n?.("Adding toolkit files..."),await k(r,t),await A(r,t),await C(r,t),await w(r,t),await T(r,t),await P(r,t),await R(r,t),await z(r,t),t.installDeps&&(n?.("Installing dependencies..."),l("pnpm install",{cwd:r}))}async function U(t,n){let r=v(process.cwd(),t.name);n?.("Creating workspace..."),await E(r,t,n),t.installDeps&&(n?.("Installing dependencies..."),l("pnpm install",{cwd:r}))}export{O as scaffold};
|