@nubase/create 0.1.27 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/index.js +17 -16
  2. package/package.json +3 -3
  3. package/templates/{frontend/e2e → e2e}/fixtures/test-api.ts +20 -10
  4. package/templates/{frontend/e2e → e2e}/global-setup.ts +7 -7
  5. package/templates/nubase/migrations/.gitkeep +0 -0
  6. package/templates/nubase/nubase.config.ts +14 -0
  7. package/templates/root/README.md +13 -10
  8. package/templates/{backend → root}/drizzle.config.ts +1 -1
  9. package/templates/{frontend → root}/index.html +1 -1
  10. package/templates/root/package.json +57 -23
  11. package/templates/{frontend → root}/playwright.config.ts +8 -21
  12. package/templates/root/tsconfig.backend.json +12 -0
  13. package/templates/root/tsconfig.frontend.json +9 -0
  14. package/templates/{backend → root}/tsconfig.json +2 -4
  15. package/templates/root/vite-env.d.ts +1 -0
  16. package/templates/root/vite.config.ts +65 -0
  17. package/templates/{backend/src → src/backend}/api/handler-factory.ts +1 -1
  18. package/templates/{backend/src → src/backend}/api/routes/test-utils.ts +5 -5
  19. package/templates/{backend/src/index.ts → src/backend/app.ts} +10 -31
  20. package/templates/{backend/src → src/backend}/middleware/workspace-middleware.ts +1 -1
  21. package/templates/src/backend/server.ts +18 -0
  22. package/templates/{frontend/src → src/frontend}/config.tsx +3 -4
  23. package/templates/{frontend/src → src/frontend}/dashboards/analytics.ts +1 -1
  24. package/templates/{frontend/src → src/frontend}/resources/ticket.ts +1 -1
  25. package/templates/{frontend/src → src/frontend}/resources/user.ts +1 -1
  26. package/templates/backend/package.json +0 -48
  27. package/templates/frontend/.env.development.template +0 -1
  28. package/templates/frontend/.env.test.template +0 -1
  29. package/templates/frontend/package.json +0 -38
  30. package/templates/frontend/postcss.config.js +0 -5
  31. package/templates/frontend/src/vite-env.d.ts +0 -9
  32. package/templates/frontend/tsconfig.json +0 -17
  33. package/templates/frontend/vite.config.ts +0 -14
  34. package/templates/root/turbo.json +0 -25
  35. package/templates/schema/package.json +0 -28
  36. package/templates/schema/tsconfig.json +0 -14
  37. /package/templates/{backend/db → db}/schema.sql +0 -0
  38. /package/templates/{backend/docker → docker}/dev/docker-compose.yml +0 -0
  39. /package/templates/{backend/docker → docker}/dev/postgresql-init/dump.sql +0 -0
  40. /package/templates/{backend/docker → docker}/test/docker-compose.yml +0 -0
  41. /package/templates/{backend/docker → docker}/test/postgresql-init/dump.sql +0 -0
  42. /package/templates/{frontend/e2e → e2e}/auth.spec.ts +0 -0
  43. /package/templates/{frontend/e2e → e2e}/fixtures/base.ts +0 -0
  44. /package/templates/{frontend/e2e → e2e}/ticket.spec.ts +0 -0
  45. /package/templates/{frontend/e2e → e2e}/utils/test-reporter.ts +0 -0
  46. /package/templates/{backend → root}/.env.development.template +0 -0
  47. /package/templates/{backend → root}/.env.test.template +0 -0
  48. /package/templates/{backend → root}/vitest.config.ts +0 -0
  49. /package/templates/{backend/src → src/backend}/api/routes/auth.ts +0 -0
  50. /package/templates/{backend/src → src/backend}/api/routes/dashboard.ts +0 -0
  51. /package/templates/{backend/src → src/backend}/api/routes/index.ts +0 -0
  52. /package/templates/{backend/src → src/backend}/api/routes/ticket.ts +0 -0
  53. /package/templates/{backend/src → src/backend}/api/routes/user.ts +0 -0
  54. /package/templates/{backend/src → src/backend}/auth/index.ts +0 -0
  55. /package/templates/{backend/src → src/backend}/db/helpers/drizzle.ts +0 -0
  56. /package/templates/{backend/src → src/backend}/db/schema/index.ts +0 -0
  57. /package/templates/{backend/src → src/backend}/db/schema/ticket.ts +0 -0
  58. /package/templates/{backend/src → src/backend}/db/schema/user-workspace.ts +0 -0
  59. /package/templates/{backend/src → src/backend}/db/schema/user.ts +0 -0
  60. /package/templates/{backend/src → src/backend}/db/schema/workspace.ts +0 -0
  61. /package/templates/{backend/src → src/backend}/db/seed.ts +0 -0
  62. /package/templates/{backend/src → src/backend}/helpers/env.ts +0 -0
  63. /package/templates/{backend/src → src/backend}/preflight.ts +0 -0
  64. /package/templates/{schema/src → src/common}/api-endpoints.ts +0 -0
  65. /package/templates/{schema/src → src/common}/endpoints/auth/get-me.ts +0 -0
  66. /package/templates/{schema/src → src/common}/endpoints/auth/index.ts +0 -0
  67. /package/templates/{schema/src → src/common}/endpoints/auth/login-complete.ts +0 -0
  68. /package/templates/{schema/src → src/common}/endpoints/auth/login-start.ts +0 -0
  69. /package/templates/{schema/src → src/common}/endpoints/auth/login.ts +0 -0
  70. /package/templates/{schema/src → src/common}/endpoints/auth/logout.ts +0 -0
  71. /package/templates/{schema/src → src/common}/endpoints/auth/signup.ts +0 -0
  72. /package/templates/{schema/src → src/common}/endpoints/dashboard/active-users.ts +0 -0
  73. /package/templates/{schema/src → src/common}/endpoints/dashboard/browser-stats.ts +0 -0
  74. /package/templates/{schema/src → src/common}/endpoints/dashboard/index.ts +0 -0
  75. /package/templates/{schema/src → src/common}/endpoints/dashboard/recent-activity.ts +0 -0
  76. /package/templates/{schema/src → src/common}/endpoints/dashboard/revenue-chart.ts +0 -0
  77. /package/templates/{schema/src → src/common}/endpoints/dashboard/sales-chart.ts +0 -0
  78. /package/templates/{schema/src → src/common}/endpoints/dashboard/total-revenue.ts +0 -0
  79. /package/templates/{schema/src → src/common}/endpoints/index.ts +0 -0
  80. /package/templates/{schema/src → src/common}/endpoints/ticket/delete-ticket.ts +0 -0
  81. /package/templates/{schema/src → src/common}/endpoints/ticket/get-ticket.ts +0 -0
  82. /package/templates/{schema/src → src/common}/endpoints/ticket/get-tickets.ts +0 -0
  83. /package/templates/{schema/src → src/common}/endpoints/ticket/index.ts +0 -0
  84. /package/templates/{schema/src → src/common}/endpoints/ticket/patch-ticket.ts +0 -0
  85. /package/templates/{schema/src → src/common}/endpoints/ticket/post-ticket.ts +0 -0
  86. /package/templates/{schema/src → src/common}/endpoints/user/delete-user.ts +0 -0
  87. /package/templates/{schema/src → src/common}/endpoints/user/get-user.ts +0 -0
  88. /package/templates/{schema/src → src/common}/endpoints/user/get-users.ts +0 -0
  89. /package/templates/{schema/src → src/common}/endpoints/user/index.ts +0 -0
  90. /package/templates/{schema/src → src/common}/endpoints/user/lookup-users.ts +0 -0
  91. /package/templates/{schema/src → src/common}/endpoints/user/patch-user.ts +0 -0
  92. /package/templates/{schema/src → src/common}/endpoints/user/post-user.ts +0 -0
  93. /package/templates/{schema/src → src/common}/index.ts +0 -0
  94. /package/templates/{schema/src → src/common}/resources/index.ts +0 -0
  95. /package/templates/{schema/src → src/common}/resources/ticket.ts +0 -0
  96. /package/templates/{schema/src → src/common}/resources/user.ts +0 -0
  97. /package/templates/{schema/src → src/common}/resources/workspace.ts +0 -0
  98. /package/templates/{frontend/src → src/frontend}/auth/__PROJECT_NAME_PASCAL__AuthController.ts +0 -0
  99. /package/templates/{frontend/src → src/frontend}/main.tsx +0 -0
  100. /package/templates/{frontend/src → src/frontend}/styles/theme.css +0 -0
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ function replaceInContent(content, options) {
27
27
  const pascalName = toPascalCase(options.name);
28
28
  const camelName = toCamelCase(options.name);
29
29
  const nubaseVersion = options.nubaseTag === "latest" ? "*" : options.nubaseTag;
30
- return content.replace(/__PROJECT_NAME__/g, kebabName).replace(/__PROJECT_NAME_PASCAL__/g, pascalName).replace(/__PROJECT_NAME_CAMEL__/g, camelName).replace(/__DB_NAME__/g, options.dbName).replace(/__DB_USER__/g, options.dbUser).replace(/__DB_PASSWORD__/g, options.dbPassword).replace(/__DEV_PORT__/g, String(options.devPort)).replace(/__TEST_PORT__/g, String(options.testPort)).replace(/__BACKEND_PORT__/g, String(options.backendPort)).replace(/__FRONTEND_PORT__/g, String(options.frontendPort)).replace(/__TEST_BACKEND_PORT__/g, String(options.testBackendPort)).replace(/__TEST_FRONTEND_PORT__/g, String(options.testFrontendPort)).replace(/"@nubase\/core": "\*"/g, `"@nubase/core": "${nubaseVersion}"`).replace(/"@nubase\/frontend": "\*"/g, `"@nubase/frontend": "${nubaseVersion}"`).replace(/"@nubase\/backend": "\*"/g, `"@nubase/backend": "${nubaseVersion}"`).replace(/"@nubase\/create": "\*"/g, `"@nubase/create": "${nubaseVersion}"`);
30
+ return content.replace(/__PROJECT_NAME__/g, kebabName).replace(/__PROJECT_NAME_PASCAL__/g, pascalName).replace(/__PROJECT_NAME_CAMEL__/g, camelName).replace(/__DB_NAME__/g, options.dbName).replace(/__DB_USER__/g, options.dbUser).replace(/__DB_PASSWORD__/g, options.dbPassword).replace(/__DEV_PORT__/g, String(options.devPort)).replace(/__TEST_PORT__/g, String(options.testPort)).replace(/__PORT__/g, String(options.port)).replace(/__TEST_PORT_APP__/g, String(options.testPortApp)).replace(/"@nubase\/core": "\*"/g, `"@nubase/core": "${nubaseVersion}"`).replace(/"@nubase\/frontend": "\*"/g, `"@nubase/frontend": "${nubaseVersion}"`).replace(/"@nubase\/backend": "\*"/g, `"@nubase/backend": "${nubaseVersion}"`).replace(/"@nubase\/create": "\*"/g, `"@nubase/create": "${nubaseVersion}"`);
31
31
  }
