@palbase/backend 12.0.0 → 13.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.cjs +71 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +71 -32
- package/dist/index.js.map +1 -1
- package/docs/events.md +5 -1
- package/docs/llms-full.txt +17 -10
- package/docs/resources.md +12 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -320,7 +320,13 @@ function baseTsType(def) {
|
|
|
320
320
|
return "string";
|
|
321
321
|
case "integer":
|
|
322
322
|
return "number";
|
|
323
|
+
// Both are exact-precision in Postgres and lossy as a JSON number, so the
|
|
324
|
+
// database proxy serializes them as strings — measured: 9007199254740993
|
|
325
|
+
// used to arrive as ...992 and 41.00821234567890123 as 41.0082123456789.
|
|
326
|
+
// numeric had no case at all and fell through to `unknown`, which typed
|
|
327
|
+
// every numeric column out of existence.
|
|
323
328
|
case "bigint":
|
|
329
|
+
case "numeric":
|
|
324
330
|
return "string";
|
|
325
331
|
case "boolean":
|
|
326
332
|
return "boolean";
|
|
@@ -839,38 +845,6 @@ function defineFlags(input) {
|
|
|
839
845
|
return { __config: FLAGS_CONFIG_KIND, flags };
|
|
840
846
|
}
|
|
841
847
|
|
|
842
|
-
// src/decorators/controller.ts
|
|
843
|
-
var CONTROLLER_META = /* @__PURE__ */ Symbol.for("palbase.backend.controllerMeta");
|
|
844
|
-
function Controller(basePath, options = {}) {
|
|
845
|
-
return function(ctor) {
|
|
846
|
-
const normalized = basePath.replace(/\/+$/, "");
|
|
847
|
-
if (normalized === "/webhooks" || normalized.startsWith("/webhooks/")) {
|
|
848
|
-
throw new Error(
|
|
849
|
-
`@Controller("${basePath}") uses the reserved /webhooks path \u2014 inbound webhooks are served there`
|
|
850
|
-
);
|
|
851
|
-
}
|
|
852
|
-
const carrier = ctor;
|
|
853
|
-
const meta = {
|
|
854
|
-
__palbase: "controller",
|
|
855
|
-
basePath,
|
|
856
|
-
...options.auth !== void 0 ? { defaultAuth: options.auth } : {}
|
|
857
|
-
};
|
|
858
|
-
Object.defineProperty(carrier, CONTROLLER_META, {
|
|
859
|
-
value: meta,
|
|
860
|
-
enumerable: false,
|
|
861
|
-
configurable: true,
|
|
862
|
-
writable: false
|
|
863
|
-
});
|
|
864
|
-
Object.defineProperty(carrier, "__palbase", {
|
|
865
|
-
value: "controller",
|
|
866
|
-
enumerable: false,
|
|
867
|
-
configurable: true,
|
|
868
|
-
writable: false
|
|
869
|
-
});
|
|
870
|
-
return ctor;
|
|
871
|
-
};
|
|
872
|
-
}
|
|
873
|
-
|
|
874
848
|
// src/decorators/registry.ts
|
|
875
849
|
var ROUTES = /* @__PURE__ */ Symbol.for("palbase.backend.routes");
|
|
876
850
|
var PARAM_BUFFER = /* @__PURE__ */ Symbol.for("palbase.backend.paramBuffer");
|
|
@@ -963,6 +937,48 @@ function getRoutes(ctor) {
|
|
|
963
937
|
}));
|
|
964
938
|
}
|
|
965
939
|
|
|
940
|
+
// src/decorators/controller.ts
|
|
941
|
+
var CONTROLLER_META = /* @__PURE__ */ Symbol.for("palbase.backend.controllerMeta");
|
|
942
|
+
var RESERVED_FIRST_SEGMENT = "webhooks";
|
|
943
|
+
function assertNotReserved(path, subject) {
|
|
944
|
+
const [first] = path.split("/").filter(Boolean);
|
|
945
|
+
if (first === RESERVED_FIRST_SEGMENT) {
|
|
946
|
+
throw new Error(
|
|
947
|
+
`${subject} resolves under the reserved /${RESERVED_FIRST_SEGMENT} path \u2014 inbound webhooks are served there and would shadow this route`
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
function Controller(basePath, options = {}) {
|
|
952
|
+
return function(ctor) {
|
|
953
|
+
assertNotReserved(basePath, `@Controller("${basePath}")`);
|
|
954
|
+
for (const route of getRoutes(ctor)) {
|
|
955
|
+
assertNotReserved(
|
|
956
|
+
`${basePath}${route.subpath}`,
|
|
957
|
+
`@${route.method}("${route.subpath}") in @Controller("${basePath}")`
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
const carrier = ctor;
|
|
961
|
+
const meta = {
|
|
962
|
+
__palbase: "controller",
|
|
963
|
+
basePath,
|
|
964
|
+
...options.auth !== void 0 ? { defaultAuth: options.auth } : {}
|
|
965
|
+
};
|
|
966
|
+
Object.defineProperty(carrier, CONTROLLER_META, {
|
|
967
|
+
value: meta,
|
|
968
|
+
enumerable: false,
|
|
969
|
+
configurable: true,
|
|
970
|
+
writable: false
|
|
971
|
+
});
|
|
972
|
+
Object.defineProperty(carrier, "__palbase", {
|
|
973
|
+
value: "controller",
|
|
974
|
+
enumerable: false,
|
|
975
|
+
configurable: true,
|
|
976
|
+
writable: false
|
|
977
|
+
});
|
|
978
|
+
return ctor;
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
|
|
966
982
|
// src/decorators/methods.ts
|
|
967
983
|
function makeMethodDecorator(method) {
|
|
968
984
|
return function(subpath, options = {}) {
|
|
@@ -1292,6 +1308,29 @@ function getWebhookConfig(ctor) {
|
|
|
1292
1308
|
"@Webhook requires either a `provider` preset or an explicit `signature` \u2014 an endpoint with no verification would accept forged deliveries"
|
|
1293
1309
|
);
|
|
1294
1310
|
}
|
|
1311
|
+
if (meta.provider && meta.signature) {
|
|
1312
|
+
throw new Error(
|
|
1313
|
+
"@Webhook declares BOTH a `provider` preset and an explicit `signature` \u2014 these are alternatives; keep the one that describes the sender, because only `provider` would be used"
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
if (meta.signature) {
|
|
1317
|
+
const sig = meta.signature;
|
|
1318
|
+
if (!sig.header) {
|
|
1319
|
+
throw new Error("@Webhook signature requires `header` \u2014 the header the signature arrives in");
|
|
1320
|
+
}
|
|
1321
|
+
if (sig.algo !== "hmac-sha256" && sig.algo !== "hmac-sha1") {
|
|
1322
|
+
throw new Error(`@Webhook signature has an unsupported algo "${sig.algo}"`);
|
|
1323
|
+
}
|
|
1324
|
+
if (sig.encoding !== "hex" && sig.encoding !== "base64") {
|
|
1325
|
+
throw new Error(`@Webhook signature has an unsupported encoding "${sig.encoding}"`);
|
|
1326
|
+
}
|
|
1327
|
+
if (!sig.signs?.includes("{body}")) {
|
|
1328
|
+
throw new Error("@Webhook signature `signs` must contain {body} \u2014 signing a constant is not a signature");
|
|
1329
|
+
}
|
|
1330
|
+
if (sig.signs.includes("{ts}") && !sig.timestampHeader) {
|
|
1331
|
+
throw new Error("@Webhook signature uses {ts} but declares no `timestampHeader` to read it from");
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1295
1334
|
if (!meta.secret?.env) {
|
|
1296
1335
|
throw new Error('@Webhook requires `secret: { env: "VAR_NAME" }`');
|
|
1297
1336
|
}
|