@rebasepro/cli 0.10.1-canary.d8d45b2 → 0.10.1-canary.ed8caed
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/bundle.d.ts +35 -0
- package/dist/commands/cloud/bundle-deploy.d.ts +25 -0
- package/dist/fold-static.d.ts +46 -0
- package/dist/index.es.js +175 -2
- package/dist/index.es.js.map +1 -1
- package/package.json +7 -7
- package/templates/overlays/baas/backend/src/index.ts +7 -0
- package/templates/overlays/baas/backend/src/storage.ts +71 -0
- package/templates/template/backend/src/index.ts +7 -0
- package/templates/template/config/admin.d.ts +9 -0
- package/templates/template/config/collections/authors.ts +11 -9
- package/templates/template/config/collections/posts.ts +6 -4
- package/templates/template/config/collections/presets/ecommerce/categories.ts +7 -5
- package/templates/template/config/collections/presets/ecommerce/orders.ts +32 -20
- package/templates/template/config/collections/presets/ecommerce/products.ts +21 -13
- package/templates/template/config/collections/tags.ts +5 -3
- package/templates/template/config/collections/users.ts +34 -29
- package/templates/template/config/frontend-assets.d.ts +17 -0
- package/templates/template/config/index.ts +6 -0
- package/templates/template/config/package.json +26 -25
- package/templates/template/config/storage.ts +88 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/cli",
|
|
3
|
-
"version": "0.10.1-canary.
|
|
3
|
+
"version": "0.10.1-canary.ed8caed",
|
|
4
4
|
"description": "Developer tools for Rebase projects",
|
|
5
5
|
"main": "./dist/index.es.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"execa": "^9.6.1",
|
|
32
32
|
"inquirer": "14.0.2",
|
|
33
33
|
"jiti": "^2.7.0",
|
|
34
|
-
"@rebasepro/agent-skills": "0.10.1-canary.
|
|
35
|
-
"@rebasepro/client": "0.10.1-canary.
|
|
36
|
-
"@rebasepro/
|
|
37
|
-
"@rebasepro/
|
|
38
|
-
"@rebasepro/
|
|
39
|
-
"@rebasepro/server": "0.10.1-canary.
|
|
34
|
+
"@rebasepro/agent-skills": "0.10.1-canary.ed8caed",
|
|
35
|
+
"@rebasepro/client": "0.10.1-canary.ed8caed",
|
|
36
|
+
"@rebasepro/types": "0.10.1-canary.ed8caed",
|
|
37
|
+
"@rebasepro/server": "0.10.1-canary.ed8caed",
|
|
38
|
+
"@rebasepro/codegen": "0.10.1-canary.ed8caed",
|
|
39
|
+
"@rebasepro/server-postgres": "0.10.1-canary.ed8caed"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^25.9.3",
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from "@rebasepro/server";
|
|
16
16
|
import { createPostgresDatabaseConnection, createPostgresAdapter } from "@rebasepro/server-postgres";
|
|
17
17
|
import { env } from "./env.js";
|
|
18
|
+
import { storageAuthorize } from "./storage.js";
|
|
18
19
|
|
|
19
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
21
|
const __dirname = path.dirname(__filename);
|
|
@@ -153,6 +154,12 @@ pass: env.SMTP_PASS! }
|
|
|
153
154
|
type: "local",
|
|
154
155
|
basePath: env.STORAGE_PATH || path.resolve(__dirname, "../../uploads")
|
|
155
156
|
},
|
|
157
|
+
// Storage is not under row-level security, so this hook IS its access
|
|
158
|
+
// model — the server refuses to boot in production without one, because
|
|
159
|
+
// "signed in" would otherwise be the only thing between a caller and every
|
|
160
|
+
// file in the bucket. See storage.ts; the default scopes each caller to
|
|
161
|
+
// `users/<uid>/` and is meant to be replaced with your own rule.
|
|
162
|
+
storageAuthorize,
|
|
156
163
|
history: true,
|
|
157
164
|
enableSwagger: true
|
|
158
165
|
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { isPublicStoragePath, type StorageAuthorize } from "@rebasepro/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Who may do what to files in storage.
|
|
5
|
+
*
|
|
6
|
+
* Storage is **not** under row-level security. Tables are: a request runs as
|
|
7
|
+
* `rebase_user` and Postgres decides row by row. Object storage has no equivalent,
|
|
8
|
+
* so keys share one flat namespace and this hook is the whole authorization model.
|
|
9
|
+
* Without it the server refuses to boot in production, because "authenticated"
|
|
10
|
+
* would be the only thing between a signed-in caller and every file in the bucket —
|
|
11
|
+
* they can `GET /storage/list?prefix=` to enumerate every key, then read, overwrite
|
|
12
|
+
* or delete any of them.
|
|
13
|
+
*
|
|
14
|
+
* It lives in `backend/src/` rather than a config package because BaaS mode has no
|
|
15
|
+
* config package: collections come from the live database, so there is nothing to
|
|
16
|
+
* declare and nowhere else to put this.
|
|
17
|
+
*
|
|
18
|
+
* ## The default this starter ships
|
|
19
|
+
*
|
|
20
|
+
* A deliberately conservative one, because a BaaS project's storage semantics are
|
|
21
|
+
* whatever *your* application says they are and this file cannot know:
|
|
22
|
+
*
|
|
23
|
+
* | operation | who |
|
|
24
|
+
* | --- | --- |
|
|
25
|
+
* | `read` of `public/…` | anyone, signed in or not |
|
|
26
|
+
* | everything else | a signed-in caller under their own `users/<uid>/` prefix |
|
|
27
|
+
*
|
|
28
|
+
* Gating `list` on the prefix is the important half. Enumeration is what turns "keys
|
|
29
|
+
* are hard to guess" into "keys are known", and it is step one of the attack the
|
|
30
|
+
* boot guard exists to prevent.
|
|
31
|
+
*
|
|
32
|
+
* ## Replace this with your model
|
|
33
|
+
*
|
|
34
|
+
* Prefix rules are a starting point, not a general answer: they work for writes
|
|
35
|
+
* because a write *puts* the object there, but anything already in the bucket needs
|
|
36
|
+
* the row that owns it consulted. `ctx.data` is handed in for exactly that — trusted,
|
|
37
|
+
* RLS-bypassing reads, because the hook *is* the authorization decision and running
|
|
38
|
+
* it through a reader already narrowed by the caller's permissions would be circular:
|
|
39
|
+
*
|
|
40
|
+
* ```ts
|
|
41
|
+
* export const storageAuthorize: StorageAuthorize = async ({ key, user, operation, data }) => {
|
|
42
|
+
* if (operation === "read" && isPublicStoragePath(key)) return true;
|
|
43
|
+
* if (!user) return false;
|
|
44
|
+
* const row = (await data?.collection("attachments").find({
|
|
45
|
+
* where: { storage_key: ["==", key] }, limit: 1
|
|
46
|
+
* }))?.data?.[0];
|
|
47
|
+
* return row?.owner_id === user.uid;
|
|
48
|
+
* };
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* If your bucket really is a public read-only CDN, `storagePublicRead: true` says so
|
|
52
|
+
* instead. If every signed-in caller is genuinely trusted with every file,
|
|
53
|
+
* `storageInsecureAllowAnyAuthenticated: true` says *that* — it is named to be read
|
|
54
|
+
* twice. Both are set on `initializeRebaseBackend` in `index.ts`.
|
|
55
|
+
*/
|
|
56
|
+
export const storageAuthorize: StorageAuthorize = ({ key, user, operation }) => {
|
|
57
|
+
// The `public/` prefix is the framework's convention for world-readable objects.
|
|
58
|
+
if (operation === "read" && isPublicStoragePath(key)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// `user` is null on routes that allow unauthenticated access.
|
|
63
|
+
if (!user) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Each caller gets their own namespace. A listing is scoped the same way, so a
|
|
68
|
+
// prefix outside it — including the empty prefix, which would enumerate the
|
|
69
|
+
// whole bucket — is denied.
|
|
70
|
+
return key.startsWith(`users/${user.uid}/`);
|
|
71
|
+
};
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "@rebasepro/server";
|
|
17
17
|
import { createPostgresDatabaseConnection, createPostgresAdapter } from "@rebasepro/server-postgres";
|
|
18
18
|
import { enums, relations, tables } from "./schema.generated.js";
|
|
19
|
+
import { storageAuthorize } from "../../config/storage.js";
|
|
19
20
|
import { env } from "./env.js";
|
|
20
21
|
import usersCollection from "../../config/collections/users.js";
|
|
21
22
|
|
|
@@ -154,6 +155,12 @@ pass: env.SMTP_PASS! }
|
|
|
154
155
|
type: "local",
|
|
155
156
|
basePath: env.STORAGE_PATH || path.resolve(__dirname, "../../uploads")
|
|
156
157
|
},
|
|
158
|
+
// Storage is not under row-level security, so this hook IS its access
|
|
159
|
+
// model — the server refuses to boot in production without one, because
|
|
160
|
+
// "signed in" would otherwise be the only thing between a visitor and
|
|
161
|
+
// every file in the bucket. See config/storage.ts, which also shows the
|
|
162
|
+
// multi-tenant (per-owner) shape and the two escape hatches.
|
|
163
|
+
storageAuthorize,
|
|
157
164
|
history: true
|
|
158
165
|
});
|
|
159
166
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="@rebasepro/admin-types" />
|
|
2
|
+
|
|
3
|
+
// One line, once per project. `@rebasepro/admin-types` declares the `admin` block on
|
|
4
|
+
// `CollectionConfig` and on every property type by declaration merging, and an
|
|
5
|
+
// augmentation applies to the whole *program* — so this reference is what makes
|
|
6
|
+
// `admin: { … }` legal in every collection file here.
|
|
7
|
+
//
|
|
8
|
+
// A BaaS project has no admin panel and no reason for this file. Without it, `admin` on
|
|
9
|
+
// a collection or a property is a type error, which is the guarantee.
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const authorsCollection:
|
|
3
|
+
const authorsCollection: PostgresCollectionConfig = {
|
|
4
4
|
name: "Authors",
|
|
5
5
|
singularName: "Author",
|
|
6
6
|
slug: "authors",
|
|
7
7
|
table: "authors",
|
|
8
|
-
icon: "Person",
|
|
9
8
|
properties: {
|
|
10
9
|
id: {
|
|
11
10
|
name: "ID",
|
|
@@ -34,12 +33,15 @@ const authorsCollection: CollectionConfig = {
|
|
|
34
33
|
}
|
|
35
34
|
}
|
|
36
35
|
},
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
admin: {
|
|
37
|
+
icon: "Person",
|
|
38
|
+
propertiesOrder: [
|
|
39
|
+
"id",
|
|
40
|
+
"name",
|
|
41
|
+
"email",
|
|
42
|
+
"picture"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
43
45
|
};
|
|
44
46
|
|
|
45
47
|
export default authorsCollection;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PostgresCollectionConfig } 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: PostgresCollectionConfig = {
|
|
6
6
|
name: "Posts",
|
|
7
7
|
singularName: "Post",
|
|
8
8
|
slug: "posts",
|
|
9
9
|
table: "posts",
|
|
10
|
-
icon: "Article",
|
|
11
10
|
properties: {
|
|
12
11
|
id: {
|
|
13
12
|
name: "ID",
|
|
@@ -24,7 +23,7 @@ const postsCollection: CollectionConfig = {
|
|
|
24
23
|
content: {
|
|
25
24
|
name: "Content",
|
|
26
25
|
type: "string",
|
|
27
|
-
|
|
26
|
+
admin: {
|
|
28
27
|
markdown: true
|
|
29
28
|
}
|
|
30
29
|
},
|
|
@@ -65,6 +64,9 @@ const postsCollection: CollectionConfig = {
|
|
|
65
64
|
cardinality: "many",
|
|
66
65
|
direction: "owning"
|
|
67
66
|
}
|
|
67
|
+
},
|
|
68
|
+
admin: {
|
|
69
|
+
icon: "Article"
|
|
68
70
|
}
|
|
69
71
|
};
|
|
70
72
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const categoriesCollection:
|
|
3
|
+
const categoriesCollection: PostgresCollectionConfig = {
|
|
4
4
|
name: "Categories",
|
|
5
5
|
singularName: "Category",
|
|
6
6
|
slug: "categories",
|
|
7
7
|
table: "categories",
|
|
8
|
-
icon: "Category",
|
|
9
8
|
properties: {
|
|
10
9
|
id: {
|
|
11
10
|
name: "ID",
|
|
@@ -25,7 +24,7 @@ const categoriesCollection: CollectionConfig = {
|
|
|
25
24
|
description: {
|
|
26
25
|
name: "Description",
|
|
27
26
|
type: "string",
|
|
28
|
-
|
|
27
|
+
admin: {
|
|
29
28
|
multiline: true
|
|
30
29
|
}
|
|
31
30
|
},
|
|
@@ -34,7 +33,10 @@ const categoriesCollection: CollectionConfig = {
|
|
|
34
33
|
type: "string"
|
|
35
34
|
}
|
|
36
35
|
},
|
|
37
|
-
|
|
36
|
+
admin: {
|
|
37
|
+
icon: "Category",
|
|
38
|
+
propertiesOrder: ["id", "name", "slug", "description", "icon"]
|
|
39
|
+
}
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
export default categoriesCollection;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const ordersCollection:
|
|
3
|
+
const ordersCollection: PostgresCollectionConfig = {
|
|
4
4
|
name: "Orders",
|
|
5
5
|
singularName: "Order",
|
|
6
6
|
slug: "orders",
|
|
7
7
|
table: "orders",
|
|
8
|
-
icon: "Receipt",
|
|
9
8
|
properties: {
|
|
10
9
|
id: {
|
|
11
10
|
name: "ID",
|
|
@@ -22,21 +21,31 @@ const ordersCollection: CollectionConfig = {
|
|
|
22
21
|
name: "Status",
|
|
23
22
|
type: "string",
|
|
24
23
|
enum: [
|
|
25
|
-
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
label: "
|
|
33
|
-
color: "
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
{
|
|
25
|
+
id: "pending",
|
|
26
|
+
label: "Pending",
|
|
27
|
+
color: "gray"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "processing",
|
|
31
|
+
label: "Processing",
|
|
32
|
+
color: "blue"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "shipped",
|
|
36
|
+
label: "Shipped",
|
|
37
|
+
color: "orange"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "delivered",
|
|
41
|
+
label: "Delivered",
|
|
42
|
+
color: "green"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "cancelled",
|
|
46
|
+
label: "Cancelled",
|
|
47
|
+
color: "red"
|
|
48
|
+
}
|
|
40
49
|
]
|
|
41
50
|
},
|
|
42
51
|
total: {
|
|
@@ -47,7 +56,7 @@ color: "red" }
|
|
|
47
56
|
notes: {
|
|
48
57
|
name: "Notes",
|
|
49
58
|
type: "string",
|
|
50
|
-
|
|
59
|
+
admin: {
|
|
51
60
|
multiline: true
|
|
52
61
|
}
|
|
53
62
|
},
|
|
@@ -56,10 +65,13 @@ color: "red" }
|
|
|
56
65
|
type: "date",
|
|
57
66
|
columnName: "created_at",
|
|
58
67
|
autoValue: "on_create",
|
|
59
|
-
|
|
68
|
+
admin: {
|
|
60
69
|
readOnly: true
|
|
61
70
|
}
|
|
62
71
|
}
|
|
72
|
+
},
|
|
73
|
+
admin: {
|
|
74
|
+
icon: "Receipt"
|
|
63
75
|
}
|
|
64
76
|
};
|
|
65
77
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
2
2
|
import categoriesCollection from "./categories.js";
|
|
3
3
|
|
|
4
|
-
const productsCollection:
|
|
4
|
+
const productsCollection: PostgresCollectionConfig = {
|
|
5
5
|
name: "Products",
|
|
6
6
|
singularName: "Product",
|
|
7
7
|
slug: "products",
|
|
8
8
|
table: "products",
|
|
9
|
-
icon: "ShoppingCart",
|
|
10
9
|
properties: {
|
|
11
10
|
id: {
|
|
12
11
|
name: "ID",
|
|
@@ -21,7 +20,7 @@ const productsCollection: CollectionConfig = {
|
|
|
21
20
|
description: {
|
|
22
21
|
name: "Description",
|
|
23
22
|
type: "string",
|
|
24
|
-
|
|
23
|
+
admin: {
|
|
25
24
|
markdown: true
|
|
26
25
|
}
|
|
27
26
|
},
|
|
@@ -39,15 +38,21 @@ const productsCollection: CollectionConfig = {
|
|
|
39
38
|
name: "Status",
|
|
40
39
|
type: "string",
|
|
41
40
|
enum: [
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
label: "
|
|
50
|
-
color: "
|
|
41
|
+
{
|
|
42
|
+
id: "draft",
|
|
43
|
+
label: "Draft",
|
|
44
|
+
color: "gray"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "active",
|
|
48
|
+
label: "Active",
|
|
49
|
+
color: "green"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "archived",
|
|
53
|
+
label: "Archived",
|
|
54
|
+
color: "orange"
|
|
55
|
+
}
|
|
51
56
|
]
|
|
52
57
|
},
|
|
53
58
|
category: {
|
|
@@ -58,6 +63,9 @@ color: "orange" }
|
|
|
58
63
|
cardinality: "one",
|
|
59
64
|
direction: "owning"
|
|
60
65
|
}
|
|
66
|
+
},
|
|
67
|
+
admin: {
|
|
68
|
+
icon: "ShoppingCart"
|
|
61
69
|
}
|
|
62
70
|
};
|
|
63
71
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const tagsCollection:
|
|
3
|
+
const tagsCollection: PostgresCollectionConfig = {
|
|
4
4
|
name: "Tags",
|
|
5
5
|
singularName: "Tag",
|
|
6
6
|
slug: "tags",
|
|
7
7
|
table: "tags",
|
|
8
|
-
icon: "Tag",
|
|
9
8
|
properties: {
|
|
10
9
|
id: {
|
|
11
10
|
name: "ID",
|
|
@@ -19,6 +18,9 @@ const tagsCollection: CollectionConfig = {
|
|
|
19
18
|
required: true
|
|
20
19
|
}
|
|
21
20
|
}
|
|
21
|
+
},
|
|
22
|
+
admin: {
|
|
23
|
+
icon: "Tag"
|
|
22
24
|
}
|
|
23
25
|
};
|
|
24
26
|
|
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PostgresCollectionConfig } from "@rebasepro/types";
|
|
2
2
|
|
|
3
|
-
const usersCollection:
|
|
3
|
+
const usersCollection: PostgresCollectionConfig = {
|
|
4
4
|
name: "Users",
|
|
5
5
|
singularName: "User",
|
|
6
6
|
slug: "users",
|
|
7
7
|
auth: { enabled: true },
|
|
8
8
|
table: "users",
|
|
9
9
|
schema: "rebase",
|
|
10
|
-
icon: "Users",
|
|
11
|
-
group: "Settings",
|
|
12
|
-
openEntityMode: "dialog",
|
|
13
|
-
disableDefaultActions: ["copy"],
|
|
14
10
|
securityRules: [
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
{
|
|
12
|
+
operation: "select",
|
|
13
|
+
roles: ["admin"]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
operations: ["insert", "update", "delete"],
|
|
17
|
+
roles: ["admin"]
|
|
18
|
+
}
|
|
19
19
|
],
|
|
20
|
-
sort: ["createdAt", "desc"],
|
|
21
20
|
properties: {
|
|
22
21
|
id: {
|
|
23
22
|
name: "ID",
|
|
24
23
|
type: "string",
|
|
25
24
|
isId: "uuid",
|
|
26
|
-
|
|
25
|
+
admin: {
|
|
27
26
|
readOnly: true
|
|
28
27
|
}
|
|
29
28
|
},
|
|
@@ -44,9 +43,8 @@ roles: ["admin"] }
|
|
|
44
43
|
name: "Photo URL",
|
|
45
44
|
type: "string",
|
|
46
45
|
columnName: "photo_url",
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
46
|
+
url: true,
|
|
47
|
+
admin: { urlPreview: "image" }
|
|
50
48
|
},
|
|
51
49
|
roles: {
|
|
52
50
|
name: "Roles",
|
|
@@ -67,7 +65,7 @@ roles: ["admin"] }
|
|
|
67
65
|
type: "string",
|
|
68
66
|
columnName: "password_hash",
|
|
69
67
|
excludeFromApi: true,
|
|
70
|
-
|
|
68
|
+
admin: {
|
|
71
69
|
hideFromCollection: true,
|
|
72
70
|
disabled: { hidden: true }
|
|
73
71
|
}
|
|
@@ -77,7 +75,7 @@ roles: ["admin"] }
|
|
|
77
75
|
type: "boolean",
|
|
78
76
|
columnName: "email_verified",
|
|
79
77
|
defaultValue: false,
|
|
80
|
-
|
|
78
|
+
admin: {
|
|
81
79
|
hideFromCollection: true,
|
|
82
80
|
disabled: { hidden: true }
|
|
83
81
|
}
|
|
@@ -87,7 +85,7 @@ roles: ["admin"] }
|
|
|
87
85
|
type: "string",
|
|
88
86
|
columnName: "email_verification_token",
|
|
89
87
|
excludeFromApi: true,
|
|
90
|
-
|
|
88
|
+
admin: {
|
|
91
89
|
hideFromCollection: true,
|
|
92
90
|
disabled: { hidden: true }
|
|
93
91
|
}
|
|
@@ -96,7 +94,7 @@ roles: ["admin"] }
|
|
|
96
94
|
name: "Email Verification Sent At",
|
|
97
95
|
type: "date",
|
|
98
96
|
columnName: "email_verification_sent_at",
|
|
99
|
-
|
|
97
|
+
admin: {
|
|
100
98
|
hideFromCollection: true,
|
|
101
99
|
disabled: { hidden: true }
|
|
102
100
|
}
|
|
@@ -107,7 +105,7 @@ roles: ["admin"] }
|
|
|
107
105
|
keyValue: true,
|
|
108
106
|
properties: {},
|
|
109
107
|
defaultValue: {},
|
|
110
|
-
|
|
108
|
+
admin: {
|
|
111
109
|
hideFromCollection: true,
|
|
112
110
|
disabled: { hidden: true }
|
|
113
111
|
}
|
|
@@ -117,7 +115,7 @@ roles: ["admin"] }
|
|
|
117
115
|
type: "date",
|
|
118
116
|
columnName: "created_at",
|
|
119
117
|
autoValue: "on_create",
|
|
120
|
-
|
|
118
|
+
admin: {
|
|
121
119
|
readOnly: true
|
|
122
120
|
}
|
|
123
121
|
},
|
|
@@ -126,19 +124,26 @@ roles: ["admin"] }
|
|
|
126
124
|
type: "date",
|
|
127
125
|
columnName: "updated_at",
|
|
128
126
|
autoValue: "on_update",
|
|
129
|
-
|
|
127
|
+
admin: {
|
|
130
128
|
hideFromCollection: true,
|
|
131
129
|
disabled: { hidden: true }
|
|
132
130
|
}
|
|
133
131
|
}
|
|
134
132
|
},
|
|
135
|
-
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"createdAt"
|
|
141
|
-
|
|
133
|
+
admin: {
|
|
134
|
+
icon: "Users",
|
|
135
|
+
group: "Settings",
|
|
136
|
+
openEntityMode: "dialog",
|
|
137
|
+
disableDefaultActions: ["copy"],
|
|
138
|
+
sort: ["createdAt", "desc"],
|
|
139
|
+
propertiesOrder: [
|
|
140
|
+
"id",
|
|
141
|
+
"email",
|
|
142
|
+
"displayName",
|
|
143
|
+
"roles",
|
|
144
|
+
"createdAt"
|
|
145
|
+
]
|
|
146
|
+
}
|
|
142
147
|
};
|
|
143
148
|
|
|
144
149
|
export default usersCollection;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient declarations for the asset imports a frontend component makes.
|
|
3
|
+
*
|
|
4
|
+
* A collection that points at a custom `Field` or `Preview` with a lazy `import()`
|
|
5
|
+
* thunk gets that reference type-checked — which means TypeScript resolves the
|
|
6
|
+
* component's *own* imports too, including `import icon from "./icon.png"`. That
|
|
7
|
+
* import is Vite's doing and means nothing to `tsc`: the frontend gets away with it
|
|
8
|
+
* through `vite/client` types, but those belong to the frontend's program, not this
|
|
9
|
+
* one, and Vite is not a dependency here (nothing in `config/` runs in a browser).
|
|
10
|
+
*
|
|
11
|
+
* Without these three lines, adding your first custom component fails the config and
|
|
12
|
+
* backend builds with `Cannot find module './icon.png'` — pointing at a frontend file
|
|
13
|
+
* from a build that has no obvious business compiling it.
|
|
14
|
+
*/
|
|
15
|
+
declare module "*.png" { const src: string; export default src; }
|
|
16
|
+
declare module "*.svg" { const src: string; export default src; }
|
|
17
|
+
declare module "*.jpg" { const src: string; export default src; }
|
|
@@ -4,3 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export { collections } from "./collections/index.js";
|
|
7
|
+
|
|
8
|
+
// Who may read, write, delete and list files in storage. Exported from here
|
|
9
|
+
// because that is where the runtime and `rebase cloud deploy` look for it — the
|
|
10
|
+
// bundle manifest records whether this export exists, so a managed deploy can be
|
|
11
|
+
// refused with a readable message instead of turning into a boot crash-loop.
|
|
12
|
+
export { storageAuthorize } from "./storage.js";
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
"name": "{{PROJECT_NAME}}-config",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared collections for frontend and backend",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"private": true,
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"clean": "rm -rf dist"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@rebasepro/admin-types": "workspace:*",
|
|
16
|
+
"@rebasepro/types": "workspace:*"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"typescript": "^5.9.2"
|
|
20
|
+
},
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
13
26
|
},
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"typescript": "^5.9.2"
|
|
19
|
-
},
|
|
20
|
-
"exports": {
|
|
21
|
-
".": {
|
|
22
|
-
"import": "./dist/index.js",
|
|
23
|
-
"types": "./dist/index.d.ts",
|
|
24
|
-
"default": "./dist/index.js"
|
|
25
|
-
},
|
|
26
|
-
"./package.json": "./package.json"
|
|
27
|
-
}
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
}
|
|
28
29
|
}
|