@palbase/backend 3.0.0 → 5.0.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.
Files changed (41) hide show
  1. package/dist/{chunk-B7EUJP5W.js → chunk-2N4YNN6F.js} +113 -3
  2. package/dist/chunk-2N4YNN6F.js.map +1 -0
  3. package/dist/{chunk-PHAFZGHN.js → chunk-WUQO76NW.js} +26 -19
  4. package/dist/chunk-WUQO76NW.js.map +1 -0
  5. package/dist/db/index.cjs +117 -2
  6. package/dist/db/index.cjs.map +1 -1
  7. package/dist/db/index.d.cts +2 -2
  8. package/dist/db/index.d.ts +2 -2
  9. package/dist/db/index.js +11 -1
  10. package/dist/{endpoint-DJ98tQd6.d.cts → endpoint-BEHjfvFH.d.cts} +99 -57
  11. package/dist/{endpoint-DJ98tQd6.d.ts → endpoint-BEHjfvFH.d.ts} +99 -57
  12. package/dist/index-BTVdhfsb.d.ts +469 -0
  13. package/dist/index-mr3Co63T.d.cts +469 -0
  14. package/dist/index.cjs +356 -42
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +80 -219
  17. package/dist/index.d.ts +80 -219
  18. package/dist/index.js +203 -21
  19. package/dist/index.js.map +1 -1
  20. package/dist/test/index.cjs +34 -19
  21. package/dist/test/index.cjs.map +1 -1
  22. package/dist/test/index.d.cts +1 -1
  23. package/dist/test/index.d.ts +1 -1
  24. package/dist/test/index.js +10 -2
  25. package/dist/test/index.js.map +1 -1
  26. package/docs/README.md +212 -14
  27. package/docs/database.md +40 -0
  28. package/docs/endpoints.md +110 -92
  29. package/docs/errors.md +37 -30
  30. package/docs/getting-started.md +64 -26
  31. package/docs/llms-full.txt +724 -312
  32. package/docs/llms.txt +1 -1
  33. package/docs/migrations.md +75 -73
  34. package/docs/routing.md +39 -45
  35. package/docs/schema.md +135 -23
  36. package/docs/services.md +13 -10
  37. package/package.json +2 -2
  38. package/dist/chunk-B7EUJP5W.js.map +0 -1
  39. package/dist/chunk-PHAFZGHN.js.map +0 -1
  40. package/dist/index-CXUs9iTQ.d.ts +0 -294
  41. package/dist/index-CZAwpQE1.d.cts +0 -294
package/dist/index.cjs CHANGED
@@ -20,16 +20,42 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
+ BadRequest: () => BadRequest,
24
+ Body: () => Body,
23
25
  Cache: () => Cache,
26
+ Client: () => Client,
27
+ Conflict: () => Conflict,
28
+ Controller: () => Controller,
24
29
  Database: () => Database,
30
+ Delete: () => Delete,
25
31
  Documents: () => Documents,
32
+ EXTENSION_DEPENDENCIES: () => EXTENSION_DEPENDENCIES,
26
33
  Flags: () => Flags,
34
+ Forbidden: () => Forbidden,
35
+ Get: () => Get,
36
+ Headers: () => Headers,
27
37
  HttpError: () => HttpError,
28
38
  Log: () => Log,
39
+ NotFound: () => NotFound,
29
40
  Notifications: () => Notifications,
41
+ OptionalUser: () => OptionalUser,
42
+ PALBASE_EXTENSIONS: () => PALBASE_EXTENSIONS,
43
+ PalError: () => PalError,
44
+ Param: () => Param,
45
+ Patch: () => Patch,
46
+ PolicyBuilder: () => PolicyBuilder,
47
+ Post: () => Post,
48
+ Put: () => Put,
49
+ Query: () => Query,
30
50
  Queue: () => Queue,
51
+ Req: () => Req,
52
+ RequestId: () => RequestId,
31
53
  Resource: () => Resource,
32
54
  Storage: () => Storage,
55
+ TooManyRequests: () => TooManyRequests,
56
+ TraceId: () => TraceId,
57
+ Unauthorized: () => Unauthorized,
58
+ User: () => User,
33
59
  __getRuntime: () => __getRuntime,
34
60
  __registerResource: () => __registerResource,
35
61
  __requestALS: () => __requestALS,