32
32
  function copyTemplateDir(src, dest, options) {
33
33
  fse.ensureDirSync(dest);
@@ -52,7 +52,7 @@ function copyTemplateDir(src, dest, options) {
52
52
  }
53
53
  }
54
54
  async function main() {
55
- program.name("@nubase/create").description("Create a new Nubase application").argument("[project-name]", "Name of the project").option("--db-name <name>", "Database name").option("--db-user <user>", "Database user").option("--db-password <password>", "Database password").option("--dev-port <port>", "Development database port", "5434").option("--test-port <port>", "Test database port", "5435").option("--backend-port <port>", "Backend server port", "3001").option("--frontend-port <port>", "Frontend dev server port", "3002").option("--test-backend-port <port>", "Test backend server port", "4001").option("--test-frontend-port <port>", "Test frontend dev server port", "4002").option("--skip-install", "Skip npm install").option("--tag <tag>", "npm tag for @nubase/* packages (latest, dev)", "latest").parse();
55
+ program.name("@nubase/create").description("Create a new Nubase application").argument("[project-name]", "Name of the project").option("--db-name <name>", "Database name").option("--db-user <user>", "Database user").option("--db-password <password>", "Database password").option("--dev-port <port>", "Development database port", "5434").option("--test-port <port>", "Test database port", "5435").option("--port <port>", "Application server port", "3000").option("--test-port-app <port>", "Test application server port", "4000").option("--skip-install", "Skip npm install").option("--tag <tag>", "npm tag for @nubase/* packages (latest, dev)", "latest").parse();
56
56
  const args = program.args;
57
57
  const opts = program.opts();
58
58
  console.log(chalk.bold.cyan("\n Welcome to Nubase!\n"));
@@ -81,10 +81,8 @@ async function main() {
81
81
  dbPassword,
82
82
  devPort: Number.parseInt(opts.devPort, 10),
83
83
  testPort: Number.parseInt(opts.testPort, 10),
84
- backendPort: Number.parseInt(opts.backendPort, 10),
85
- frontendPort: Number.parseInt(opts.frontendPort, 10),
86
- testBackendPort: Number.parseInt(opts.testBackendPort, 10),
87
- testFrontendPort: Number.parseInt(opts.testFrontendPort, 10),
84
+ port: Number.parseInt(opts.port, 10),
85
+ testPortApp: Number.parseInt(opts.testPortApp, 10),
88
86
  nubaseTag: opts.tag
89
87
  };
90
88
  const targetDir = path.join(process.cwd(), projectName);
@@ -104,20 +102,23 @@ async function main() {
104
102
  console.log(chalk.blue(`
105
103
  Creating project in ${chalk.bold(targetDir)}...
106
104
  `));
107
- const templates = ["root", "schema", "backend", "frontend"];
105
+ const templates = [
106
+ { name: "root", dest: "" },
107
+ { name: "src", dest: "src" },
108
+ { name: "docker", dest: "docker" },
109
+ { name: "db", dest: "db" },
110
+ { name: "e2e", dest: "e2e" },
111
+ { name: "nubase", dest: "nubase" }
112
+ ];
108
113
  for (const template of templates) {
109
- const templatePath = path.join(TEMPLATE_DIR, template);
114
+ const templatePath = path.join(TEMPLATE_DIR, template.name);
110
115
  if (!fs.existsSync(templatePath)) {
111
- console.log(chalk.yellow(`Template ${template} not found, skipping...`));
116
+ console.log(chalk.yellow(`Template ${template.name} not found, skipping...`));
112
117
  continue;
113
118
  }
114
- if (template === "root") {
115
- copyTemplateDir(templatePath, targetDir, options);
116
- } else {
117
- const destPath = path.join(targetDir, template);
118
- copyTemplateDir(templatePath, destPath, options);
119
- }
120
- console.log(chalk.green(` \u2713 Created ${template}`));
119
+ const destPath = template.dest ? path.join(targetDir, template.dest) : targetDir;
120
+ copyTemplateDir(templatePath, destPath, options);
121
+ console.log(chalk.green(` \u2713 Created ${template.name}`));
121
122
  }
122
123
  if (!opts.skipInstall) {
123
124
  console.log(chalk.blue("\nInstalling dependencies...\n"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nubase/create",
3
- "version": "0.1.27",
3
+ "version": "0.1.31",
4
4
  "description": "Create a new Nubase application",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,9 +21,9 @@
21
21
  "publish:dev": "npm publish --access public --tag dev"
22
22
  },
23
23
  "dependencies": {
24
- "chalk": "^5.3.0",
24
+ "chalk": "^5.6.2",
25
25
  "commander": "^12.1.0",
26
- "fs-extra": "^11.3.3",
26
+ "fs-extra": "^11.3.4",
27
27
  "prompts": "^2.4.2"
28
28
  },
29
29
  "devDependencies": {
@@ -10,8 +10,8 @@ export const TEST_USER = {
10
10
  // Test workspace for path-based multi-workspace
11
11
  export const TEST_WORKSPACE = "tavern";
12
12
 
13
- // Backend API base URL (no subdomain for path-based tenancy)
14
- const API_BASE_URL = "http://localhost:__TEST_BACKEND_PORT__";
13
+ // API base URL - same origin, all API routes are under /api
14
+ const API_BASE_URL = "http://localhost:__TEST_PORT_APP__";
15
15
 
16
16
  export class TestAPI {
17
17
  constructor(private request: APIRequestContext) {}
@@ -45,9 +45,12 @@ export class TestAPI {
45
45
  password: string = TEST_USER.password,
46
46
  workspace: string = TEST_WORKSPACE,
47
47
  ) {
48
- const response = await this.request.post(`${API_BASE_URL}/auth/login`, {
49
- data: { email, password, workspace },
50
- });
48
+ const response = await this.request.post(
49
+ `${API_BASE_URL}/api/auth/login`,
50
+ {
51
+ data: { email, password, workspace },
52
+ },
53
+ );
51
54
 
52
55
  if (!response.ok()) {
53
56
  const body = await response.text();
@@ -76,9 +79,12 @@ export class TestAPI {
76
79
  async seedTestData(data: {
77
80
  tickets?: Array<{ title: string; description?: string }>;
78
81
  }) {
79
- const response = await this.request.post(`${API_BASE_URL}/api/test/seed`, {
80
- data,
81
- });
82
+ const response = await this.request.post(
83
+ `${API_BASE_URL}/api/test/seed`,
84
+ {
85
+ data,
86
+ },
87
+ );
82
88
  if (!response.ok()) {
83
89
  throw new Error(`Failed to seed test data: ${response.status()}`);
84
90
  }
@@ -86,7 +92,9 @@ export class TestAPI {
86
92
  }
87
93
 
88
94
  async getDatabaseStats() {
89
- const response = await this.request.get(`${API_BASE_URL}/api/test/stats`);
95
+ const response = await this.request.get(
96
+ `${API_BASE_URL}/api/test/stats`,
97
+ );
90
98
  if (!response.ok()) {
91
99
  const body = await response.text();
92
100
  throw new Error(
@@ -97,7 +105,9 @@ export class TestAPI {
97
105
  }
98
106
 
99
107
  async getTicket(id: number) {
100
- const response = await this.request.get(`${API_BASE_URL}/tickets/${id}`);
108
+ const response = await this.request.get(
109
+ `${API_BASE_URL}/api/tickets/${id}`,
110
+ );
101
111
  if (!response.ok()) {
102
112
  throw new Error(`Failed to get ticket: ${response.status()}`);
103
113
  }
@@ -1,29 +1,29 @@
1
1
  import type { FullConfig } from "@playwright/test";
2
2
 
3
- // Backend API base URL
4
- const API_BASE_URL = "http://localhost:__TEST_BACKEND_PORT__";
3
+ // API base URL - same origin in unified architecture
4
+ const API_BASE_URL = "http://localhost:__TEST_PORT_APP__";
5
5
 
6
6
  async function globalSetup(_config: FullConfig) {
7
7
  console.log("Running global setup...");
8
8
 
9
- // Wait for backend to be ready
9
+ // Wait for server to be ready
10
10
  const maxRetries = 30;
11
11
  let retries = 0;
12
12
 
13
13
  while (retries < maxRetries) {
14
14
  try {
15
- const response = await fetch(`${API_BASE_URL}/`);
15
+ const response = await fetch(`${API_BASE_URL}/api/`);
16
16
  if (response.ok) {
17
- console.log("Backend is ready");
17
+ console.log("Server is ready");
18
18
  break;
19
19
  }
20
20
  } catch (_error) {
21
- // Backend not ready yet
21
+ // Server not ready yet
22
22
  }
23
23
 
24
24
  retries++;
25
25
  if (retries === maxRetries) {
26
- throw new Error("Backend failed to start within timeout");
26
+ throw new Error("Server failed to start within timeout");
27
27
  }
28
28
 
29
29
  await new Promise((resolve) => setTimeout(resolve, 1000));
File without changes
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from "@nubase/cli";
2
+
3
+ export default defineConfig({
4
+ environments: {
5
+ local: {
6
+ url: "postgres://__DB_USER__:__DB_PASSWORD__@localhost:__DEV_PORT__/__DB_NAME__",
7
+ },
8
+ production: {
9
+ url: process.env.PRODUCTION_DATABASE_URL!,
10
+ },
11
+ },
12
+ defaultEnvironment: "local",
13
+ schemas: ["public"],
14
+ });
@@ -30,15 +30,13 @@ npm run db:up
30
30
  npm run db:seed
31
31
  ```
32
32
 
33
- 4. Start the development servers:
33
+ 4. Start the development server:
34
34
 
35
35
  ```bash
36
36
  npm run dev
37
37
  ```
38
38
 
39
- The application will be available at:
40
- - Frontend: http://localhost:__FRONTEND_PORT__/default
41
- - Backend API: http://localhost:__BACKEND_PORT__
39
+ The application will be available at http://localhost:__PORT__/tavern
42
40
 
43
41
  ### Default Credentials
44
42
 
@@ -49,16 +47,21 @@ The application will be available at:
49
47
 
50
48
  ```
51
49
  __PROJECT_NAME__/
52
- ├── schema/ # Shared API schemas and types
53
- ├── backend/ # Node.js backend (Hono + PostgreSQL)
54
- ├── frontend/ # React frontend (Vite + Nubase)
55
- └── package.json # Root workspace configuration
50
+ ├── src/
51
+ ├── backend/ # Hono API server
52
+ ├── frontend/ # React frontend (Vite + Nubase)
53
+ └── common/ # Shared API schemas and types
54
+ ├── docker/ # Docker Compose configs
55
+ ├── e2e/ # Playwright E2E tests
56
+ ├── vite.config.ts # Unified Vite config (dev + build)
57
+ └── package.json # Project configuration
56
58
  ```
57
59
 
58
60
  ## Available Scripts
59
61
 
60
- - `npm run dev` - Start both frontend and backend in development mode
61
- - `npm run build` - Build all packages
62
+ - `npm run dev` - Start development server (frontend + backend on single port)
63
+ - `npm run build` - Build for production (client + server)
64
+ - `npm run start` - Start production server
62
65
  - `npm run db:up` - Start PostgreSQL database
63
66
  - `npm run db:down` - Stop PostgreSQL database
64
67
  - `npm run db:seed` - Seed database with sample data
@@ -2,7 +2,7 @@ import { defineConfig } from "drizzle-kit";
2
2
 
3
3
  export default defineConfig({
4
4
  out: "./drizzle",
5
- schema: "./src/db/schema",
5
+ schema: "./src/backend/db/schema",
6
6
  dialect: "postgresql",
7
7
  dbCredentials: {
8
8
  url: process.env.DATABASE_URL_ADMIN!,
@@ -8,6 +8,6 @@
8
8
  </head>
9
9
  <body>
10
10
  <div id="root"></div>
11
- <script type="module" src="/src/main.tsx"></script>
11
+ <script type="module" src="/src/frontend/main.tsx"></script>
12
12
  </body>
13
13
  </html>
@@ -3,33 +3,67 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
- "workspaces": [
7
- "schema",
8
- "backend",
9
- "frontend"
10
- ],
11
6
  "scripts": {
12
- "dev": "turbo run dev",
13
- "dev:e2e": "turbo run dev dev:e2e",
14
- "build": "turbo run build",
15
- "db:up": "./scripts/check-docker.sh npm run -w backend db:dev:up",
16
- "db:down": "./scripts/check-docker.sh npm run -w backend db:dev:down",
17
- "db:seed": "npm run -w backend db:dev:seed",
18
- "db:reset": "./scripts/check-docker.sh npm run -w backend db:dev:reset",
19
- "db:test:up": "./scripts/check-docker.sh npm run -w backend db:test:up",
20
- "db:test:reset": "./scripts/check-docker.sh npm run -w backend db:test:reset",
21
- "typecheck": "turbo run typecheck",
22
- "lint": "turbo run lint",
23
- "lint:fix": "turbo run lint:fix",
24
- "e2e": "turbo run e2e",
25
- "e2e:ui": "cd frontend && npm run e2e:ui",
26
- "e2e:headed": "cd frontend && npm run e2e:headed",
27
- "e2e:install": "cd frontend && npm run e2e:install"
7
+ "dev": "vite",
8
+ "build": "vite build --mode client && vite build --mode server",
9
+ "start": "node dist/server/index.js",
10
+ "typecheck": "tsc --noEmit -p tsconfig.backend.json && tsc --noEmit -p tsconfig.frontend.json",
11
+ "lint": "biome check .",
12
+ "lint:fix": "biome check . --write --unsafe",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "db:up": "./scripts/check-docker.sh docker compose -f docker/dev/docker-compose.yml up -d",
16
+ "db:down": "docker compose -f docker/dev/docker-compose.yml down",
17
+ "db:kill": "docker compose -f docker/dev/docker-compose.yml down -v && rm -rf docker/dev/postgresql-data",
18
+ "db:seed": "NODE_ENV=development tsx src/backend/db/seed.ts",
19
+ "db:reset": "npm run db:kill && npm run db:schema-sync && npm run db:up && sleep 5 && npm run db:seed",
20
+ "db:schema-sync": "cp db/schema.sql docker/dev/postgresql-init/dump.sql && cp db/schema.sql docker/test/postgresql-init/dump.sql",
21
+ "db:test:up": "./scripts/check-docker.sh docker compose -f docker/test/docker-compose.yml up -d",
22
+ "db:test:down": "docker compose -f docker/test/docker-compose.yml down",
23
+ "db:test:kill": "docker compose -f docker/test/docker-compose.yml down -v && rm -rf docker/test/postgresql-data",
24
+ "db:test:reset": "npm run db:test:kill && npm run db:schema-sync && npm run db:test:up",
25
+ "dev:test": "NODE_ENV=test vite --mode test --port __TEST_PORT_APP__",
26
+ "e2e": "playwright test",
27
+ "e2e:ui": "playwright test --ui",
28
+ "e2e:headed": "playwright test --headed",
29
+ "e2e:install": "playwright install"
30
+ },
31
+ "dependencies": {
32
+ "@hono/node-server": "^1.19.9",
33
+ "@nubase/backend": "*",
34
+ "@nubase/core": "*",
35
+ "@nubase/frontend": "*",
36
+ "@tailwindcss/vite": "^4.1.18",
37
+ "@tanstack/react-router": "^1.150.0",
38
+ "bcrypt": "^6.0.0",
39
+ "dotenv": "^17.2.3",
40
+ "drizzle-orm": "^0.45.1",
41
+ "hono": "^4.11.4",
42
+ "jsonwebtoken": "^9.0.3",
43
+ "lucide-react": "^0.539.0",
44
+ "pg": "^8.17.1",
45
+ "react": "^19.2.3",
46
+ "react-dom": "^19.2.3",
47
+ "tailwindcss": "^4.1.18"
28
48
  },
29
49
  "devDependencies": {
30
50
  "@biomejs/biome": "^2.3.11",
31
- "turbo": "^2.7.5",
32
- "typescript": "^5.9.3"
51
+ "@faker-js/faker": "^9.9.0",
52
+ "@hono/vite-build": "^1.5.0",
53
+ "@hono/vite-dev-server": "^0.19.0",
54
+ "@playwright/test": "^1.49.0",
55
+ "@types/bcrypt": "^6.0.0",
56
+ "@types/jsonwebtoken": "^9.0.10",
57
+ "@types/node": "^22.19.7",
58
+ "@types/pg": "^8.16.0",
59
+ "@types/react": "^19.2.8",
60
+ "@types/react-dom": "^19.2.3",
61
+ "@vitejs/plugin-react": "^5.1.2",
62
+ "drizzle-kit": "^0.31.8",
63
+ "tsx": "^4.21.0",
64
+ "typescript": "^5.9.3",
65
+ "vite": "^7.3.1",
66
+ "vitest": "^4.0.17"
33
67
  },
34
68
  "engines": {
35
69
  "node": ">=18",
@@ -20,7 +20,7 @@ export default defineConfig({
20
20
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
21
21
  use: {
22
22
  /* Base URL to use in actions like `await page.goto('/')`. */
23
- baseURL: "http://localhost:__TEST_FRONTEND_PORT__",
23
+ baseURL: "http://localhost:__TEST_PORT_APP__",
24
24
  /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
25
25
  trace: "on-first-retry",
26
26
  /* Screenshot on failure */
@@ -37,24 +37,11 @@ export default defineConfig({
37
37
  },
38
38
  ],
39
39
 
40
- /* Run your local dev server before starting the tests */
41
- webServer: [
42
- {
43
- command: "npm run dev:test",
44
- url: "http://localhost:__TEST_FRONTEND_PORT__/tavern",
45
- reuseExistingServer: true,
46
- timeout: 120 * 1000,
47
- },
48
- {
49
- command: "cd ../backend && npm run dev:test",
50
- url: "http://localhost:__TEST_BACKEND_PORT__",
51
- reuseExistingServer: true,
52
- timeout: 120 * 1000,
53
- env: {
54
- NODE_ENV: "test",
55
- DATABASE_URL:
56
- "postgresql://__DB_NAME__:__DB_PASSWORD__@localhost:__TEST_PORT__/__DB_NAME__",
57
- },
58
- },
59
- ],
40
+ /* Run the unified dev server before starting the tests */
41
+ webServer: {
42
+ command: "npm run dev:test",
43
+ url: "http://localhost:__TEST_PORT_APP__/tavern",
44
+ reuseExistingServer: true,
45
+ timeout: 120 * 1000,
46
+ },
60
47
  });
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "types": ["node"],
5
+ "jsx": "react-jsx",
6
+ "jsxImportSource": "hono/jsx",
7
+ "rootDir": "./src",
8
+ "declaration": true,
9
+ "outDir": "./dist/server"
10
+ },
11
+ "include": ["src/backend/**/*", "src/common/**/*"]
12
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "jsx": "react-jsx",
6
+ "noEmit": true
7
+ },
8
+ "include": ["src/frontend/**/*", "src/common/**/*", "vite-env.d.ts"]
9
+ }
@@ -6,10 +6,8 @@
6
6
  "esModuleInterop": true,
7
7
  "strict": true,
8
8
  "skipLibCheck": true,
9
- "declaration": true,
10
- "outDir": "./dist",
11
- "rootDir": "./src"
9
+ "resolveJsonModule": true,
10
+ "isolatedModules": true
12
11
  },
13
- "include": ["src/**/*"],
14
12
  "exclude": ["node_modules", "dist"]
15
13
  }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,65 @@
1
+ import devServer, { defaultOptions } from "@hono/vite-dev-server";
2
+ import build from "@hono/vite-build/node";
3
+ import tailwindcss from "@tailwindcss/vite";
4
+ import react from "@vitejs/plugin-react";
5
+ import { defineConfig } from "vite";
6
+
7
+ export default defineConfig(({ mode }) => {
8
+ if (mode === "client") {
9
+ return {
10
+ plugins: [react(), tailwindcss()],
11
+ build: {
12
+ outDir: "dist/client",
13
+ emptyOutDir: true,
14
+ },
15
+ };
16
+ }
17
+
18
+ if (mode === "server") {
19
+ return {
20
+ plugins: [
21
+ build({
22
+ entry: "src/backend/server.ts",
23
+ output: "index.js",
24
+ }),
25
+ ],
26
+ build: {
27
+ outDir: "dist/server",
28
+ emptyOutDir: true,
29
+ },
30
+ };
31
+ }
32
+
33
+ // Development mode
34
+ return {
35
+ plugins: [
36
+ react(),
37
+ tailwindcss(),
38
+ devServer({
39
+ entry: "src/backend/app.ts",
40
+ exclude: [
41
+ // Only send /api/* requests to Hono; everything else goes to Vite
42
+ /^(?!\/api\/).+/,
43
+ ...defaultOptions.exclude,
44
+ ],
45
+ }),
46
+ ],
47
+ ssr: {
48
+ external: [
49
+ "@nubase/core",
50
+ "@nubase/backend",
51
+ "@nubase/frontend",
52
+ "pg",
53
+ "drizzle-orm",
54
+ "bcrypt",
55
+ "jsonwebtoken",
56
+ "dotenv",
57
+ "@hono/node-server",
58
+ "@faker-js/faker",
59
+ ],
60
+ },
61
+ server: {
62
+ port: __PORT__,
63
+ },
64
+ };
65
+ });
@@ -1,5 +1,5 @@
1
1
  import { createHandlerFactory } from "@nubase/backend";
2
- import { apiEndpoints, type ApiEndpoints } from "schema";
2
+ import { apiEndpoints, type ApiEndpoints } from "../../common";
3
3
  import type { __PROJECT_NAME_PASCAL__User } from "../auth";
4
4
 
5
5
  /**
@@ -32,7 +32,7 @@ async function getWorkspaceBySlug(slug: string) {
32
32
  export const handleClearDatabase = createHttpHandler({
33
33
  endpoint: {
34
34
  method: "POST" as const,
35
- path: "/api/test/clear-database",
35
+ path: "/test/clear-database",
36
36
  requestParams: emptySchema,
37
37
  requestBody: nu.object({
38
38
  workspace: nu.string().optional(),
@@ -97,7 +97,7 @@ export const handleClearDatabase = createHttpHandler({
97
97
  export const handleSeedTestData = createHttpHandler({
98
98
  endpoint: {
99
99
  method: "POST" as const,
100
- path: "/api/test/seed",
100
+ path: "/test/seed",
101
101
  requestParams: emptySchema,
102
102
  requestBody: nu.object({
103
103
  workspace: nu.string().optional(),
@@ -162,7 +162,7 @@ export const handleSeedTestData = createHttpHandler({
162
162
  export const handleGetDatabaseStats = createHttpHandler({
163
163
  endpoint: {
164
164
  method: "GET" as const,
165
- path: "/api/test/stats",
165
+ path: "/test/stats",
166
166
  requestParams: nu.object({
167
167
  workspace: nu.string().optional(),
168
168
  }),
@@ -199,7 +199,7 @@ export const handleGetDatabaseStats = createHttpHandler({
199
199
  export const handleEnsureWorkspace = createHttpHandler({
200
200
  endpoint: {
201
201
  method: "POST" as const,
202
- path: "/api/test/ensure-workspace",
202
+ path: "/test/ensure-workspace",
203
203
  requestParams: emptySchema,
204
204
  requestBody: nu.object({
205
205
  workspace: nu.string().optional(),
@@ -271,7 +271,7 @@ export const handleEnsureWorkspace = createHttpHandler({
271
271
  export const handleSeedMultiWorkspaceUser = createHttpHandler({
272
272
  endpoint: {
273
273
  method: "POST" as const,
274
- path: "/api/test/seed-multi-workspace-user",
274
+ path: "/test/seed-multi-workspace-user",
275
275
  requestParams: emptySchema,
276
276
  requestBody: nu.object({
277
277
  email: nu.string(),
@@ -1,7 +1,5 @@
1
- import { serve } from "@hono/node-server";
2
1
  import { createAuthMiddleware, registerHandlers } from "@nubase/backend";
3
2
  import { Hono } from "hono";
4
- import { cors } from "hono/cors";
5
3
  import { authHandlers } from "./api/routes/auth";
6
4
  import { dashboardHandlers } from "./api/routes/dashboard";
7
5
  import { testUtilsHandlers } from "./api/routes/test-utils";
@@ -21,21 +19,6 @@ const app = new Hono();
21
19
  // Auth controller
22
20
  const authController = new __PROJECT_NAME_PASCAL__AuthController();
23
21
 
24
- // CORS configuration
25
- app.use(
26
- "*",
27
- cors({
28
- origin: (origin) => {
29
- // Allow localhost origins
30
- if (origin?.match(/^http:\/\/localhost(:\d+)?$/)) {
31
- return origin;
32
- }
33
- return null;
34
- },
35
- credentials: true,
36
- }),
37
- );
38
-
39
22
  // Workspace middleware - handles login path (gets workspace from body)
40
23
  app.use("*", createWorkspaceMiddleware());
41
24
 
@@ -45,24 +28,20 @@ app.use("*", createAuthMiddleware({ controller: authController }));
45
28
  // Post-auth workspace middleware - sets context from authenticated user's workspace
46
29
  app.use("*", createPostAuthWorkspaceMiddleware());
47
30
 
48
- // Root route
49
- app.get("/", (c) => c.json({ message: "Welcome to __PROJECT_NAME_PASCAL__ API" }));
31
+ // API routes - all handlers are mounted under /api
32
+ const api = new Hono();
33
+
34
+ api.get("/", (c) => c.json({ message: "Welcome to __PROJECT_NAME_PASCAL__ API" }));
50
35
 
51
- // Register all handlers - path and method extracted from endpoint metadata
52
- registerHandlers(app, authHandlers);
53
- registerHandlers(app, ticketHandlers);
54
- registerHandlers(app, dashboardHandlers);
36
+ registerHandlers(api, authHandlers);
37
+ registerHandlers(api, ticketHandlers);
38
+ registerHandlers(api, dashboardHandlers);
55
39
 
56
40
  // Register test utility handlers (only in test environment)
57
41
  if (process.env.NODE_ENV === "test") {
58
- registerHandlers(app, testUtilsHandlers);
42
+ registerHandlers(api, testUtilsHandlers);
59
43
  }
60
44
 
61
- const port = Number(process.env.PORT) || __BACKEND_PORT__;
62
-
63
- console.log(`Server is running on http://localhost:${port}`);
45
+ app.route("/api", api);
64
46
 
65
- serve({
66
- fetch: app.fetch,
67
- port,
68
- });
47
+ export default app;
@@ -13,7 +13,7 @@ export interface Workspace {
13
13
  const WORKSPACE_BYPASS_PATHS = ["/"];
14
14
 
15
15
  // Paths where workspace comes from request body (login) instead of JWT
16
- const WORKSPACE_FROM_BODY_PATHS = ["/auth/login"];
16
+ const WORKSPACE_FROM_BODY_PATHS = ["/api/auth/login"];
17
17
 
18
18
  /**
19
19
  * Workspace middleware for path-based multi-workspace.
@@ -0,0 +1,18 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { serve } from "@hono/node-server";
3
+ import { serveStatic } from "@hono/node-server/serve-static";
4
+ import app from "./app";
5
+
6
+ // Serve built frontend assets
7
+ app.use("/assets/*", serveStatic({ root: "./dist/client" }));
8
+ app.use("/favicon.ico", serveStatic({ root: "./dist/client" }));
9
+
10
+ // SPA fallback - serve index.html for all non-API routes
11
+ const indexHtml = await readFile("./dist/client/index.html", "utf-8");
12
+ app.get("*", (c) => c.html(indexHtml));
13
+
14
+ const port = Number(process.env.PORT) || __PORT__;
15
+
16
+ serve({ fetch: app.fetch, port }, (info) => {
17
+ console.log(`Server running on http://localhost:${info.port}`);
18
+ });
@@ -1,14 +1,13 @@
1
1
  import type { NubaseFrontendConfig } from "@nubase/frontend";
2
2
  import { defaultKeybindings, resourceLink } from "@nubase/frontend";
3
3
  import { Home, TicketIcon, UsersIcon } from "lucide-react";
4
- import { apiEndpoints } from "schema";
4
+ import { apiEndpoints } from "../common";
5
5
  import { __PROJECT_NAME_PASCAL__AuthController } from "./auth/__PROJECT_NAME_PASCAL__AuthController";
6
6
  import { analyticsDashboard } from "./dashboards/analytics";
7
7
  import { ticketResource } from "./resources/ticket";
8
8
  import { userResource } from "./resources/user";
9
9
 
10
- const apiBaseUrl =
11
- import.meta.env.VITE_API_BASE_URL || "http://localhost:__BACKEND_PORT__";
10
+ const apiBaseUrl = "/api";
12
11
 
13
12
  // Preserve auth controller across HMR to prevent losing authentication state during development
14
13
  const authController: __PROJECT_NAME_PASCAL__AuthController = (import.meta.hot
@@ -47,7 +46,7 @@ export const config: NubaseFrontendConfig<typeof apiEndpoints> = {
47
46
  [userResource.id]: userResource,
48
47
  },
49
48
  keybindings: defaultKeybindings.extend(),
50
- apiBaseUrl: apiBaseUrl,
49
+ apiBaseUrl,
51
50
  apiEndpoints,
52
51
  themeIds: ["dark", "light"],
53
52
  defaultThemeId: "dark",
@@ -1,5 +1,5 @@
1
1
  import { createDashboard } from "@nubase/frontend";
2
- import { apiEndpoints } from "schema";
2
+ import { apiEndpoints } from "../../common";
3
3
 
4
4
  /**
5
5
  * Analytics dashboard configuration.
@@ -1,6 +1,6 @@
1
1
  import { createResource, showToast } from "@nubase/frontend";
2
2
  import { TrashIcon } from "lucide-react";
3
- import { apiEndpoints } from "schema";
3
+ import { apiEndpoints } from "../../common";
4
4
 
5
5
  export const ticketResource = createResource("ticket")
6
6
  .withApiEndpoints(apiEndpoints)
@@ -1,6 +1,6 @@
1
1
  import { createResource, showToast } from "@nubase/frontend";
2
2
  import { TrashIcon } from "lucide-react";
3
- import { apiEndpoints } from "schema";
3
+ import { apiEndpoints } from "../../common";
4
4
 
5
5
  export const userResource = createResource("user")
6
6
  .withApiEndpoints(apiEndpoints)
@@ -1,48 +0,0 @@
1
- {
2
- "name": "backend",
3
- "version": "0.1.0",
4
- "type": "module",
5
- "scripts": {
6
- "dev": "NODE_ENV=development tsx src/preflight.ts && NODE_ENV=development tsx watch src/index.ts",
7
- "dev:test": "PORT=__TEST_BACKEND_PORT__ DB_PORT=__TEST_PORT__ NODE_ENV=test tsx watch src/index.ts",
8
- "build": "tsc",
9
- "start": "node dist/index.js",
10
- "db:dev:up": "docker compose -f docker/dev/docker-compose.yml up -d",
11
- "db:dev:down": "docker compose -f docker/dev/docker-compose.yml down",
12
- "db:dev:kill": "docker compose -f docker/dev/docker-compose.yml down -v && rm -rf docker/dev/postgresql-data",
13
- "db:dev:seed": "NODE_ENV=development tsx src/db/seed.ts",
14
- "db:dev:reset": "npm run db:dev:kill && npm run db:schema-sync && npm run db:dev:up && sleep 5 && npm run db:dev:seed",
15
- "db:test:up": "docker compose -f docker/test/docker-compose.yml up -d",
16
- "db:test:down": "docker compose -f docker/test/docker-compose.yml down",
17
- "db:test:kill": "docker compose -f docker/test/docker-compose.yml down -v && rm -rf docker/test/postgresql-data",
18
- "db:test:reset": "npm run db:test:kill && npm run db:schema-sync && npm run db:test:up",
19
- "db:schema-sync": "cp db/schema.sql docker/dev/postgresql-init/dump.sql && cp db/schema.sql docker/test/postgresql-init/dump.sql",
20
- "typecheck": "tsc --noEmit",
21
- "lint": "biome check .",
22
- "lint:fix": "biome check . --write --unsafe",
23
- "test": "vitest run",
24
- "test:watch": "vitest"
25
- },
26
- "dependencies": {
27
- "@hono/node-server": "^1.19.9",
28
- "@nubase/backend": "*",
29
- "bcrypt": "^6.0.0",
30
- "dotenv": "^17.2.3",
31
- "drizzle-orm": "^0.45.1",
32
- "hono": "^4.11.4",
33
- "jsonwebtoken": "^9.0.3",
34
- "pg": "^8.17.1",
35
- "schema": "*"
36
- },
37
- "devDependencies": {
38
- "@faker-js/faker": "^9.9.0",
39
- "@types/bcrypt": "^6.0.0",
40
- "@types/jsonwebtoken": "^9.0.10",
41
- "@types/node": "^22.19.7",
42
- "@types/pg": "^8.16.0",
43
- "drizzle-kit": "^0.31.8",
44
- "tsx": "^4.21.0",
45
- "typescript": "^5.9.3",
46
- "vitest": "^4.0.17"
47
- }
48
- }
@@ -1 +0,0 @@
1
- VITE_API_BASE_URL=http://localhost:__BACKEND_PORT__
@@ -1 +0,0 @@
1
- VITE_API_BASE_URL=http://localhost:__TEST_BACKEND_PORT__
@@ -1,38 +0,0 @@
1
- {
2
- "name": "frontend",
3
- "private": true,
4
- "version": "0.1.0",
5
- "type": "module",
6
- "scripts": {
7
- "dev": "vite",
8
- "dev:test": "vite --mode test --port __TEST_FRONTEND_PORT__",
9
- "dev:e2e": "playwright test --ui",
10
- "build": "tsc -b && vite build",
11
- "preview": "vite preview",
12
- "typecheck": "tsc --noEmit",
13
- "lint": "biome check .",
14
- "lint:fix": "biome check . --write --unsafe",
15
- "e2e": "playwright test",
16
- "e2e:ui": "playwright test --ui",
17
- "e2e:headed": "playwright test --headed",
18
- "e2e:install": "playwright install"
19
- },
20
- "dependencies": {
21
- "@nubase/frontend": "*",
22
- "@tailwindcss/vite": "^4.1.18",
23
- "@tanstack/react-router": "^1.150.0",
24
- "lucide-react": "^0.539.0",
25
- "react": "^19.2.3",
26
- "react-dom": "^19.2.3",
27
- "tailwindcss": "^4.1.18",
28
- "schema": "*"
29
- },
30
- "devDependencies": {
31
- "@playwright/test": "^1.49.0",
32
- "@types/react": "^19.2.8",
33
- "@types/react-dom": "^19.2.3",
34
- "@vitejs/plugin-react": "^5.1.2",
35
- "typescript": "^5.9.3",
36
- "vite": "^7.3.1"
37
- }
38
- }
@@ -1,5 +0,0 @@
1
- export default {
2
- plugins: {
3
- "@tailwindcss/postcss": {},
4
- },
5
- };
@@ -1,9 +0,0 @@
1
- /// <reference types="vite/client" />
2
-
3
- interface ImportMetaEnv {
4
- readonly VITE_API_BASE_URL: string;
5
- }
6
-
7
- interface ImportMeta {
8
- readonly env: ImportMetaEnv;
9
- }
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "esModuleInterop": true,
8
- "strict": true,
9
- "skipLibCheck": true,
10
- "noEmit": true,
11
- "jsx": "react-jsx",
12
- "resolveJsonModule": true,
13
- "isolatedModules": true
14
- },
15
- "include": ["src/**/*"],
16
- "exclude": ["node_modules"]
17
- }
@@ -1,14 +0,0 @@
1
- import tailwindcss from "@tailwindcss/vite";
2
- import react from "@vitejs/plugin-react";
3
- import { defineConfig } from "vite";
4
-
5
- export default defineConfig({
6
- plugins: [react(), tailwindcss()],
7
- build: {
8
- outDir: "dist",
9
- },
10
- server: {
11
- port: __FRONTEND_PORT__,
12
- open: "http://localhost:__FRONTEND_PORT__/tavern",
13
- },
14
- });
@@ -1,25 +0,0 @@
1
- {
2
- "$schema": "https://turbo.build/schema.json",
3
- "tasks": {
4
- "build": {
5
- "dependsOn": ["^build"],
6
- "outputs": ["dist/**"]
7
- },
8
- "dev": {
9
- "cache": false,
10
- "persistent": true
11
- },
12
- "dev:e2e": {
13
- "cache": false,
14
- "persistent": true
15
- },
16
- "typecheck": {
17
- "dependsOn": ["^build"]
18
- },
19
- "lint": {},
20
- "lint:fix": {},
21
- "e2e": {
22
- "cache": false
23
- }
24
- }
25
- }
@@ -1,28 +0,0 @@
1
- {
2
- "name": "schema",
3
- "version": "0.1.0",
4
- "description": "Schema for __PROJECT_NAME_PASCAL__",
5
- "type": "module",
6
- "files": [
7
- "src"
8
- ],
9
- "exports": {
10
- ".": {
11
- "types": "./src/index.ts",
12
- "import": "./src/index.ts",
13
- "require": "./src/index.ts"
14
- }
15
- },
16
- "license": "MIT",
17
- "scripts": {
18
- "typecheck": "tsc --noEmit",
19
- "lint": "biome check .",
20
- "lint:fix": "biome check . --write --unsafe"
21
- },
22
- "dependencies": {
23
- "@nubase/core": "*"
24
- },
25
- "devDependencies": {
26
- "typescript": "^5.9.3"
27
- }
28
- }
@@ -1,14 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "esModuleInterop": true,
7
- "strict": true,
8
- "skipLibCheck": true,
9
- "declaration": true,
10
- "noEmit": true
11
- },
12
- "include": ["src/**/*"],
13
- "exclude": ["node_modules"]
14
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes