vibeorm 1.1.5 → 1.1.7

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 (2) hide show
  1. package/README.md +116 -0
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -1063,6 +1063,122 @@ const db = VibeClient({
1063
1063
 
1064
1064
  ---
1065
1065
 
1066
+ ## Views
1067
+
1068
+ Views let you define **named, read-only projections** that restrict which fields are returned per model. They provide:
1069
+
1070
+ - **SQL-level restriction** -- only view-defined fields appear in `SELECT` clauses
1071
+ - **Zod safety net** -- a derived schema strips any extra fields post-query
1072
+ - **`reveal` keyword** -- explicitly opt-in to extra fields that are excluded from `JSON.stringify` by default
1073
+ - **Serialization safety** -- revealed fields are accessible as normal properties but excluded from JSON output
1074
+
1075
+ ### Defining a view
1076
+
1077
+ ```ts
1078
+ const publicApi = db.defineView({
1079
+ name: "public-api",
1080
+ definition: {
1081
+ user: { id: true, name: true, createdAt: true },
1082
+ post: { id: true, title: true, createdAt: true },
1083
+ },
1084
+ });
1085
+ ```
1086
+
1087
+ The `definition` is type-safe -- only valid model names and scalar field names are accepted.
1088
+
1089
+ ### Reading through a view
1090
+
1091
+ Views expose only read operations (`findMany`, `findFirst`, `findUnique`, `findUniqueOrThrow`, `findFirstOrThrow`, `count`, `aggregate`, `groupBy`). Write operations (`create`, `update`, `delete`, etc.) are not available -- use the original `db` client for writes.
1092
+
1093
+ ```ts
1094
+ // Only returns { id, name, createdAt } per user
1095
+ const users = await publicApi.user.findMany();
1096
+
1097
+ // Where, orderBy, pagination all work normally
1098
+ const admins = await publicApi.user.findMany({
1099
+ where: { role: "ADMIN" },
1100
+ orderBy: { createdAt: "desc" },
1101
+ take: 10,
1102
+ });
1103
+
1104
+ // select narrows within view fields
1105
+ const names = await publicApi.user.findMany({
1106
+ select: { id: true, name: true },
1107
+ });
1108
+ // Type: { id: number; name: string | null }[]
1109
+ ```
1110
+
1111
+ ### Relations are restricted too
1112
+
1113
+ When you `include` a relation, its fields are also restricted by the view definition:
1114
+
1115
+ ```ts
1116
+ const users = await publicApi.user.findMany({
1117
+ include: { posts: true },
1118
+ });
1119
+ // users[0].posts → [{ id, title, createdAt }] — only post view fields
1120
+ ```
1121
+
1122
+ If a relation's model is **not** in the view definition, it returns all fields as usual.
1123
+
1124
+ ### Revealing extra fields
1125
+
1126
+ Use `reveal` to access fields outside the view. Revealed fields are accessible as normal properties but **excluded from `JSON.stringify()`** -- preventing accidental data leaks in API responses.
1127
+
1128
+ ```ts
1129
+ const user = await publicApi.user.findUniqueOrThrow({
1130
+ where: { id: 1 },
1131
+ reveal: { email: true },
1132
+ });
1133
+
1134
+ user.id; // number (view field)
1135
+ user.name; // string | null (view field)
1136
+ user.email; // string (revealed -- accessible)
1137
+
1138
+ JSON.stringify(user); // { "id": 1, "name": "Alice", "createdAt": "..." }
1139
+ // email is excluded from serialization
1140
+
1141
+ user.$unsafe(); // { id, name, createdAt, email } -- escape hatch
1142
+ ```
1143
+
1144
+ The `reveal` keyword also works on nested relations:
1145
+
1146
+ ```ts
1147
+ const users = await publicApi.user.findMany({
1148
+ include: {
1149
+ posts: { reveal: { content: true } },
1150
+ },
1151
+ });
1152
+ // posts[0].content is accessible but excluded from JSON.stringify
1153
+ ```
1154
+
1155
+ ### Type safety
1156
+
1157
+ The view system is fully type-safe at compile time:
1158
+
1159
+ ```ts
1160
+ const view = db.defineView({
1161
+ name: "restricted",
1162
+ definition: { user: { id: true, email: true } },
1163
+ });
1164
+
1165
+ // select only allows view fields
1166
+ await view.user.findMany({ select: { id: true } }); // OK
1167
+ await view.user.findMany({ select: { role: true } }); // Type error -- role not in view
1168
+
1169
+ // reveal only allows non-view fields
1170
+ await view.user.findMany({ reveal: { name: true } }); // OK
1171
+ await view.user.findMany({ reveal: { id: true } }); // Type error -- id is already in view
1172
+
1173
+ // Write operations are not available
1174
+ await view.user.create({ data: { email: "x" } }); // Type error -- no create on view
1175
+
1176
+ // Models not in the definition are not accessible
1177
+ await view.post.findMany(); // Type error -- post not in view
1178
+ ```
1179
+
1180
+ ---
1181
+
1066
1182
  ## Adapters
1067
1183
 
1068
1184
  ### `@vibeorm/adapter-bun` (recommended)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibeorm",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "CLI for VibeORM — generate clients, run migrations, introspect databases",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -41,10 +41,10 @@
41
41
  "bun": ">=1.1.0"
42
42
  },
43
43
  "dependencies": {
44
- "@vibeorm/parser": "1.1.3",
45
- "@vibeorm/generator": "1.1.4",
46
- "@vibeorm/migrate": "1.1.3",
47
- "@vibeorm/runtime": "1.1.3",
48
- "@vibeorm/adapter-bun": "1.1.3"
44
+ "@vibeorm/parser": "1.1.4",
45
+ "@vibeorm/generator": "1.1.5",
46
+ "@vibeorm/migrate": "1.1.5",
47
+ "@vibeorm/runtime": "1.1.4",
48
+ "@vibeorm/adapter-bun": "1.1.4"
49
49
  }
50
50
  }