@@ -39,8 +65,6 @@ __export(src_exports, {
39
65
  __shutdownResources: () => __shutdownResources,
40
66
  auth: () => auth,
41
67
  boolean: () => boolean,
42
- defineController: () => defineController,
43
- defineHandler: () => defineHandler,
44
68
  defineJob: () => defineJob,
45
69
  defineMiddleware: () => defineMiddleware,
46
70
  defineSchema: () => defineSchema,
@@ -49,10 +73,11 @@ __export(src_exports, {
49
73
  documents: () => documents,
50
74
  enumType: () => enumType,
51
75
  integer: () => integer,
76
+ isPalbaseExtension: () => isPalbaseExtension,
52
77
  jsonb: () => jsonb,
53
78
  makeEnvDts: () => makeEnvDts,
54
79
  makeTypedDB: () => makeTypedDB,
55
- route: () => route,
80
+ policy: () => policy,
56
81
  storage: () => storage,
57
82
  text: () => text,
58
83
  timestamp: () => timestamp,
@@ -111,27 +136,34 @@ function makeTablesAccessor(ops) {
111
136
  return tablesProxy;
112
137
  }
113
138
  var rawDatabase = makeServiceProxy("Database");
114
- var Database = Object.assign(
115
- // Spread the raw ops onto a fresh object so the added `tables`/typed
116
- // `transaction` members live alongside them. Each op still forwards through
117
- // the request-scoped runtime Proxy.
118
- {
119
- query: (sql, params) => rawDatabase.query(sql, params),
120
- insert: (table, data) => rawDatabase.insert(table, data),
121
- update: (table, id, data) => rawDatabase.update(table, id, data),
122
- delete: (table, id) => rawDatabase.delete(table, id),
123
- findById: (table, id) => rawDatabase.findById(table, id),
124
- findMany: (table, query) => rawDatabase.findMany(table, query)
125
- },
126
- {
127
- tables: makeTablesAccessor(() => rawDatabase),
139
+ function makeTypedSurface(raw) {
140
+ const ops = {
141
+ query: (sql, params) => raw.query(sql, params),
142
+ insert: (table, data) => raw.insert(table, data),
143
+ update: (table, id, data) => raw.update(table, id, data),
144
+ delete: (table, id) => raw.delete(table, id),
145
+ findById: (table, id) => raw.findById(table, id),
146
+ findMany: (table, query) => raw.findMany(table, query)
147
+ };
148
+ return Object.assign(ops, {
149
+ tables: makeTablesAccessor(() => raw),
128
150
  transaction(fn) {
129
- return rawDatabase.transaction(
130
- (rawTx) => fn({ tables: makeTablesAccessor(() => rawTx) })
131
- );
151
+ return raw.transaction((rawTx) => fn({ tables: makeTablesAccessor(() => rawTx) }));
132
152
  }
153
+ });
154
+ }
155
+ var Database = Object.assign(makeTypedSurface(rawDatabase), {
156
+ /**
157
+ * Lazily resolve the runtime's service-role sibling on each call. We do NOT
158
+ * cache it: `rawDatabase.asService()` reads the CURRENT request scope through
159
+ * the runtime proxy, and the per-request runtime injects a service client
160
+ * bound to that request's identity headers — caching would leak one request's
161
+ * sibling into another concurrent request.
162
+ */
163
+ asService() {
164
+ return makeTypedSurface(rawDatabase.asService());
133
165
  }
134
- );
166
+ });
135
167
  var Documents = makeServiceProxy("Documents");
136
168
  var Storage = makeServiceProxy("Storage");
137
169
  var Cache = makeServiceProxy("Cache");
@@ -140,13 +172,118 @@ var Log = makeServiceProxy("Log");
140
172
  var Notifications = makeServiceProxy("Notifications");
141
173
  var Flags = makeServiceProxy("Flags");
142
174
 
175
+ // src/db/policy.ts
176
+ var PolicyBuilder = class {
177
+ _def;
178
+ constructor(name) {
179
+ this._def = {
180
+ name,
181
+ command: "all",
182
+ roles: ["authenticated"],
183
+ using: null,
184
+ withCheck: null,
185
+ permissive: true
186
+ };
187
+ }
188
+ /** Restrict the policy to a single SQL command (default `"all"`). */
189
+ for(command) {
190
+ this._def.command = command;
191
+ return this;
192
+ }
193
+ /**
194
+ * Set the DB roles the policy applies to (the `TO` clause), replacing any
195
+ * previously-set roles. Call with no arguments to target PUBLIC (all roles).
196
+ *
197
+ * @example
198
+ * policy("p").to("authenticated")
199
+ * policy("p").to("authenticated", "service_role")
200
+ * policy("p").to() // PUBLIC
201
+ */
202
+ to(...roles) {
203
+ this._def.roles = roles;
204
+ return this;
205
+ }
206
+ /** Set the `USING (...)` row-visibility expression (raw SQL). */
207
+ using(sqlExpr) {
208
+ this._def.using = sqlExpr;
209
+ return this;
210
+ }
211
+ /** Set the `WITH CHECK (...)` write-validation expression (raw SQL). */
212
+ withCheck(sqlExpr) {
213
+ this._def.withCheck = sqlExpr;
214
+ return this;
215
+ }
216
+ /** Set the policy mode: `"permissive"` (default, OR-combined) or
217
+ * `"restrictive"` (AND-combined). */
218
+ as(mode) {
219
+ this._def.permissive = mode === "permissive";
220
+ return this;
221
+ }
222
+ };
223
+ function policy(name) {
224
+ return new PolicyBuilder(name);
225
+ }
226
+
143
227
  // src/db/schema.ts
228
+ function toPolicyDef(p) {
229
+ return p instanceof PolicyBuilder ? p._def : p;
230
+ }
144
231
  function defineSchema(input) {
145
232
  const tables = {};
146
233
  for (const name of Object.keys(input.tables)) {
147
- tables[name] = { name, columns: input.tables[name] };
234
+ const table = input.tables[name];
235
+ if (table === void 0) continue;
236
+ const policies = (table.policies ?? []).map(toPolicyDef);
237
+ const rls = table.rls === true || policies.length > 0;
238
+ tables[name] = {
239
+ name,
240
+ columns: table.columns,
241
+ rls,
242
+ policies
243
+ };
148
244
  }
149
- return { tables };
245
+ const extensions = [...new Set(input.extensions ?? [])];
246
+ return { tables, extensions };
247
+ }
248
+
249
+ // src/db/extensions.ts
250
+ var PALBASE_EXTENSIONS = [
251
+ // Search & text
252
+ "vector",
253
+ // pgvector: AI embeddings + vector similarity search (semantic search / RAG).
254
+ // NB: the Postgres extension is named "vector", not "pgvector" — declare "vector".
255
+ "pg_trgm",
256
+ // trigram fuzzy / typo-tolerant text search
257
+ "unaccent",
258
+ // accent-insensitive text search
259
+ "citext",
260
+ // case-insensitive text type
261
+ // Geospatial / location
262
+ "postgis",
263
+ // geospatial types + queries (maps, "near me")
264
+ "cube",
265
+ // multi-dimensional cubes (dependency of earthdistance)
266
+ "earthdistance",
267
+ // great-circle distance (needs cube)
268
+ // Data types & structures
269
+ "hstore",
270
+ // key/value pairs in a single column
271
+ "ltree",
272
+ // hierarchical tree-structured labels
273
+ // Scheduling
274
+ "pg_cron",
275
+ // schedule jobs inside the database
276
+ // Crypto / ids (also installed by default; listable for explicitness)
277
+ "pgcrypto",
278
+ // cryptographic functions (hashing, encryption)
279
+ "uuid-ossp"
280
+ // UUID generation functions
281
+ ];
282
+ var EXTENSION_DEPENDENCIES = {
283
+ earthdistance: ["cube"]
284
+ };
285
+ function isPalbaseExtension(name) {
286
+ return PALBASE_EXTENSIONS.includes(name);
150
287
  }
151
288
 
152
289
  // src/db/columns.ts
@@ -322,26 +459,132 @@ export {};
322
459
  `;
323
460
  }
324
461
 
325
- // src/handler.ts
326
- function defineHandler(config) {
327
- return { __palbase: "handler", ...config };
462
+ // src/decorators/controller.ts
463
+ var CONTROLLER_META = /* @__PURE__ */ Symbol.for("palbase.backend.controllerMeta");
464
+ function Controller(basePath, options = {}) {
465
+ return function(ctor) {
466
+ const carrier = ctor;
467
+ const meta = {
468
+ __palbase: "controller",
469
+ basePath,
470
+ ...options.auth !== void 0 ? { defaultAuth: options.auth } : {}
471
+ };
472
+ Object.defineProperty(carrier, CONTROLLER_META, {
473
+ value: meta,
474
+ enumerable: false,
475
+ configurable: true,
476
+ writable: false
477
+ });
478
+ Object.defineProperty(carrier, "__palbase", {
479
+ value: "controller",
480
+ enumerable: false,
481
+ configurable: true,
482
+ writable: false
483
+ });
484
+ return ctor;
485
+ };
328
486
  }
329
487
 
330
- // src/controller.ts
331
- function makeRoute(method) {
332
- return function(path, handler) {
333
- return { __palbase: "route", method, path, handler };
488
+ // src/decorators/registry.ts
489
+ var ROUTES = /* @__PURE__ */ Symbol.for("palbase.backend.routes");
490
+ var PARAM_BUFFER = /* @__PURE__ */ Symbol.for("palbase.backend.paramBuffer");
491
+ var RETURN_BUFFER = /* @__PURE__ */ Symbol.for("palbase.backend.returnBuffer");
492
+ function carrierOf(target) {
493
+ const ctor = typeof target === "function" ? target : target.constructor ?? target;
494
+ return ctor;
495
+ }
496
+ function ownRoutes(carrier) {
497
+ if (!Object.prototype.hasOwnProperty.call(carrier, ROUTES)) {
498
+ carrier[ROUTES] = [];
499
+ }
500
+ return carrier[ROUTES];
501
+ }
502
+ function ownParamBuffer(carrier) {
503
+ if (!Object.prototype.hasOwnProperty.call(carrier, PARAM_BUFFER)) {
504
+ carrier[PARAM_BUFFER] = {};
505
+ }
506
+ return carrier[PARAM_BUFFER];
507
+ }
508
+ function recordRoute(target, fnName, method, subpath, options) {
509
+ const carrier = carrierOf(target);
510
+ const routes = ownRoutes(carrier);
511
+ const buffer = ownParamBuffer(carrier);
512
+ const params = (buffer[fnName] ?? []).slice().sort((a, b) => a.index - b.index);
513
+ const route = { method, subpath, fnName, options, params };
514
+ const returnBuffer = carrier[RETURN_BUFFER];
515
+ if (returnBuffer && returnBuffer[fnName] !== void 0) {
516
+ route.returnSchema = returnBuffer[fnName];
517
+ }
518
+ routes.push(route);
519
+ }
520
+ function recordParam(target, fnName, meta) {
521
+ const carrier = carrierOf(target);
522
+ const buffer = ownParamBuffer(carrier);
523
+ (buffer[fnName] ??= []).push(meta);
524
+ const routes = carrier[ROUTES];
525
+ if (routes) {
526
+ const route = routes.find((r) => r.fnName === fnName);
527
+ if (route) {
528
+ route.params.push(meta);
529
+ route.params.sort((a, b) => a.index - b.index);
530
+ }
531
+ }
532
+ }
533
+
534
+ // src/decorators/methods.ts
535
+ function makeMethodDecorator(method) {
536
+ return function(subpath, options = {}) {
537
+ return function(target, propertyKey) {
538
+ recordRoute(target, String(propertyKey), method, subpath, options);
539
+ };
334
540
  };
335
541
  }
336
- var route = {
337
- get: makeRoute("GET"),
338
- post: makeRoute("POST"),
339
- put: makeRoute("PUT"),
340
- patch: makeRoute("PATCH"),
341
- delete: makeRoute("DELETE")
342
- };
343
- function defineController(basePath, routes) {
344
- return { __palbase: "controller", basePath, routes };
542
+ var Get = makeMethodDecorator("GET");
543
+ var Post = makeMethodDecorator("POST");
544
+ var Put = makeMethodDecorator("PUT");
545
+ var Patch = makeMethodDecorator("PATCH");
546
+ var Delete = makeMethodDecorator("DELETE");
547
+
548
+ // src/decorators/params.ts
549
+ function makeParamDecorator(kind, extra) {
550
+ return function(target, propertyKey, parameterIndex) {
551
+ recordParam(target, String(propertyKey), {
552
+ index: parameterIndex,
553
+ kind,
554
+ ...extra?.schema !== void 0 ? { schema: extra.schema } : {},
555
+ ...extra?.name !== void 0 ? { name: extra.name } : {}
556
+ });
557
+ };
558
+ }
559
+ function Body(schema) {
560
+ return makeParamDecorator("body", { schema });
561
+ }
562
+ function Query(schema) {
563
+ return makeParamDecorator("query", { schema });
564
+ }
565
+ function Headers(schema) {
566
+ return makeParamDecorator("headers", schema !== void 0 ? { schema } : void 0);
567
+ }
568
+ function Param(name) {
569
+ return makeParamDecorator("param", { name });
570
+ }
571
+ function User() {
572
+ return makeParamDecorator("user");
573
+ }
574
+ function OptionalUser() {
575
+ return makeParamDecorator("optionalUser");
576
+ }
577
+ function Client() {
578
+ return makeParamDecorator("client");
579
+ }
580
+ function RequestId() {
581
+ return makeParamDecorator("requestId");
582
+ }
583
+ function TraceId() {
584
+ return makeParamDecorator("traceId");
585
+ }
586
+ function Req() {
587
+ return makeParamDecorator("req");
345
588
  }
346
589
 
347
590
  // src/middleware.ts
@@ -386,6 +629,52 @@ var HttpError = class extends Error {
386
629
  return result;
387
630
  }
388
631
  };
632
+ var PalError = class extends HttpError {
633
+ constructor(status, code, description, data) {
634
+ super(status, code, description, data);
635
+ this.name = "PalError";
636
+ }
637
+ };
638
+ var NamedHttpError = class extends HttpError {
639
+ constructor(status, defaultCode, name, message, code, data) {
640
+ super(status, code ?? defaultCode, message ?? defaultMessage(name), data);
641
+ this.name = name;
642
+ }
643
+ };
644
+ function defaultMessage(name) {
645
+ const spaced = name.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
646
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
647
+ }
648
+ var BadRequest = class extends NamedHttpError {
649
+ constructor(message, code, data) {
650
+ super(400, "bad_request", "BadRequest", message, code, data);
651
+ }
652
+ };
653
+ var Unauthorized = class extends NamedHttpError {
654
+ constructor(message, code, data) {
655
+ super(401, "unauthorized", "Unauthorized", message, code, data);
656
+ }
657
+ };
658
+ var Forbidden = class extends NamedHttpError {
659
+ constructor(message, code, data) {
660
+ super(403, "forbidden", "Forbidden", message, code, data);
661
+ }
662
+ };
663
+ var NotFound = class extends NamedHttpError {
664
+ constructor(message, code, data) {
665
+ super(404, "not_found", "NotFound", message, code, data);
666
+ }
667
+ };
668
+ var Conflict = class extends NamedHttpError {
669
+ constructor(message, code, data) {
670
+ super(409, "conflict", "Conflict", message, code, data);
671
+ }
672
+ };
673
+ var TooManyRequests = class extends NamedHttpError {
674
+ constructor(message, code, data) {
675
+ super(429, "too_many_requests", "TooManyRequests", message, code, data);
676
+ }
677
+ };
389
678
 
390
679
  // src/worker.ts
391
680
  var VALID_WORKER_NAME = /^[a-zA-Z0-9_-]+$/;
@@ -688,16 +977,42 @@ var documents = {
688
977
  var import_zod = require("zod");
689
978
  // Annotate the CommonJS export names for ESM import in node:
690
979
  0 && (module.exports = {
980
+ BadRequest,
981
+ Body,
691
982
  Cache,
983
+ Client,
984
+ Conflict,
985
+ Controller,
692
986
  Database,
987
+ Delete,
693
988
  Documents,
989
+ EXTENSION_DEPENDENCIES,
694
990
  Flags,
991
+ Forbidden,
992
+ Get,
993
+ Headers,
695
994
  HttpError,
696
995
  Log,
996
+ NotFound,
697
997
  Notifications,
998
+ OptionalUser,
999
+ PALBASE_EXTENSIONS,
1000
+ PalError,
1001
+ Param,
1002
+ Patch,
1003
+ PolicyBuilder,
1004
+ Post,
1005
+ Put,
1006
+ Query,
698
1007
  Queue,
1008
+ Req,
1009
+ RequestId,
699
1010
  Resource,
700
1011
  Storage,
1012
+ TooManyRequests,
1013
+ TraceId,
1014
+ Unauthorized,
1015
+ User,
701
1016
  __getRuntime,
702
1017
  __registerResource,
703
1018
  __requestALS,
@@ -707,8 +1022,6 @@ var import_zod = require("zod");
707
1022
  __shutdownResources,
708
1023
  auth,
709
1024
  boolean,
710
- defineController,
711
- defineHandler,
712
1025
  defineJob,
713
1026
  defineMiddleware,
714
1027
  defineSchema,
@@ -717,10 +1030,11 @@ var import_zod = require("zod");
717
1030
  documents,
718
1031
  enumType,
719
1032
  integer,
1033
+ isPalbaseExtension,
720
1034
  jsonb,
721
1035
  makeEnvDts,
722
1036
  makeTypedDB,
723
- route,
1037
+ policy,
724
1038
  storage,
725
1039
  text,
726
1040
  timestamp,