@palbase/backend 18.0.1 → 21.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.
package/dist/index.js CHANGED
@@ -1217,7 +1217,7 @@ function makeEnvDts(schema) {
1217
1217
  ${blocks.join("\n")}
1218
1218
  ` : "";
1219
1219
  return `// AUTO-GENERATED by @palbase/backend \u2014 DO NOT EDIT.
1220
- // Regenerated from db/schema.ts on every \`palbase db types\` / deploy.
1220
+ // Regenerated from db/schema.ts by \`palbase build\` and by every deploy.
1221
1221
  // Augments the @palbase/backend/env \`Tables\` interface so \`Database.tables.*\`
1222
1222
  // is typed with no import and no generic.
1223
1223
 
@@ -1883,95 +1883,6 @@ var Patch = makeMethodDecorator("PATCH");
1883
1883
  var Delete = makeMethodDecorator("DELETE");
1884
1884
  var Query = makeMethodDecorator("QUERY");
1885
1885
 
1886
- // src/decorators/upload.ts
1887
- function Upload(subpath, config) {
1888
- const { auth: auth2, rateLimit, ...uploadConfig } = config;
1889
- validateUploadConfigShape(uploadConfig);
1890
- const options = {
1891
- uploadConfig,
1892
- ...auth2 !== void 0 ? { auth: auth2 } : {},
1893
- ...rateLimit !== void 0 ? { rateLimit } : {}
1894
- };
1895
- return function(target, propertyKey) {
1896
- recordRoute(target, String(propertyKey), "POST", subpath, options);
1897
- };
1898
- }
1899
- function UploadedObject() {
1900
- return function(target, propertyKey, parameterIndex) {
1901
- recordParam(target, String(propertyKey), {
1902
- index: parameterIndex,
1903
- kind: "uploadedObject"
1904
- });
1905
- };
1906
- }
1907
- function validateUploadConfigShape(c) {
1908
- if (c === null || typeof c !== "object") {
1909
- throw new Error("@Upload config must be an object { bucket, pathTemplate, ... }");
1910
- }
1911
- if (typeof c.bucket !== "string" || c.bucket.length === 0) {
1912
- throw new Error("@Upload config.bucket must be a non-empty bucket name");
1913
- }
1914
- if (typeof c.pathTemplate !== "string" || c.pathTemplate.length === 0) {
1915
- throw new Error("@Upload config.pathTemplate must be a non-empty key template");
1916
- }
1917
- }
1918
- function validateUploadAgainstStorage(uploadConfig, storage2, routeLabel) {
1919
- const def = storage2.buckets[uploadConfig.bucket];
1920
- if (def === void 0) {
1921
- const known = Object.keys(storage2.buckets);
1922
- throw new Error(
1923
- `@Upload route ${routeLabel} targets bucket "${uploadConfig.bucket}" which is not declared in defineStorage(...). ` + (known.length ? `Known buckets: ${known.join(", ")}.` : "No buckets are declared.")
1924
- );
1925
- }
1926
- }
1927
-
1928
- // src/decorators/params.ts
1929
- function makeParamDecorator(kind, extra) {
1930
- return function(target, propertyKey, parameterIndex) {
1931
- recordParam(target, String(propertyKey), {
1932
- index: parameterIndex,
1933
- kind,
1934
- ...extra?.schema !== void 0 ? { schema: extra.schema } : {},
1935
- ...extra?.name !== void 0 ? { name: extra.name } : {}
1936
- });
1937
- };
1938
- }
1939
- function Body(schema) {
1940
- return makeParamDecorator("body", { schema });
1941
- }
1942
- function QueryParams(schema) {
1943
- return makeParamDecorator("query", { schema });
1944
- }
1945
- function Headers(schema) {
1946
- return makeParamDecorator("headers", schema !== void 0 ? { schema } : void 0);
1947
- }
1948
- function Param(name) {
1949
- return makeParamDecorator("param", { name });
1950
- }
1951
- function User() {
1952
- return makeParamDecorator("user");
1953
- }
1954
- function OptionalUser() {
1955
- return makeParamDecorator("optionalUser");
1956
- }
1957
- function Client() {
1958
- return makeParamDecorator("client");
1959
- }
1960
- function RequestId() {
1961
- return makeParamDecorator("requestId");
1962
- }
1963
- function TraceId() {
1964
- return makeParamDecorator("traceId");
1965
- }
1966
- function Req() {
1967
- return makeParamDecorator("req");
1968
- }
1969
-
1970
- // src/middleware.ts
1971
- function defineMiddleware(fn) {
1972
- return fn;
1973
- }
1974
-
1975
1886
  // src/decorators/webhook.ts
1976
1887
  var WEBHOOK_META = /* @__PURE__ */ Symbol.for("palbase.backend.webhookMeta");
1977
1888
  var WEBHOOK_EVENTS = /* @__PURE__ */ Symbol.for("palbase.backend.webhookEvents");
@@ -2069,6 +1980,147 @@ function getWebhookConfig(ctor) {
2069
1980
  };
2070
1981
  }
