@rebasepro/cli 0.7.0 → 0.9.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/dist/index.es.js +80 -3
- package/dist/index.es.js.map +1 -1
- package/dist/utils/project.d.ts +15 -0
- package/package.json +13 -19
- package/templates/template/.env.example +4 -0
- package/templates/template/backend/Dockerfile +4 -3
- package/templates/template/backend/functions/hello.ts +36 -32
- package/templates/template/backend/package.json +3 -1
- package/templates/template/backend/src/env.ts +2 -1
- package/templates/template/backend/src/index.ts +12 -12
- package/templates/template/config/collections/authors.ts +2 -2
- package/templates/template/config/collections/posts.ts +5 -3
- package/templates/template/config/collections/presets/ecommerce/categories.ts +5 -3
- package/templates/template/config/collections/presets/ecommerce/orders.ts +5 -3
- package/templates/template/config/collections/presets/ecommerce/products.ts +5 -3
- package/templates/template/config/collections/tags.ts +2 -2
- package/templates/template/config/collections/users.ts +5 -3
- package/templates/template/frontend/Dockerfile +5 -3
- package/templates/template/frontend/src/App.tsx +4 -1
- package/templates/template/frontend/vite.config.ts +14 -0
- package/templates/template/package.json +3 -1
- package/templates/template/pnpm-workspace.yaml +2 -0
- package/templates/template/scripts/example.ts +1 -1
package/dist/utils/project.d.ts
CHANGED
|
@@ -35,6 +35,21 @@ export declare function resolveLocalBin(projectRoot: string, binName: string): s
|
|
|
35
35
|
* Resolve the tsx binary. Checks backend node_modules first, then root.
|
|
36
36
|
*/
|
|
37
37
|
export declare function resolveTsx(projectRoot: string): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Validate that a resolved tsx binary actually has an intact installation.
|
|
40
|
+
*
|
|
41
|
+
* `resolveLocalBin` only checks whether `node_modules/.bin/tsx` (a symlink)
|
|
42
|
+
* exists. If the pnpm content-addressable store was cleaned or a previous
|
|
43
|
+
* install was interrupted, the symlink can exist while critical files inside
|
|
44
|
+
* the tsx package (e.g. `dist/preflight.cjs`) are missing — causing a
|
|
45
|
+
* confusing MODULE_NOT_FOUND error at runtime.
|
|
46
|
+
*
|
|
47
|
+
* This function follows the symlink, walks up to find the tsx package root
|
|
48
|
+
* (`package.json` with `name: "tsx"`), and verifies that `dist/preflight.cjs`
|
|
49
|
+
* is present. Returns `null` when the installation looks healthy, or an
|
|
50
|
+
* error description string when it appears corrupted.
|
|
51
|
+
*/
|
|
52
|
+
export declare function validateTsxInstallation(tsxBinPath: string): string | null;
|
|
38
53
|
/**
|
|
39
54
|
* Require the project root or exit with a helpful error.
|
|
40
55
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Developer tools for Rebase projects",
|
|
5
5
|
"main": "./dist/index.es.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
@@ -13,12 +13,6 @@
|
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
|
-
"scripts": {
|
|
17
|
-
"test": "vitest run",
|
|
18
|
-
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
19
|
-
"build": "vite build && tsc --emitDeclarationOnly -p tsconfig.json",
|
|
20
|
-
"clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
|
|
21
|
-
},
|
|
22
16
|
"keywords": [
|
|
23
17
|
"cli",
|
|
24
18
|
"create-rebase-app",
|
|
@@ -31,17 +25,17 @@
|
|
|
31
25
|
"author": "rebase.pro",
|
|
32
26
|
"license": "MIT",
|
|
33
27
|
"dependencies": {
|
|
34
|
-
"@rebasepro/agent-skills": "workspace:*",
|
|
35
|
-
"@rebasepro/sdk-generator": "workspace:*",
|
|
36
|
-
"@rebasepro/server-core": "workspace:*",
|
|
37
|
-
"@rebasepro/server-postgresql": "workspace:*",
|
|
38
|
-
"@rebasepro/types": "workspace:*",
|
|
39
28
|
"arg": "^5.0.2",
|
|
40
29
|
"chalk": "^5.6.2",
|
|
41
30
|
"dotenv": "^17.4.2",
|
|
42
31
|
"execa": "^9.6.1",
|
|
43
32
|
"inquirer": "14.0.2",
|
|
44
|
-
"jiti": "^2.7.0"
|
|
33
|
+
"jiti": "^2.7.0",
|
|
34
|
+
"@rebasepro/agent-skills": "0.9.0",
|
|
35
|
+
"@rebasepro/sdk-generator": "0.9.0",
|
|
36
|
+
"@rebasepro/server-core": "0.9.0",
|
|
37
|
+
"@rebasepro/types": "0.9.0",
|
|
38
|
+
"@rebasepro/server-postgresql": "0.9.0"
|
|
45
39
|
},
|
|
46
40
|
"devDependencies": {
|
|
47
41
|
"@types/node": "^25.9.3",
|
|
@@ -67,10 +61,10 @@
|
|
|
67
61
|
"url": "https://github.com/rebasepro/rebase.git",
|
|
68
62
|
"directory": "packages/cli"
|
|
69
63
|
},
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
"scripts": {
|
|
65
|
+
"test": "vitest run",
|
|
66
|
+
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
67
|
+
"build": "vite build && tsc --emitDeclarationOnly -p tsconfig.json",
|
|
68
|
+
"clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
|
|
75
69
|
}
|
|
76
|
-
}
|
|
70
|
+
}
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
# The backend will automatically detect the database type.
|
|
10
10
|
DATABASE_URL=postgresql://rebase:changeme@localhost:5432/rebase?options=-c%20search_path=public
|
|
11
11
|
# DATABASE_URL=mongodb://localhost:27017/rebase
|
|
12
|
+
#
|
|
13
|
+
# Local Postgres without SSL? If you see "SSL is not enabled on the server",
|
|
14
|
+
# append &sslmode=disable to the connection string, e.g.:
|
|
15
|
+
# DATABASE_URL=postgresql://rebase:changeme@localhost:5432/rebase?options=-c%20search_path=public&sslmode=disable
|
|
12
16
|
|
|
13
17
|
# Separate admin connection string for migrations and schema operations (optional)
|
|
14
18
|
# Falls back to DATABASE_URL if not set
|
|
@@ -14,12 +14,12 @@ ENV PATH="$PNPM_HOME:$PATH"
|
|
|
14
14
|
RUN corepack enable
|
|
15
15
|
|
|
16
16
|
# Native dependencies for bcrypt, pg, etc.
|
|
17
|
-
RUN apk add --no-cache python3 make g++
|
|
17
|
+
RUN apk add --no-cache python3 make g++ curl ca-certificates
|
|
18
18
|
|
|
19
19
|
WORKDIR /app
|
|
20
20
|
|
|
21
21
|
# Copy workspace root files first (cache-friendly layer)
|
|
22
|
-
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
22
|
+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
|
|
23
23
|
|
|
24
24
|
# Copy workspace packages
|
|
25
25
|
COPY backend ./backend
|
|
@@ -41,6 +41,7 @@ FROM node:22-alpine AS runtime
|
|
|
41
41
|
ENV PNPM_HOME="/pnpm"
|
|
42
42
|
ENV PATH="$PNPM_HOME:$PATH"
|
|
43
43
|
ENV NODE_ENV=production
|
|
44
|
+
ENV CI=true
|
|
44
45
|
|
|
45
46
|
RUN corepack enable
|
|
46
47
|
|
|
@@ -50,7 +51,7 @@ RUN addgroup -g 1001 rebase && adduser -u 1001 -G rebase -s /bin/sh -D rebase
|
|
|
50
51
|
WORKDIR /app
|
|
51
52
|
|
|
52
53
|
# Copy only production artifacts
|
|
53
|
-
COPY --from=builder /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./
|
|
54
|
+
COPY --from=builder /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml /app/.npmrc ./
|
|
54
55
|
COPY --from=builder /app/node_modules ./node_modules
|
|
55
56
|
COPY --from=builder /app/backend ./backend
|
|
56
57
|
COPY --from=builder /app/config ./config
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { HonoEnv } from "@rebasepro/server-core";
|
|
3
|
-
import { rebase } from "@rebasepro/server-core";
|
|
1
|
+
import { defineFunction } from "@rebasepro/server-core";
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Example custom function route.
|
|
@@ -12,41 +10,47 @@ import { rebase } from "@rebasepro/server-core";
|
|
|
12
10
|
* Call from the client SDK:
|
|
13
11
|
* const result = await client.call("functions/hello", { name: "World" });
|
|
14
12
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* Authored with `defineFunction`, which hands you a pre-typed Hono app
|
|
14
|
+
* (so `c.get("user")` / `c.get("driver")` are typed) and the `rebase`
|
|
15
|
+
* singleton via the injected context — use any Hono middleware, define any
|
|
16
|
+
* HTTP methods, access the request/response directly.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* `rebase.dataAsAdmin` gives you admin-level access to your data and
|
|
19
|
+
* **bypasses RLS** — use it only for trusted admin work. For request-scoped /
|
|
20
|
+
* RLS-scoped data access, use c.get("user") and c.get("driver"), which carry
|
|
21
|
+
* the caller's identity. (`rebase` also exposes auth, storage, email.)
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
+
export default defineFunction((app, { rebase }) => {
|
|
24
|
+
void rebase; // available for dataAsAdmin/auth/storage/email — see commented usage below
|
|
23
25
|
|
|
24
|
-
app.post("/", async (c) => {
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
app.post("/", async (c) => {
|
|
27
|
+
const body = await c.req.json().catch(() => ({}));
|
|
28
|
+
const user = c.get("user");
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const userId = (user && typeof user === "object" && "userId" in user)
|
|
31
|
+
? user.userId
|
|
32
|
+
: "anonymous";
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
// Access any Rebase service via the injected `rebase`:
|
|
35
|
+
// await rebase.email.send({
|
|
36
|
+
// to: "admin@example.com",
|
|
37
|
+
// subject: "Function called",
|
|
38
|
+
// html: `<p>Hello from ${userId}!</p>`,
|
|
39
|
+
// });
|
|
40
|
+
//
|
|
41
|
+
// Admin-scoped data (bypasses RLS — trusted work only):
|
|
42
|
+
// const authors = await rebase.dataAsAdmin.authors.find({ limit: 5 });
|
|
43
|
+
// For user-scoped data (RLS applies), use the request-scoped driver
|
|
44
|
+
// (c.get("driver")), which carries the caller's identity.
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
return c.json({
|
|
47
|
+
message: `Hello, ${body.name || "World"}!`,
|
|
48
|
+
user: userId
|
|
49
|
+
});
|
|
44
50
|
});
|
|
45
|
-
});
|
|
46
51
|
|
|
47
|
-
app.get("/", (c) => {
|
|
48
|
-
|
|
49
|
-
endpoint: "hello" });
|
|
52
|
+
app.get("/", (c) => {
|
|
53
|
+
return c.json({ status: "ok",
|
|
54
|
+
endpoint: "hello" });
|
|
55
|
+
});
|
|
50
56
|
});
|
|
51
|
-
|
|
52
|
-
export default app;
|
|
@@ -14,13 +14,15 @@
|
|
|
14
14
|
"@rebasepro/server-core": "workspace:*",
|
|
15
15
|
"@rebasepro/server-postgresql": "workspace:*",
|
|
16
16
|
"@rebasepro/admin": "workspace:*",
|
|
17
|
+
"@rebasepro/types": "workspace:*",
|
|
17
18
|
"drizzle-orm": "^0.45.2",
|
|
18
19
|
"hono": "^4.12.10",
|
|
19
20
|
"@hono/node-server": "^1.19.12",
|
|
20
21
|
"pg": "^8.11.3",
|
|
21
22
|
"ws": "^8.16.0",
|
|
22
23
|
"react-compiler-runtime": "^1.0.0",
|
|
23
|
-
"dotenv": "^16.0.0"
|
|
24
|
+
"dotenv": "^16.0.0",
|
|
25
|
+
"zod": "^4.4.3"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
26
28
|
"@types/pg": "^8.6.5",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as dotenv from "dotenv";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
-
import { loadEnv
|
|
4
|
+
import { loadEnv } from "@rebasepro/server-core";
|
|
5
|
+
import { z } from "zod";
|
|
5
6
|
|
|
6
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
8
|
const __dirname = path.dirname(__filename);
|
|
@@ -7,6 +7,7 @@ import path from "path";
|
|
|
7
7
|
import { fileURLToPath } from "url";
|
|
8
8
|
import {
|
|
9
9
|
initializeRebaseBackend,
|
|
10
|
+
installShutdownHandlers,
|
|
10
11
|
serveSPA,
|
|
11
12
|
HonoEnv,
|
|
12
13
|
listenWithPortRetry,
|
|
@@ -88,10 +89,15 @@ relations },
|
|
|
88
89
|
accessExpiresIn: env.JWT_ACCESS_EXPIRES_IN,
|
|
89
90
|
refreshExpiresIn: env.JWT_REFRESH_EXPIRES_IN,
|
|
90
91
|
serviceKey: env.REBASE_SERVICE_KEY,
|
|
92
|
+
// Cookie-based auth: the refresh token is stored in an httpOnly
|
|
93
|
+
// cookie (not readable by JS) instead of localStorage, so it is
|
|
94
|
+
// not exposed to XSS. The frontend opts in via
|
|
95
|
+
// `authFlowMode: "cookie"` on createRebaseClient. Requires CORS
|
|
96
|
+
// `credentials: true` (set above).
|
|
97
|
+
cookieAuth: { sameSite: "Lax" },
|
|
91
98
|
google: env.GOOGLE_CLIENT_ID
|
|
92
99
|
? { clientId: env.GOOGLE_CLIENT_ID }
|
|
93
100
|
: undefined,
|
|
94
|
-
seedDefaultRoles: true,
|
|
95
101
|
allowRegistration: env.ALLOW_REGISTRATION,
|
|
96
102
|
email: env.SMTP_HOST
|
|
97
103
|
? {
|
|
@@ -164,17 +170,11 @@ pass: env.SMTP_PASS! }
|
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
// ─── Graceful Shutdown ───────────────────────────────────────────────
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
await pool.end();
|
|
173
|
-
logger.info("Database pool closed");
|
|
174
|
-
process.exit(0);
|
|
175
|
-
};
|
|
176
|
-
process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
|
|
177
|
-
process.on("SIGINT", () => gracefulShutdown("SIGINT"));
|
|
173
|
+
// Drains HTTP, stops crons, tears down realtime, then closes the pool.
|
|
174
|
+
// Guards against double signals and force-exits if shutdown hangs.
|
|
175
|
+
installShutdownHandlers(backend, {
|
|
176
|
+
onCleanup: () => pool.end()
|
|
177
|
+
});
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
startServer().catch(err => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const authorsCollection:
|
|
3
|
+
const authorsCollection: CollectionConfig = {
|
|
4
4
|
name: "Authors",
|
|
5
5
|
singularName: "Author",
|
|
6
6
|
slug: "authors",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionConfig } from "@rebasepro/types";
|
|
2
2
|
import authorsCollection from "./authors.js";
|
|
3
3
|
import tagsCollection from "./tags.js";
|
|
4
4
|
|
|
5
|
-
const postsCollection:
|
|
5
|
+
const postsCollection: CollectionConfig = {
|
|
6
6
|
name: "Posts",
|
|
7
7
|
singularName: "Post",
|
|
8
8
|
slug: "posts",
|
|
@@ -24,7 +24,9 @@ const postsCollection: EntityCollection = {
|
|
|
24
24
|
content: {
|
|
25
25
|
name: "Content",
|
|
26
26
|
type: "string",
|
|
27
|
-
|
|
27
|
+
ui: {
|
|
28
|
+
markdown: true
|
|
29
|
+
}
|
|
28
30
|
},
|
|
29
31
|
status: {
|
|
30
32
|
name: "Status",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const categoriesCollection:
|
|
3
|
+
const categoriesCollection: CollectionConfig = {
|
|
4
4
|
name: "Categories",
|
|
5
5
|
singularName: "Category",
|
|
6
6
|
slug: "categories",
|
|
@@ -25,7 +25,9 @@ const categoriesCollection: EntityCollection = {
|
|
|
25
25
|
description: {
|
|
26
26
|
name: "Description",
|
|
27
27
|
type: "string",
|
|
28
|
-
|
|
28
|
+
ui: {
|
|
29
|
+
multiline: true
|
|
30
|
+
}
|
|
29
31
|
},
|
|
30
32
|
icon: {
|
|
31
33
|
name: "Icon",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const ordersCollection:
|
|
3
|
+
const ordersCollection: CollectionConfig = {
|
|
4
4
|
name: "Orders",
|
|
5
5
|
singularName: "Order",
|
|
6
6
|
slug: "orders",
|
|
@@ -47,7 +47,9 @@ color: "red" }
|
|
|
47
47
|
notes: {
|
|
48
48
|
name: "Notes",
|
|
49
49
|
type: "string",
|
|
50
|
-
|
|
50
|
+
ui: {
|
|
51
|
+
multiline: true
|
|
52
|
+
}
|
|
51
53
|
},
|
|
52
54
|
createdAt: {
|
|
53
55
|
name: "Created At",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CollectionConfig } from "@rebasepro/types";
|
|
2
2
|
import categoriesCollection from "./categories.js";
|
|
3
3
|
|
|
4
|
-
const productsCollection:
|
|
4
|
+
const productsCollection: CollectionConfig = {
|
|
5
5
|
name: "Products",
|
|
6
6
|
singularName: "Product",
|
|
7
7
|
slug: "products",
|
|
@@ -21,7 +21,9 @@ const productsCollection: EntityCollection = {
|
|
|
21
21
|
description: {
|
|
22
22
|
name: "Description",
|
|
23
23
|
type: "string",
|
|
24
|
-
|
|
24
|
+
ui: {
|
|
25
|
+
markdown: true
|
|
26
|
+
}
|
|
25
27
|
},
|
|
26
28
|
price: {
|
|
27
29
|
name: "Price",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const usersCollection:
|
|
3
|
+
const usersCollection: CollectionConfig = {
|
|
4
4
|
name: "Users",
|
|
5
5
|
singularName: "User",
|
|
6
6
|
slug: "users",
|
|
@@ -44,7 +44,9 @@ roles: ["admin"] }
|
|
|
44
44
|
name: "Photo URL",
|
|
45
45
|
type: "string",
|
|
46
46
|
columnName: "photo_url",
|
|
47
|
-
|
|
47
|
+
ui: {
|
|
48
|
+
url: "image"
|
|
49
|
+
}
|
|
48
50
|
},
|
|
49
51
|
roles: {
|
|
50
52
|
name: "Roles",
|
|
@@ -17,14 +17,16 @@ RUN apk add --no-cache python3 make g++
|
|
|
17
17
|
WORKDIR /app
|
|
18
18
|
|
|
19
19
|
# Copy workspace root files
|
|
20
|
-
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
|
20
|
+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
|
|
21
21
|
|
|
22
22
|
# Copy workspace packages
|
|
23
23
|
COPY frontend ./frontend
|
|
24
24
|
COPY config ./config
|
|
25
25
|
|
|
26
|
-
# Install dependencies
|
|
27
|
-
|
|
26
|
+
# Install dependencies (skip scripts to avoid @ariga/atlas binary download,
|
|
27
|
+
# which is a backend-only dependency that may fail on certain platforms)
|
|
28
|
+
RUN pnpm install --frozen-lockfile --ignore-scripts
|
|
29
|
+
RUN pnpm rebuild esbuild
|
|
28
30
|
|
|
29
31
|
# Build config first, then frontend
|
|
30
32
|
RUN pnpm --filter "*-config" run build
|
|
@@ -17,7 +17,10 @@ const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;
|
|
|
17
17
|
|
|
18
18
|
export function App() {
|
|
19
19
|
const rebaseClient = React.useMemo(() => createRebaseClient({
|
|
20
|
-
baseUrl: API_URL
|
|
20
|
+
baseUrl: API_URL,
|
|
21
|
+
// Store the refresh token in an httpOnly cookie (XSS-safe) rather than
|
|
22
|
+
// localStorage. The backend issues it via `auth.cookieAuth`.
|
|
23
|
+
auth: { authFlowMode: "cookie" }
|
|
21
24
|
}), []);
|
|
22
25
|
|
|
23
26
|
const authController = useRebaseAuthController({
|
|
@@ -7,6 +7,20 @@ import { rebaseCollectionsPlugin } from "@rebasepro/core/vitePlugin";
|
|
|
7
7
|
|
|
8
8
|
export default defineConfig({
|
|
9
9
|
envDir: path.resolve(__dirname, ".."),
|
|
10
|
+
// Force a single copy of React and React Router across the app and all
|
|
11
|
+
// @rebasepro/* packages. Without this, a locally `link:`ed Rebase checkout
|
|
12
|
+
// resolves its own copies of react-router, producing "multiple copies of
|
|
13
|
+
// React" and "useBlocker must be used within a data router" errors in the
|
|
14
|
+
// admin. Safe to keep for npm-installed setups too.
|
|
15
|
+
resolve: {
|
|
16
|
+
dedupe: [
|
|
17
|
+
"react",
|
|
18
|
+
"react-dom",
|
|
19
|
+
"react-router",
|
|
20
|
+
"react-router-dom",
|
|
21
|
+
"@remix-run/router"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
10
24
|
esbuild: {
|
|
11
25
|
logOverride: { "this-is-undefined-in-esm": "silent" }
|
|
12
26
|
},
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@rebasepro/cli": "workspace:*",
|
|
27
|
+
"@rebasepro/types": "workspace:*",
|
|
27
28
|
"concurrently": "^8.2.2",
|
|
28
29
|
"typescript": "^5.9.2"
|
|
29
30
|
},
|
|
@@ -33,7 +34,8 @@
|
|
|
33
34
|
"pnpm": {
|
|
34
35
|
"onlyBuiltDependencies": [
|
|
35
36
|
"esbuild",
|
|
36
|
-
"sharp"
|
|
37
|
+
"sharp",
|
|
38
|
+
"@ariga/atlas"
|
|
37
39
|
]
|
|
38
40
|
}
|
|
39
41
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Scripts run OUTSIDE the server and need explicit authentication.
|
|
5
5
|
* Use a Service Key (set in .env as REBASE_SERVICE_KEY) to get admin
|
|
6
|
-
* access — similar to a
|
|
6
|
+
* access — similar to a Service Account credential.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
|
9
9
|
* # With local dev server running (`pnpm dev` in another terminal):
|