@palbase/backend 18.0.0 → 20.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/bin/palbase-backend.cjs +36 -17
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +1 -1
- package/dist/{chunk-VYH4U7ZQ.js → chunk-PFQJYW6C.js} +37 -18
- package/dist/chunk-PFQJYW6C.js.map +1 -0
- package/dist/engine/index.cjs +36 -17
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/{index-DZDUMth5.d.ts → index-BeHLq2i-.d.ts} +5 -0
- package/dist/{index-B46CGNvx.d.cts → index-Br9P7yRu.d.cts} +5 -0
- package/dist/index.cjs +189 -129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +190 -121
- package/dist/index.d.ts +190 -121
- package/dist/index.js +178 -121
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/template/package.json +1 -1
- package/dist/chunk-VYH4U7ZQ.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -940,13 +940,13 @@ function buildBucketClient(http, bucketName) {
|
|
|
940
940
|
},
|
|
941
941
|
async remove(paths) {
|
|
942
942
|
for (const p of paths) validateStoragePath(p);
|
|
943
|
-
const
|
|
943
|
+
const removed2 = [];
|
|
944
944
|
for (const p of paths) {
|
|
945
945
|
const res = await http.request("DELETE", objectPath(p));
|
|
946
946
|
if (res.error) return { data: null, error: res.error, status: res.status };
|
|
947
|
-
|
|
947
|
+
removed2.push(toFileObject(bucketName, { path: p }));
|
|
948
948
|
}
|
|
949
|
-
return { data:
|
|
949
|
+
return { data: removed2, error: null, status: 200 };
|
|
950
950
|
},
|
|
951
951
|
async move(from, to) {
|
|
952
952
|
validateStoragePath(from);
|
|
@@ -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
|
|
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: auth2, rateLimit, ...uploadConfig } = config;
|
|
2038
|
+
validateUploadConfigShape(uploadConfig);
|
|
2039
|
+
const options = {
|
|
2040
|
+
uploadConfig,
|
|
2041
|
+
...auth2 !== void 0 ? { auth: auth2 } : {},
|
|
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, storage2, routeLabel) {
|
|
2068
|
+
const def = storage2.buckets[uploadConfig.bucket];
|
|
2069
|
+
if (def === void 0) {
|
|
2070
|
+
const known = Object.keys(storage2.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
|
|
@@ -2234,38 +2295,31 @@ async function __shutdownResources() {
|
|
|
2234
2295
|
}
|
|
2235
2296
|
|
|
2236
2297
|
// src/hooks.ts
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
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 };
|
|
2298
|
+
function removed(helper, decorator, event) {
|
|
2299
|
+
throw new Error(
|
|
2300
|
+
`${helper}() does not register anything and never did \u2014 nothing in the runtime or the bundler reads what it returns, so the handler you passed would never run. Declare it instead in hooks/<name>.ts:
|
|
2301
|
+
|
|
2302
|
+
export default class MyHooks {
|
|
2303
|
+
${decorator}("${event}")
|
|
2304
|
+
async handle(event, meta) { /* \u2026 */ }
|
|
2249
2305
|
}
|
|
2306
|
+
`
|
|
2307
|
+
);
|
|
2308
|
+
}
|
|
2309
|
+
var auth = {
|
|
2310
|
+
onUserCreated: (_h) => removed("auth.onUserCreated", "@Hook", "before.user.create"),
|
|
2311
|
+
onSignIn: (_h) => removed("auth.onSignIn", "@Hook", "before.login"),
|
|
2312
|
+
onSignOut: (_h) => removed("auth.onSignOut", "@On", "after.session.revoke"),
|
|
2313
|
+
onPasswordReset: (_h) => removed("auth.onPasswordReset", "@Hook", "before.password.reset")
|
|
2250
2314
|
};
|
|
2251
2315
|
var storage = {
|
|
2252
|
-
onFileUploaded(
|
|
2253
|
-
|
|
2254
|
-
},
|
|
2255
|
-
onFileDeleted(handler) {
|
|
2256
|
-
return { module: "storage", event: "file.deleted", handler };
|
|
2257
|
-
}
|
|
2316
|
+
onFileUploaded: (_h) => removed("storage.onFileUploaded", "@On", "file.uploaded"),
|
|
2317
|
+
onFileDeleted: (_h) => removed("storage.onFileDeleted", "@On", "file.deleted")
|
|
2258
2318
|
};
|
|
2259
2319
|
var documents = {
|
|
2260
|
-
onDocumentCreated(
|
|
2261
|
-
|
|
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
|
-
}
|
|
2320
|
+
onDocumentCreated: (_h) => removed("documents.onDocumentCreated", "@On", "document.created"),
|
|
2321
|
+
onDocumentUpdated: (_h) => removed("documents.onDocumentUpdated", "@On", "document.updated"),
|
|
2322
|
+
onDocumentDeleted: (_h) => removed("documents.onDocumentDeleted", "@On", "document.deleted")
|
|
2269
2323
|
};
|
|
2270
2324
|
|
|
2271
2325
|
// src/index.ts
|
|
@@ -2280,6 +2334,7 @@ export {
|
|
|
2280
2334
|
DEFAULT_TEMPLATE_LOCALE,
|
|
2281
2335
|
Database,
|
|
2282
2336
|
Delete,
|
|
2337
|
+
Deny,
|
|
2283
2338
|
Documents,
|
|
2284
2339
|
EGRESS_CONFIG_KIND,
|
|
2285
2340
|
EGRESS_TIMEOUT_DEFAULT_MS,
|
|
@@ -2291,6 +2346,7 @@ export {
|
|
|
2291
2346
|
Forbidden,
|
|
2292
2347
|
Get,
|
|
2293
2348
|
Headers,
|
|
2349
|
+
Hook,
|
|
2294
2350
|
HttpError,
|
|
2295
2351
|
Job,
|
|
2296
2352
|
Log,
|
|
@@ -2362,6 +2418,7 @@ export {
|
|
|
2362
2418
|
extractVariables,
|
|
2363
2419
|
flag,
|
|
2364
2420
|
getErrorRegistry,
|
|
2421
|
+
getHookConfig,
|
|
2365
2422
|
getJobConfig,
|
|
2366
2423
|
getRegisteredControllers,
|
|
2367
2424
|
getRoutes,
|