2071
1982
 
1983
+ // src/decorators/hook.ts
1984
+ var Deny = class extends Error {
1985
+ constructor(reason) {
1986
+ super(reason);
1987
+ this.name = "Deny";
1988
+ }
1989
+ };
1990
+ var HOOK_BLOCKING = /* @__PURE__ */ Symbol.for("palbase.backend.hookBlocking");
1991
+ function Hook(event) {
1992
+ return function(target, fnName) {
1993
+ const carrier = target.constructor;
1994
+ const existing = carrier[HOOK_BLOCKING];
1995
+ const entries = existing ? [...existing] : [];
1996
+ entries.push({ event, fnName: String(fnName) });
1997
+ Object.defineProperty(carrier, HOOK_BLOCKING, {
1998
+ value: entries,
1999
+ enumerable: false,
2000
+ configurable: true,
2001
+ writable: false
2002
+ });
2003
+ };
2004
+ }
2005
+ function bind(instance, entries, kind) {
2006
+ const out = /* @__PURE__ */ Object.create(null);
2007
+ for (const entry of entries) {
2008
+ if (Object.prototype.hasOwnProperty.call(out, entry.event)) {
2009
+ throw new Error(`${kind}("${entry.event}") declared twice on the same hook class`);
2010
+ }
2011
+ const fn = instance[entry.fnName];
2012
+ if (typeof fn !== "function") {
2013
+ throw new Error(`${kind}("${entry.event}") names no method "${entry.fnName}" on the class`);
2014
+ }
2015
+ out[entry.event] = (event, meta) => fn.call(instance, event, meta);
2016
+ }
2017
+ return out;
2018
+ }
2019
+ function getHookConfig(ctor) {
2020
+ const carrier = ctor;
2021
+ const blockingEntries = carrier[HOOK_BLOCKING] ?? [];
2022
+ const listenerEntries = carrier[WEBHOOK_EVENTS] ?? [];
2023
+ if (blockingEntries.length === 0 && listenerEntries.length === 0) {
2024
+ throw new Error(
2025
+ `${ctor.name ?? "a hook class"} carries no handler \u2014 a hook file must declare at least one @Hook (blocking) or @On (listener) method`
2026
+ );
2027
+ }
2028
+ const instance = new ctor();
2029
+ return {
2030
+ blocking: bind(instance, blockingEntries, "@Hook"),
2031
+ listeners: bind(instance, listenerEntries, "@On")
2032
+ };
2033
+ }
2034
+
2035
+ // src/decorators/upload.ts
2036
+ function Upload(subpath, config) {
2037
+ const { auth, rateLimit, ...uploadConfig } = config;
2038
+ validateUploadConfigShape(uploadConfig);
2039
+ const options = {
2040
+ uploadConfig,
2041
+ ...auth !== void 0 ? { auth } : {},
2042
+ ...rateLimit !== void 0 ? { rateLimit } : {}
2043
+ };
2044
+ return function(target, propertyKey) {
2045
+ recordRoute(target, String(propertyKey), "POST", subpath, options);
2046
+ };
2047
+ }
2048
+ function UploadedObject() {
2049
+ return function(target, propertyKey, parameterIndex) {
2050
+ recordParam(target, String(propertyKey), {
2051
+ index: parameterIndex,
2052
+ kind: "uploadedObject"
2053
+ });
2054
+ };
2055
+ }
2056
+ function validateUploadConfigShape(c) {
2057
+ if (c === null || typeof c !== "object") {
2058
+ throw new Error("@Upload config must be an object { bucket, pathTemplate, ... }");
2059
+ }
2060
+ if (typeof c.bucket !== "string" || c.bucket.length === 0) {
2061
+ throw new Error("@Upload config.bucket must be a non-empty bucket name");
2062
+ }
2063
+ if (typeof c.pathTemplate !== "string" || c.pathTemplate.length === 0) {
2064
+ throw new Error("@Upload config.pathTemplate must be a non-empty key template");
2065
+ }
2066
+ }
2067
+ function validateUploadAgainstStorage(uploadConfig, storage, routeLabel) {
2068
+ const def = storage.buckets[uploadConfig.bucket];
2069
+ if (def === void 0) {
2070
+ const known = Object.keys(storage.buckets);
2071
+ throw new Error(
2072
+ `@Upload route ${routeLabel} targets bucket "${uploadConfig.bucket}" which is not declared in defineStorage(...). ` + (known.length ? `Known buckets: ${known.join(", ")}.` : "No buckets are declared.")
2073
+ );
2074
+ }
2075
+ }
2076
+
2077
+ // src/decorators/params.ts
2078
+ function makeParamDecorator(kind, extra) {
2079
+ return function(target, propertyKey, parameterIndex) {
2080
+ recordParam(target, String(propertyKey), {
2081
+ index: parameterIndex,
2082
+ kind,
2083
+ ...extra?.schema !== void 0 ? { schema: extra.schema } : {},
2084
+ ...extra?.name !== void 0 ? { name: extra.name } : {}
2085
+ });
2086
+ };
2087
+ }
2088
+ function Body(schema) {
2089
+ return makeParamDecorator("body", { schema });
2090
+ }
2091
+ function QueryParams(schema) {
2092
+ return makeParamDecorator("query", { schema });
2093
+ }
2094
+ function Headers(schema) {
2095
+ return makeParamDecorator("headers", schema !== void 0 ? { schema } : void 0);
2096
+ }
2097
+ function Param(name) {
2098
+ return makeParamDecorator("param", { name });
2099
+ }
2100
+ function User() {
2101
+ return makeParamDecorator("user");
2102
+ }
2103
+ function OptionalUser() {
2104
+ return makeParamDecorator("optionalUser");
2105
+ }
2106
+ function Client() {
2107
+ return makeParamDecorator("client");
2108
+ }
2109
+ function RequestId() {
2110
+ return makeParamDecorator("requestId");
2111
+ }
2112
+ function TraceId() {
2113
+ return makeParamDecorator("traceId");
2114
+ }
2115
+ function Req() {
2116
+ return makeParamDecorator("req");
2117
+ }
2118
+
2119
+ // src/middleware.ts
2120
+ function defineMiddleware(fn) {
2121
+ return fn;
2122
+ }
2123
+
2072
2124
  // src/job.ts
2073
2125
  function validateCronExpression(expression) {
2074
2126
  const trimmed = expression.trim();
@@ -2139,6 +2191,8 @@ function validateCronField(field, name, min, max) {
2139
2191
  // src/decorators/job.ts
2140
2192
  var DEFAULT_TIMEOUT_SECONDS = 30;
2141
2193
  var MAX_TIMEOUT_SECONDS = 300;
2194
+ var DEFAULT_RETRY = 5;
2195
+ var MAX_RETRY = 10;
2142
2196
  var JOB_META = /* @__PURE__ */ Symbol.for("palbase.backend.jobMeta");
2143
2197
  function Job(options) {
2144
2198
  return function(ctor) {
@@ -2179,12 +2233,19 @@ function getJobConfig(ctor) {
2179
2233
  if (timeout > MAX_TIMEOUT_SECONDS) {
2180
2234
  throw new Error(`@Job \`timeout\` exceeds the ${MAX_TIMEOUT_SECONDS}s sandbox ceiling`);
2181
2235
  }
2236
+ const retry = meta.retry ?? DEFAULT_RETRY;
2237
+ if (!Number.isInteger(retry) || retry < 0) {
2238
+ throw new Error("@Job `retry` must be a whole number of attempts, zero or more");
2239
+ }
2240
+ if (retry > MAX_RETRY) {
2241
+ throw new Error(`@Job \`retry\` exceeds the ceiling of ${MAX_RETRY}`);
2242
+ }
2182
2243
  const instance = new ctor();
2183
2244
  if (typeof instance.run !== "function") {
2184
2245
  throw new Error("@Job class must declare an async run() method");
2185
2246
  }
2186
2247
  const run = instance.run.bind(instance);
2187
- return { schedule: meta.schedule, timeout, handler: run };
2248
+ return { schedule: meta.schedule, timeout, retry, handler: run };
2188
2249
  }
2189
2250
 
2190
2251
  // src/resource.ts
@@ -2233,41 +2294,6 @@ async function __shutdownResources() {
2233
2294
  registry.length = 0;
2234
2295
  }
2235
2296
 
2236
- // src/hooks.ts
2237
- var auth = {
2238
- onUserCreated(handler) {
2239
- return { module: "auth", event: "user.created", handler };
2240
- },
2241
- onSignIn(handler) {
2242
- return { module: "auth", event: "user.sign_in", handler };
2243
- },
2244
- onSignOut(handler) {
2245
- return { module: "auth", event: "user.sign_out", handler };
2246
- },
2247
- onPasswordReset(handler) {
2248
- return { module: "auth", event: "user.password_reset", handler };
2249
- }
2250
- };
2251
- var storage = {
2252
- onFileUploaded(handler) {
2253
- return { module: "storage", event: "file.uploaded", handler };
2254
- },
2255
- onFileDeleted(handler) {
2256
- return { module: "storage", event: "file.deleted", handler };
2257
- }
2258
- };
2259
- var documents = {
2260
- onDocumentCreated(handler) {
2261
- return { module: "documents", event: "document.created", handler };
2262
- },
2263
- onDocumentUpdated(handler) {
2264
- return { module: "documents", event: "document.updated", handler };
2265
- },
2266
- onDocumentDeleted(handler) {
2267
- return { module: "documents", event: "document.deleted", handler };
2268
- }
2269
- };
2270
-
2271
2297
  // src/index.ts
2272
2298
  import { z } from "zod";
2273
2299
  export {
@@ -2280,6 +2306,7 @@ export {
2280
2306
  DEFAULT_TEMPLATE_LOCALE,
2281
2307
  Database,
2282
2308
  Delete,
2309
+ Deny,
2283
2310
  Documents,
2284
2311
  EGRESS_CONFIG_KIND,
2285
2312
  EGRESS_TIMEOUT_DEFAULT_MS,
@@ -2291,6 +2318,7 @@ export {
2291
2318
  Forbidden,
2292
2319
  Get,
2293
2320
  Headers,
2321
+ Hook,
2294
2322
  HttpError,
2295
2323
  Job,
2296
2324
  Log,
@@ -2340,7 +2368,6 @@ export {
2340
2368
  __runWithRuntime,
2341
2369
  __setRuntime,
2342
2370
  __shutdownResources,
2343
- auth,
2344
2371
  bigint,
2345
2372
  boolean,
2346
2373
  bucket,
@@ -2356,12 +2383,12 @@ export {
2356
2383
  defineSecrets,
2357
2384
  defineStorage,
2358
2385
  defineTestUsers,
2359
- documents,
2360
2386
  entitlementFor,
2361
2387
  enumType,
2362
2388
  extractVariables,
2363
2389
  flag,
2364
2390
  getErrorRegistry,
2391
+ getHookConfig,
2365
2392
  getJobConfig,
2366
2393
  getRegisteredControllers,
2367
2394
  getRoutes,
@@ -2383,7 +2410,6 @@ export {
2383
2410
  reservedSecretKey,
2384
2411
  secret,
2385
2412
  spendFor,
2386
- storage,
2387
2413
  testUser,
2388
2414
  text,
2389
2415
  timestamp,