better-call 0.0.0-experimental.01ff4b77

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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/dist/capability.cjs +417 -0
  4. package/dist/capability.cjs.map +1 -0
  5. package/dist/capability.d.cts +189 -0
  6. package/dist/capability.d.mts +189 -0
  7. package/dist/capability.mjs +401 -0
  8. package/dist/capability.mjs.map +1 -0
  9. package/dist/error.cjs +76 -0
  10. package/dist/error.cjs.map +1 -0
  11. package/dist/error.d.cts +51 -0
  12. package/dist/error.d.mts +51 -0
  13. package/dist/error.mjs +72 -0
  14. package/dist/error.mjs.map +1 -0
  15. package/dist/fn.cjs +350 -0
  16. package/dist/fn.cjs.map +1 -0
  17. package/dist/fn.d.cts +378 -0
  18. package/dist/fn.d.mts +378 -0
  19. package/dist/fn.mjs +350 -0
  20. package/dist/fn.mjs.map +1 -0
  21. package/dist/index.cjs +43 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.cts +50 -0
  24. package/dist/index.d.mts +50 -0
  25. package/dist/index.mjs +24 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/module.cjs +176 -0
  28. package/dist/module.cjs.map +1 -0
  29. package/dist/module.d.cts +283 -0
  30. package/dist/module.d.mts +283 -0
  31. package/dist/module.mjs +166 -0
  32. package/dist/module.mjs.map +1 -0
  33. package/dist/plugins/db.cjs +24 -0
  34. package/dist/plugins/db.cjs.map +1 -0
  35. package/dist/plugins/db.d.cts +18 -0
  36. package/dist/plugins/db.d.mts +18 -0
  37. package/dist/plugins/db.mjs +19 -0
  38. package/dist/plugins/db.mjs.map +1 -0
  39. package/dist/plugins/http/attrs.cjs +91 -0
  40. package/dist/plugins/http/attrs.cjs.map +1 -0
  41. package/dist/plugins/http/attrs.d.cts +26 -0
  42. package/dist/plugins/http/attrs.d.mts +26 -0
  43. package/dist/plugins/http/attrs.mjs +87 -0
  44. package/dist/plugins/http/attrs.mjs.map +1 -0
  45. package/dist/plugins/http/cookie.cjs +117 -0
  46. package/dist/plugins/http/cookie.cjs.map +1 -0
  47. package/dist/plugins/http/cookie.d.cts +637 -0
  48. package/dist/plugins/http/cookie.d.mts +637 -0
  49. package/dist/plugins/http/cookie.mjs +113 -0
  50. package/dist/plugins/http/cookie.mjs.map +1 -0
  51. package/dist/plugins/http/error.cjs +39 -0
  52. package/dist/plugins/http/error.cjs.map +1 -0
  53. package/dist/plugins/http/error.d.cts +38 -0
  54. package/dist/plugins/http/error.d.mts +38 -0
  55. package/dist/plugins/http/error.mjs +35 -0
  56. package/dist/plugins/http/error.mjs.map +1 -0
  57. package/dist/plugins/http/handle.cjs +73 -0
  58. package/dist/plugins/http/handle.cjs.map +1 -0
  59. package/dist/plugins/http/handle.d.cts +955 -0
  60. package/dist/plugins/http/handle.d.mts +955 -0
  61. package/dist/plugins/http/handle.mjs +72 -0
  62. package/dist/plugins/http/handle.mjs.map +1 -0
  63. package/dist/plugins/http/redirect.cjs +82 -0
  64. package/dist/plugins/http/redirect.cjs.map +1 -0
  65. package/dist/plugins/http/redirect.d.cts +67 -0
  66. package/dist/plugins/http/redirect.d.mts +67 -0
  67. package/dist/plugins/http/redirect.mjs +79 -0
  68. package/dist/plugins/http/redirect.mjs.map +1 -0
  69. package/dist/plugins/http/request.cjs +63 -0
  70. package/dist/plugins/http/request.cjs.map +1 -0
  71. package/dist/plugins/http/request.d.cts +142 -0
  72. package/dist/plugins/http/request.d.mts +142 -0
  73. package/dist/plugins/http/request.mjs +61 -0
  74. package/dist/plugins/http/request.mjs.map +1 -0
  75. package/dist/plugins/http/response.cjs +13 -0
  76. package/dist/plugins/http/response.cjs.map +1 -0
  77. package/dist/plugins/http/response.d.cts +18 -0
  78. package/dist/plugins/http/response.d.mts +18 -0
  79. package/dist/plugins/http/response.mjs +13 -0
  80. package/dist/plugins/http/response.mjs.map +1 -0
  81. package/dist/plugins/http.cjs +64 -0
  82. package/dist/plugins/http.cjs.map +1 -0
  83. package/dist/plugins/http.d.cts +945 -0
  84. package/dist/plugins/http.d.mts +945 -0
  85. package/dist/plugins/http.mjs +37 -0
  86. package/dist/plugins/http.mjs.map +1 -0
  87. package/dist/plugins/read-only.cjs +19 -0
  88. package/dist/plugins/read-only.cjs.map +1 -0
  89. package/dist/plugins/read-only.d.cts +17 -0
  90. package/dist/plugins/read-only.d.mts +17 -0
  91. package/dist/plugins/read-only.mjs +19 -0
  92. package/dist/plugins/read-only.mjs.map +1 -0
  93. package/dist/schema.cjs +245 -0
  94. package/dist/schema.cjs.map +1 -0
  95. package/dist/schema.d.cts +411 -0
  96. package/dist/schema.d.mts +411 -0
  97. package/dist/schema.mjs +235 -0
  98. package/dist/schema.mjs.map +1 -0
  99. package/dist/scope.d.cts +31 -0
  100. package/dist/scope.d.mts +31 -0
  101. package/dist/storage.cjs +308 -0
  102. package/dist/storage.cjs.map +1 -0
  103. package/dist/storage.d.cts +220 -0
  104. package/dist/storage.d.mts +220 -0
  105. package/dist/storage.mjs +302 -0
  106. package/dist/storage.mjs.map +1 -0
  107. package/dist/types.d.cts +8 -0
  108. package/dist/types.d.mts +8 -0
  109. package/dist/var.cjs +186 -0
  110. package/dist/var.cjs.map +1 -0
  111. package/dist/var.d.cts +46 -0
  112. package/dist/var.d.mts +46 -0
  113. package/dist/var.mjs +177 -0
  114. package/dist/var.mjs.map +1 -0
  115. package/package.json +114 -0
@@ -0,0 +1,91 @@
1
+ const require_error = require("../../error.cjs");
2
+ const require_schema = require("../../schema.cjs");
3
+ //#region src/plugins/http/attrs.ts
4
+ /** Mark a field as unusable over the wire - HTTP / capability edges
5
+ * reject it if present; in-process callers may still pass it. */
6
+ const serverOnly = (schema) => require_schema.withAttrs(schema, "http", { serverOnly: true });
7
+ const isServerOnly = (schema) => require_schema.attrsOf(schema, "http")?.serverOnly === true;
8
+ /**
9
+ * Drop fields (and nested object keys) marked {@link serverOnly}. Used
10
+ * for OpenAPI / client contracts; {@link InferArgs} on the original
11
+ * schema stays the full shape.
12
+ */
13
+ const clientSchema = (schema) => {
14
+ if (require_schema.isVar(schema)) {
15
+ const v = schema;
16
+ return {
17
+ ...schema,
18
+ schema: v.schema === void 0 ? void 0 : clientSchema(v.schema)
19
+ };
20
+ }
21
+ const def = require_schema.asType(schema);
22
+ if (def.name === "object" && def.shape !== void 0) {
23
+ const shape = {};
24
+ for (const [key, child] of Object.entries(def.shape)) {
25
+ if (isServerOnly(child)) continue;
26
+ shape[key] = clientSchema(child);
27
+ }
28
+ return {
29
+ ...def,
30
+ shape
31
+ };
32
+ }
33
+ if (def.name === "array" && def.shape !== void 0) return {
34
+ ...def,
35
+ shape: clientSchema(def.shape)
36
+ };
37
+ if (def.name === "union" && Array.isArray(def.shape)) return {
38
+ ...def,
39
+ shape: def.shape.map((option) => clientSchema(option))
40
+ };
41
+ return schema;
42
+ };
43
+ /**
44
+ * Throw if any {@link serverOnly} field is present on `value` (own key).
45
+ * Object validation otherwise strips unknown keys, so this is what stops
46
+ * wire callers from smuggling server-only values.
47
+ */
48
+ const rejectServerOnly = (schema, value, path = "input") => {
49
+ if (value === null || value === void 0) return;
50
+ const def = require_schema.asType(require_schema.isVar(schema) ? schema.schema ?? {} : schema);
51
+ if (def.name === "object" && def.shape !== void 0) {
52
+ if (require_schema.typeOf(value) !== "object") return;
53
+ const record = value;
54
+ for (const [key, child] of Object.entries(def.shape)) {
55
+ if (isServerOnly(child) && Object.hasOwn(record, key)) throw new require_error.ValidationError(`${path}.${key}`, "server-only field is not allowed over the wire");
56
+ if (Object.hasOwn(record, key)) rejectServerOnly(child, record[key], `${path}.${key}`);
57
+ }
58
+ return;
59
+ }
60
+ if (def.name === "array" && def.shape !== void 0 && Array.isArray(value)) {
61
+ for (let i = 0; i < value.length; i++) rejectServerOnly(def.shape, value[i], `${path}[${i}]`);
62
+ return;
63
+ }
64
+ if (def.name === "union" && Array.isArray(def.shape)) for (const option of def.shape) rejectServerOnly(option, value, path);
65
+ };
66
+ /**
67
+ * Wire-side input gate: reject smuggled server-only keys, then validate
68
+ * against {@link clientSchema}.
69
+ */
70
+ const wireInput = (schema, value, path = "input") => {
71
+ rejectServerOnly(schema, value, path);
72
+ return require_schema.validate(require_schema.asType(clientSchema(schema)), value, path);
73
+ };
74
+ /** Parse a JSON request body and run it through {@link wireInput}. */
75
+ const fromJsonBody = async (request, schema, path = "body") => {
76
+ let body;
77
+ try {
78
+ body = await request.json();
79
+ } catch {
80
+ throw new require_error.ValidationError(path, "expected a JSON body");
81
+ }
82
+ return wireInput(schema, body, path);
83
+ };
84
+ //#endregion
85
+ exports.clientSchema = clientSchema;
86
+ exports.fromJsonBody = fromJsonBody;
87
+ exports.rejectServerOnly = rejectServerOnly;
88
+ exports.serverOnly = serverOnly;
89
+ exports.wireInput = wireInput;
90
+
91
+ //# sourceMappingURL=attrs.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.cjs","names":["withAttrs","attrsOf","isVar","asType","typeOf","ValidationError","validate"],"sources":["../../../src/plugins/http/attrs.ts"],"sourcesContent":["import { ValidationError } from \"../../error\";\nimport {\n\tasType,\n\tattrsOf,\n\tisVar,\n\ttypeOf,\n\tvalidate,\n\twithAttrs,\n} from \"../../schema\";\n\n/** Mark a field as unusable over the wire - HTTP / capability edges\n * reject it if present; in-process callers may still pass it. */\nexport const serverOnly = <S>(schema: S): S =>\n\twithAttrs(schema, \"http\", { serverOnly: true });\n\nconst isServerOnly = (schema: unknown) =>\n\tattrsOf(schema, \"http\")?.serverOnly === true;\n\n/**\n * Drop fields (and nested object keys) marked {@link serverOnly}. Used\n * for OpenAPI / client contracts; {@link InferArgs} on the original\n * schema stays the full shape.\n */\nexport const clientSchema = <S>(schema: S): S => {\n\tif (isVar(schema)) {\n\t\tconst v = schema as { schema?: unknown };\n\t\treturn {\n\t\t\t...(schema as object),\n\t\t\tschema: v.schema === undefined ? undefined : clientSchema(v.schema as S),\n\t\t} as S;\n\t}\n\tconst def = asType(schema);\n\tif (def.name === \"object\" && def.shape !== undefined) {\n\t\tconst shape: Record<string, unknown> = {};\n\t\tfor (const [key, child] of Object.entries(\n\t\t\tdef.shape as Record<string, unknown>,\n\t\t)) {\n\t\t\tif (isServerOnly(child)) continue;\n\t\t\tshape[key] = clientSchema(child);\n\t\t}\n\t\treturn { ...def, shape } as S;\n\t}\n\tif (def.name === \"array\" && def.shape !== undefined) {\n\t\treturn { ...def, shape: clientSchema(def.shape) } as S;\n\t}\n\tif (def.name === \"union\" && Array.isArray(def.shape)) {\n\t\treturn {\n\t\t\t...def,\n\t\t\tshape: (def.shape as unknown[]).map((option) => clientSchema(option)),\n\t\t} as S;\n\t}\n\treturn schema;\n};\n\n/**\n * Throw if any {@link serverOnly} field is present on `value` (own key).\n * Object validation otherwise strips unknown keys, so this is what stops\n * wire callers from smuggling server-only values.\n */\nexport const rejectServerOnly = (\n\tschema: unknown,\n\tvalue: unknown,\n\tpath = \"input\",\n): void => {\n\tif (value === null || value === undefined) return;\n\tconst root = isVar(schema)\n\t\t? ((schema as { schema?: unknown }).schema ?? {})\n\t\t: schema;\n\tconst def = asType(root);\n\tif (def.name === \"object\" && def.shape !== undefined) {\n\t\tif (typeOf(value) !== \"object\") return;\n\t\tconst record = value as Record<string, unknown>;\n\t\tfor (const [key, child] of Object.entries(\n\t\t\tdef.shape as Record<string, unknown>,\n\t\t)) {\n\t\t\tif (isServerOnly(child) && Object.hasOwn(record, key)) {\n\t\t\t\tthrow new ValidationError(\n\t\t\t\t\t`${path}.${key}`,\n\t\t\t\t\t\"server-only field is not allowed over the wire\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (Object.hasOwn(record, key)) {\n\t\t\t\trejectServerOnly(child, record[key], `${path}.${key}`);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (def.name === \"array\" && def.shape !== undefined && Array.isArray(value)) {\n\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\trejectServerOnly(def.shape, value[i], `${path}[${i}]`);\n\t\t}\n\t\treturn;\n\t}\n\tif (def.name === \"union\" && Array.isArray(def.shape)) {\n\t\tfor (const option of def.shape as unknown[]) {\n\t\t\trejectServerOnly(option, value, path);\n\t\t}\n\t}\n};\n\n/**\n * Wire-side input gate: reject smuggled server-only keys, then validate\n * against {@link clientSchema}.\n */\nexport const wireInput = <S>(\n\tschema: S,\n\tvalue: unknown,\n\tpath = \"input\",\n): unknown => {\n\trejectServerOnly(schema, value, path);\n\treturn validate(asType(clientSchema(schema)), value, path);\n};\n\n/** Parse a JSON request body and run it through {@link wireInput}. */\nexport const fromJsonBody = async <S>(\n\trequest: Request,\n\tschema: S,\n\tpath = \"body\",\n): Promise<unknown> => {\n\tlet body: unknown;\n\ttry {\n\t\tbody = await request.json();\n\t} catch {\n\t\tthrow new ValidationError(path, \"expected a JSON body\");\n\t}\n\treturn wireInput(schema, body, path);\n};\n"],"mappings":";;;;;AAYA,MAAa,cAAiB,WAC7BA,eAAAA,UAAU,QAAQ,QAAQ,EAAE,YAAY,KAAK,CAAC;AAE/C,MAAM,gBAAgB,WACrBC,eAAAA,QAAQ,QAAQ,MAAM,CAAC,EAAE,eAAe;;;;;;AAOzC,MAAa,gBAAmB,WAAiB;CAChD,IAAIC,eAAAA,MAAM,MAAM,GAAG;EAClB,MAAM,IAAI;EACV,OAAO;GACN,GAAI;GACJ,QAAQ,EAAE,WAAW,KAAA,IAAY,KAAA,IAAY,aAAa,EAAE,MAAW;EACxE;CACD;CACA,MAAM,MAAMC,eAAAA,OAAO,MAAM;CACzB,IAAI,IAAI,SAAS,YAAY,IAAI,UAAU,KAAA,GAAW;EACrD,MAAM,QAAiC,CAAC;EACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QACjC,IAAI,KACL,GAAG;GACF,IAAI,aAAa,KAAK,GAAG;GACzB,MAAM,OAAO,aAAa,KAAK;EAChC;EACA,OAAO;GAAE,GAAG;GAAK;EAAM;CACxB;CACA,IAAI,IAAI,SAAS,WAAW,IAAI,UAAU,KAAA,GACzC,OAAO;EAAE,GAAG;EAAK,OAAO,aAAa,IAAI,KAAK;CAAE;CAEjD,IAAI,IAAI,SAAS,WAAW,MAAM,QAAQ,IAAI,KAAK,GAClD,OAAO;EACN,GAAG;EACH,OAAQ,IAAI,MAAoB,KAAK,WAAW,aAAa,MAAM,CAAC;CACrE;CAED,OAAO;AACR;;;;;;AAOA,MAAa,oBACZ,QACA,OACA,OAAO,YACG;CACV,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW;CAI3C,MAAM,MAAMA,eAAAA,OAHCD,eAAAA,MAAM,MAAM,IACpB,OAAgC,UAAU,CAAC,IAC7C,MACoB;CACvB,IAAI,IAAI,SAAS,YAAY,IAAI,UAAU,KAAA,GAAW;EACrD,IAAIE,eAAAA,OAAO,KAAK,MAAM,UAAU;EAChC,MAAM,SAAS;EACf,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QACjC,IAAI,KACL,GAAG;GACF,IAAI,aAAa,KAAK,KAAK,OAAO,OAAO,QAAQ,GAAG,GACnD,MAAM,IAAIC,cAAAA,gBACT,GAAG,KAAK,GAAG,OACX,gDACD;GAED,IAAI,OAAO,OAAO,QAAQ,GAAG,GAC5B,iBAAiB,OAAO,OAAO,MAAM,GAAG,KAAK,GAAG,KAAK;EAEvD;EACA;CACD;CACA,IAAI,IAAI,SAAS,WAAW,IAAI,UAAU,KAAA,KAAa,MAAM,QAAQ,KAAK,GAAG;EAC5E,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KACjC,iBAAiB,IAAI,OAAO,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,EAAE;EAEtD;CACD;CACA,IAAI,IAAI,SAAS,WAAW,MAAM,QAAQ,IAAI,KAAK,GAClD,KAAK,MAAM,UAAU,IAAI,OACxB,iBAAiB,QAAQ,OAAO,IAAI;AAGvC;;;;;AAMA,MAAa,aACZ,QACA,OACA,OAAO,YACM;CACb,iBAAiB,QAAQ,OAAO,IAAI;CACpC,OAAOC,eAAAA,SAASH,eAAAA,OAAO,aAAa,MAAM,CAAC,GAAG,OAAO,IAAI;AAC1D;;AAGA,MAAa,eAAe,OAC3B,SACA,QACA,OAAO,WACe;CACtB,IAAI;CACJ,IAAI;EACH,OAAO,MAAM,QAAQ,KAAK;CAC3B,QAAQ;EACP,MAAM,IAAIE,cAAAA,gBAAgB,MAAM,sBAAsB;CACvD;CACA,OAAO,UAAU,QAAQ,MAAM,IAAI;AACpC"}
@@ -0,0 +1,26 @@
1
+ //#region src/plugins/http/attrs.d.ts
2
+ /** Mark a field as unusable over the wire - HTTP / capability edges
3
+ * reject it if present; in-process callers may still pass it. */
4
+ declare const serverOnly: <S>(schema: S) => S;
5
+ /**
6
+ * Drop fields (and nested object keys) marked {@link serverOnly}. Used
7
+ * for OpenAPI / client contracts; {@link InferArgs} on the original
8
+ * schema stays the full shape.
9
+ */
10
+ declare const clientSchema: <S>(schema: S) => S;
11
+ /**
12
+ * Throw if any {@link serverOnly} field is present on `value` (own key).
13
+ * Object validation otherwise strips unknown keys, so this is what stops
14
+ * wire callers from smuggling server-only values.
15
+ */
16
+ declare const rejectServerOnly: (schema: unknown, value: unknown, path?: string) => void;
17
+ /**
18
+ * Wire-side input gate: reject smuggled server-only keys, then validate
19
+ * against {@link clientSchema}.
20
+ */
21
+ declare const wireInput: <S>(schema: S, value: unknown, path?: string) => unknown;
22
+ /** Parse a JSON request body and run it through {@link wireInput}. */
23
+ declare const fromJsonBody: <S>(request: Request, schema: S, path?: string) => Promise<unknown>;
24
+ //#endregion
25
+ export { clientSchema, fromJsonBody, rejectServerOnly, serverOnly, wireInput };
26
+ //# sourceMappingURL=attrs.d.cts.map
@@ -0,0 +1,26 @@
1
+ //#region src/plugins/http/attrs.d.ts
2
+ /** Mark a field as unusable over the wire - HTTP / capability edges
3
+ * reject it if present; in-process callers may still pass it. */
4
+ declare const serverOnly: <S>(schema: S) => S;
5
+ /**
6
+ * Drop fields (and nested object keys) marked {@link serverOnly}. Used
7
+ * for OpenAPI / client contracts; {@link InferArgs} on the original
8
+ * schema stays the full shape.
9
+ */
10
+ declare const clientSchema: <S>(schema: S) => S;
11
+ /**
12
+ * Throw if any {@link serverOnly} field is present on `value` (own key).
13
+ * Object validation otherwise strips unknown keys, so this is what stops
14
+ * wire callers from smuggling server-only values.
15
+ */
16
+ declare const rejectServerOnly: (schema: unknown, value: unknown, path?: string) => void;
17
+ /**
18
+ * Wire-side input gate: reject smuggled server-only keys, then validate
19
+ * against {@link clientSchema}.
20
+ */
21
+ declare const wireInput: <S>(schema: S, value: unknown, path?: string) => unknown;
22
+ /** Parse a JSON request body and run it through {@link wireInput}. */
23
+ declare const fromJsonBody: <S>(request: Request, schema: S, path?: string) => Promise<unknown>;
24
+ //#endregion
25
+ export { clientSchema, fromJsonBody, rejectServerOnly, serverOnly, wireInput };
26
+ //# sourceMappingURL=attrs.d.mts.map
@@ -0,0 +1,87 @@
1
+ import { ValidationError } from "../../error.mjs";
2
+ import { asType, attrsOf, isVar, typeOf, validate, withAttrs } from "../../schema.mjs";
3
+ //#region src/plugins/http/attrs.ts
4
+ /** Mark a field as unusable over the wire - HTTP / capability edges
5
+ * reject it if present; in-process callers may still pass it. */
6
+ const serverOnly = (schema) => withAttrs(schema, "http", { serverOnly: true });
7
+ const isServerOnly = (schema) => attrsOf(schema, "http")?.serverOnly === true;
8
+ /**
9
+ * Drop fields (and nested object keys) marked {@link serverOnly}. Used
10
+ * for OpenAPI / client contracts; {@link InferArgs} on the original
11
+ * schema stays the full shape.
12
+ */
13
+ const clientSchema = (schema) => {
14
+ if (isVar(schema)) {
15
+ const v = schema;
16
+ return {
17
+ ...schema,
18
+ schema: v.schema === void 0 ? void 0 : clientSchema(v.schema)
19
+ };
20
+ }
21
+ const def = asType(schema);
22
+ if (def.name === "object" && def.shape !== void 0) {
23
+ const shape = {};
24
+ for (const [key, child] of Object.entries(def.shape)) {
25
+ if (isServerOnly(child)) continue;
26
+ shape[key] = clientSchema(child);
27
+ }
28
+ return {
29
+ ...def,
30
+ shape
31
+ };
32
+ }
33
+ if (def.name === "array" && def.shape !== void 0) return {
34
+ ...def,
35
+ shape: clientSchema(def.shape)
36
+ };
37
+ if (def.name === "union" && Array.isArray(def.shape)) return {
38
+ ...def,
39
+ shape: def.shape.map((option) => clientSchema(option))
40
+ };
41
+ return schema;
42
+ };
43
+ /**
44
+ * Throw if any {@link serverOnly} field is present on `value` (own key).
45
+ * Object validation otherwise strips unknown keys, so this is what stops
46
+ * wire callers from smuggling server-only values.
47
+ */
48
+ const rejectServerOnly = (schema, value, path = "input") => {
49
+ if (value === null || value === void 0) return;
50
+ const def = asType(isVar(schema) ? schema.schema ?? {} : schema);
51
+ if (def.name === "object" && def.shape !== void 0) {
52
+ if (typeOf(value) !== "object") return;
53
+ const record = value;
54
+ for (const [key, child] of Object.entries(def.shape)) {
55
+ if (isServerOnly(child) && Object.hasOwn(record, key)) throw new ValidationError(`${path}.${key}`, "server-only field is not allowed over the wire");
56
+ if (Object.hasOwn(record, key)) rejectServerOnly(child, record[key], `${path}.${key}`);
57
+ }
58
+ return;
59
+ }
60
+ if (def.name === "array" && def.shape !== void 0 && Array.isArray(value)) {
61
+ for (let i = 0; i < value.length; i++) rejectServerOnly(def.shape, value[i], `${path}[${i}]`);
62
+ return;
63
+ }
64
+ if (def.name === "union" && Array.isArray(def.shape)) for (const option of def.shape) rejectServerOnly(option, value, path);
65
+ };
66
+ /**
67
+ * Wire-side input gate: reject smuggled server-only keys, then validate
68
+ * against {@link clientSchema}.
69
+ */
70
+ const wireInput = (schema, value, path = "input") => {
71
+ rejectServerOnly(schema, value, path);
72
+ return validate(asType(clientSchema(schema)), value, path);
73
+ };
74
+ /** Parse a JSON request body and run it through {@link wireInput}. */
75
+ const fromJsonBody = async (request, schema, path = "body") => {
76
+ let body;
77
+ try {
78
+ body = await request.json();
79
+ } catch {
80
+ throw new ValidationError(path, "expected a JSON body");
81
+ }
82
+ return wireInput(schema, body, path);
83
+ };
84
+ //#endregion
85
+ export { clientSchema, fromJsonBody, rejectServerOnly, serverOnly, wireInput };
86
+
87
+ //# sourceMappingURL=attrs.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.mjs","names":[],"sources":["../../../src/plugins/http/attrs.ts"],"sourcesContent":["import { ValidationError } from \"../../error\";\nimport {\n\tasType,\n\tattrsOf,\n\tisVar,\n\ttypeOf,\n\tvalidate,\n\twithAttrs,\n} from \"../../schema\";\n\n/** Mark a field as unusable over the wire - HTTP / capability edges\n * reject it if present; in-process callers may still pass it. */\nexport const serverOnly = <S>(schema: S): S =>\n\twithAttrs(schema, \"http\", { serverOnly: true });\n\nconst isServerOnly = (schema: unknown) =>\n\tattrsOf(schema, \"http\")?.serverOnly === true;\n\n/**\n * Drop fields (and nested object keys) marked {@link serverOnly}. Used\n * for OpenAPI / client contracts; {@link InferArgs} on the original\n * schema stays the full shape.\n */\nexport const clientSchema = <S>(schema: S): S => {\n\tif (isVar(schema)) {\n\t\tconst v = schema as { schema?: unknown };\n\t\treturn {\n\t\t\t...(schema as object),\n\t\t\tschema: v.schema === undefined ? undefined : clientSchema(v.schema as S),\n\t\t} as S;\n\t}\n\tconst def = asType(schema);\n\tif (def.name === \"object\" && def.shape !== undefined) {\n\t\tconst shape: Record<string, unknown> = {};\n\t\tfor (const [key, child] of Object.entries(\n\t\t\tdef.shape as Record<string, unknown>,\n\t\t)) {\n\t\t\tif (isServerOnly(child)) continue;\n\t\t\tshape[key] = clientSchema(child);\n\t\t}\n\t\treturn { ...def, shape } as S;\n\t}\n\tif (def.name === \"array\" && def.shape !== undefined) {\n\t\treturn { ...def, shape: clientSchema(def.shape) } as S;\n\t}\n\tif (def.name === \"union\" && Array.isArray(def.shape)) {\n\t\treturn {\n\t\t\t...def,\n\t\t\tshape: (def.shape as unknown[]).map((option) => clientSchema(option)),\n\t\t} as S;\n\t}\n\treturn schema;\n};\n\n/**\n * Throw if any {@link serverOnly} field is present on `value` (own key).\n * Object validation otherwise strips unknown keys, so this is what stops\n * wire callers from smuggling server-only values.\n */\nexport const rejectServerOnly = (\n\tschema: unknown,\n\tvalue: unknown,\n\tpath = \"input\",\n): void => {\n\tif (value === null || value === undefined) return;\n\tconst root = isVar(schema)\n\t\t? ((schema as { schema?: unknown }).schema ?? {})\n\t\t: schema;\n\tconst def = asType(root);\n\tif (def.name === \"object\" && def.shape !== undefined) {\n\t\tif (typeOf(value) !== \"object\") return;\n\t\tconst record = value as Record<string, unknown>;\n\t\tfor (const [key, child] of Object.entries(\n\t\t\tdef.shape as Record<string, unknown>,\n\t\t)) {\n\t\t\tif (isServerOnly(child) && Object.hasOwn(record, key)) {\n\t\t\t\tthrow new ValidationError(\n\t\t\t\t\t`${path}.${key}`,\n\t\t\t\t\t\"server-only field is not allowed over the wire\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (Object.hasOwn(record, key)) {\n\t\t\t\trejectServerOnly(child, record[key], `${path}.${key}`);\n\t\t\t}\n\t\t}\n\t\treturn;\n\t}\n\tif (def.name === \"array\" && def.shape !== undefined && Array.isArray(value)) {\n\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\trejectServerOnly(def.shape, value[i], `${path}[${i}]`);\n\t\t}\n\t\treturn;\n\t}\n\tif (def.name === \"union\" && Array.isArray(def.shape)) {\n\t\tfor (const option of def.shape as unknown[]) {\n\t\t\trejectServerOnly(option, value, path);\n\t\t}\n\t}\n};\n\n/**\n * Wire-side input gate: reject smuggled server-only keys, then validate\n * against {@link clientSchema}.\n */\nexport const wireInput = <S>(\n\tschema: S,\n\tvalue: unknown,\n\tpath = \"input\",\n): unknown => {\n\trejectServerOnly(schema, value, path);\n\treturn validate(asType(clientSchema(schema)), value, path);\n};\n\n/** Parse a JSON request body and run it through {@link wireInput}. */\nexport const fromJsonBody = async <S>(\n\trequest: Request,\n\tschema: S,\n\tpath = \"body\",\n): Promise<unknown> => {\n\tlet body: unknown;\n\ttry {\n\t\tbody = await request.json();\n\t} catch {\n\t\tthrow new ValidationError(path, \"expected a JSON body\");\n\t}\n\treturn wireInput(schema, body, path);\n};\n"],"mappings":";;;;;AAYA,MAAa,cAAiB,WAC7B,UAAU,QAAQ,QAAQ,EAAE,YAAY,KAAK,CAAC;AAE/C,MAAM,gBAAgB,WACrB,QAAQ,QAAQ,MAAM,CAAC,EAAE,eAAe;;;;;;AAOzC,MAAa,gBAAmB,WAAiB;CAChD,IAAI,MAAM,MAAM,GAAG;EAClB,MAAM,IAAI;EACV,OAAO;GACN,GAAI;GACJ,QAAQ,EAAE,WAAW,KAAA,IAAY,KAAA,IAAY,aAAa,EAAE,MAAW;EACxE;CACD;CACA,MAAM,MAAM,OAAO,MAAM;CACzB,IAAI,IAAI,SAAS,YAAY,IAAI,UAAU,KAAA,GAAW;EACrD,MAAM,QAAiC,CAAC;EACxC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QACjC,IAAI,KACL,GAAG;GACF,IAAI,aAAa,KAAK,GAAG;GACzB,MAAM,OAAO,aAAa,KAAK;EAChC;EACA,OAAO;GAAE,GAAG;GAAK;EAAM;CACxB;CACA,IAAI,IAAI,SAAS,WAAW,IAAI,UAAU,KAAA,GACzC,OAAO;EAAE,GAAG;EAAK,OAAO,aAAa,IAAI,KAAK;CAAE;CAEjD,IAAI,IAAI,SAAS,WAAW,MAAM,QAAQ,IAAI,KAAK,GAClD,OAAO;EACN,GAAG;EACH,OAAQ,IAAI,MAAoB,KAAK,WAAW,aAAa,MAAM,CAAC;CACrE;CAED,OAAO;AACR;;;;;;AAOA,MAAa,oBACZ,QACA,OACA,OAAO,YACG;CACV,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW;CAI3C,MAAM,MAAM,OAHC,MAAM,MAAM,IACpB,OAAgC,UAAU,CAAC,IAC7C,MACoB;CACvB,IAAI,IAAI,SAAS,YAAY,IAAI,UAAU,KAAA,GAAW;EACrD,IAAI,OAAO,KAAK,MAAM,UAAU;EAChC,MAAM,SAAS;EACf,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QACjC,IAAI,KACL,GAAG;GACF,IAAI,aAAa,KAAK,KAAK,OAAO,OAAO,QAAQ,GAAG,GACnD,MAAM,IAAI,gBACT,GAAG,KAAK,GAAG,OACX,gDACD;GAED,IAAI,OAAO,OAAO,QAAQ,GAAG,GAC5B,iBAAiB,OAAO,OAAO,MAAM,GAAG,KAAK,GAAG,KAAK;EAEvD;EACA;CACD;CACA,IAAI,IAAI,SAAS,WAAW,IAAI,UAAU,KAAA,KAAa,MAAM,QAAQ,KAAK,GAAG;EAC5E,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KACjC,iBAAiB,IAAI,OAAO,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,EAAE;EAEtD;CACD;CACA,IAAI,IAAI,SAAS,WAAW,MAAM,QAAQ,IAAI,KAAK,GAClD,KAAK,MAAM,UAAU,IAAI,OACxB,iBAAiB,QAAQ,OAAO,IAAI;AAGvC;;;;;AAMA,MAAa,aACZ,QACA,OACA,OAAO,YACM;CACb,iBAAiB,QAAQ,OAAO,IAAI;CACpC,OAAO,SAAS,OAAO,aAAa,MAAM,CAAC,GAAG,OAAO,IAAI;AAC1D;;AAGA,MAAa,eAAe,OAC3B,SACA,QACA,OAAO,WACe;CACtB,IAAI;CACJ,IAAI;EACH,OAAO,MAAM,QAAQ,KAAK;CAC3B,QAAQ;EACP,MAAM,IAAI,gBAAgB,MAAM,sBAAsB;CACvD;CACA,OAAO,UAAU,QAAQ,MAAM,IAAI;AACpC"}
@@ -0,0 +1,117 @@
1
+ const require_index = require("../../index.cjs");
2
+ const require_response = require("./response.cjs");
3
+ const require_request = require("./request.cjs");
4
+ //#region src/plugins/http/cookie.ts
5
+ /** Cookie attributes as a SCHEMA - the source of truth. The TS type
6
+ * falls out of it, and everything crossing a fn door validates against
7
+ * it (enum-checked sameSite, `instanceof`-checked expires). */
8
+ const cookieShape = {
9
+ maxAge: require_index.v.number({ optional: true }),
10
+ expires: require_index.v.date({ optional: true }),
11
+ path: require_index.v.string({ optional: true }),
12
+ domain: require_index.v.string({ optional: true }),
13
+ secure: require_index.v.boolean({ optional: true }),
14
+ httpOnly: require_index.v.boolean({ optional: true }),
15
+ sameSite: require_index.v.string({
16
+ enum: [
17
+ "strict",
18
+ "lax",
19
+ "none"
20
+ ],
21
+ optional: true
22
+ })
23
+ };
24
+ /**
25
+ * Scope-level cookie DEFAULTS, as a var: whatever sets it - app setup, a
26
+ * module, an interceptor - every `setCookie` below merges its per-call
27
+ * options ON TOP. Config that travels down the call tree is exactly what
28
+ * a var is, so "change the global cookie config" is just a `.set()` at
29
+ * any point in the scope.
30
+ */
31
+ const cookieOptions = require_index.v.var("cookieOptions", {
32
+ default: {},
33
+ schema: require_index.v.object(cookieShape)
34
+ });
35
+ /** The per-call options field: the same shape, optional to send. */
36
+ const cookieOptionsField = require_index.v.object(cookieShape, { optional: true });
37
+ const serialize = (name, value, options = {}) => {
38
+ const parts = [`${name}=${encodeURIComponent(value)}`];
39
+ if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
40
+ if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
41
+ if (options.path) parts.push(`Path=${options.path}`);
42
+ if (options.domain) parts.push(`Domain=${options.domain}`);
43
+ if (options.secure) parts.push("Secure");
44
+ if (options.httpOnly) parts.push("HttpOnly");
45
+ if (options.sameSite) parts.push(`SameSite=${options.sameSite.charAt(0).toUpperCase()}${options.sameSite.slice(1)}`);
46
+ return parts.join("; ");
47
+ };
48
+ const ck = require_index.v.fn("cookie.", { use: [{
49
+ req: require_request.req,
50
+ res: require_response.res,
51
+ cookieOptions
52
+ }] });
53
+ /** Read one cookie from the REQUEST jar. Positional: `getCookie("theme")`.
54
+ * Readonly - reading a cookie can never write the scope. */
55
+ const getCookie = ck.fn("get", {
56
+ input: [require_index.v.string()],
57
+ readonly: true
58
+ }, (c) => {
59
+ const [name] = c.input;
60
+ return c.req?.cookies[name] ?? null;
61
+ });
62
+ /** Queue a Set-Cookie on the scope's response headers: the scope's
63
+ * `cookieOptions` defaults, with per-call options merged on top. The
64
+ * written cookie also lands in the request jar, so a later `getCookie`
65
+ * in the same scope reads what was set. */
66
+ const setCookie = ck.fn("set", { input: {
67
+ name: require_index.v.string(),
68
+ value: require_index.v.string(),
69
+ options: cookieOptionsField
70
+ } }, (c) => {
71
+ const { name, value, options } = c.input;
72
+ let response = c.res;
73
+ if (!response) {
74
+ response = { headers: new Headers() };
75
+ c.res = response;
76
+ }
77
+ response.headers.append("set-cookie", serialize(name, value, {
78
+ ...c.cookieOptions,
79
+ ...options
80
+ }));
81
+ const current = c.req;
82
+ if (current) c.req = {
83
+ ...current,
84
+ cookies: {
85
+ ...current.cookies,
86
+ [name]: value
87
+ }
88
+ };
89
+ return { set: true };
90
+ });
91
+ /** Expire a cookie: a Set-Cookie with Max-Age=0 - the attributes (path,
92
+ * domain) must match the ones it was set with. */
93
+ const deleteCookie = ck.fn("delete", {
94
+ input: {
95
+ name: require_index.v.string(),
96
+ options: cookieOptionsField
97
+ },
98
+ use: [{ setCookie }]
99
+ }, (c) => {
100
+ const { name, options } = c.input;
101
+ return c.setCookie({
102
+ name,
103
+ value: "",
104
+ options: {
105
+ ...options,
106
+ maxAge: 0
107
+ }
108
+ });
109
+ });
110
+ //#endregion
111
+ exports.cookieOptions = cookieOptions;
112
+ exports.cookieShape = cookieShape;
113
+ exports.deleteCookie = deleteCookie;
114
+ exports.getCookie = getCookie;
115
+ exports.setCookie = setCookie;
116
+
117
+ //# sourceMappingURL=cookie.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.cjs","names":["v"],"sources":["../../../src/plugins/http/cookie.ts"],"sourcesContent":["import { v } from \"../../index\";\nimport type { InferArgs } from \"../../schema\";\nimport { req } from \"./request\";\nimport { res } from \"./response\";\n\n/** Cookie attributes as a SCHEMA - the source of truth. The TS type\n * falls out of it, and everything crossing a fn door validates against\n * it (enum-checked sameSite, `instanceof`-checked expires). */\nexport const cookieShape = {\n\tmaxAge: v.number({ optional: true }),\n\texpires: v.date({ optional: true }),\n\tpath: v.string({ optional: true }),\n\tdomain: v.string({ optional: true }),\n\tsecure: v.boolean({ optional: true }),\n\thttpOnly: v.boolean({ optional: true }),\n\tsameSite: v.string({ enum: [\"strict\", \"lax\", \"none\"], optional: true }),\n};\n\nexport type CookieOptions = InferArgs<typeof cookieShape>;\n\n/**\n * Scope-level cookie DEFAULTS, as a var: whatever sets it - app setup, a\n * module, an interceptor - every `setCookie` below merges its per-call\n * options ON TOP. Config that travels down the call tree is exactly what\n * a var is, so \"change the global cookie config\" is just a `.set()` at\n * any point in the scope.\n */\nexport const cookieOptions = v.var(\"cookieOptions\", {\n\tdefault: {},\n\tschema: v.object(cookieShape),\n});\n\n/** The per-call options field: the same shape, optional to send. */\nconst cookieOptionsField = v.object(cookieShape, { optional: true });\n\nconst serialize = (\n\tname: string,\n\tvalue: string,\n\toptions: CookieOptions = {},\n) => {\n\tconst parts = [`${name}=${encodeURIComponent(value)}`];\n\tif (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n\tif (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n\tif (options.path) parts.push(`Path=${options.path}`);\n\tif (options.domain) parts.push(`Domain=${options.domain}`);\n\tif (options.secure) parts.push(\"Secure\");\n\tif (options.httpOnly) parts.push(\"HttpOnly\");\n\tif (options.sameSite) {\n\t\tparts.push(\n\t\t\t`SameSite=${options.sameSite.charAt(0).toUpperCase()}${options.sameSite.slice(1)}`,\n\t\t);\n\t}\n\treturn parts.join(\"; \");\n};\n\nconst ck = v.fn(\"cookie.\", {\n\tuse: [{ req, res, cookieOptions }],\n});\n\n/** Read one cookie from the REQUEST jar. Positional: `getCookie(\"theme\")`.\n * Readonly - reading a cookie can never write the scope. */\nexport const getCookie = ck.fn(\n\t\"get\",\n\t{ input: [v.string()], readonly: true },\n\t(c): string | null => {\n\t\tconst [name] = c.input;\n\t\treturn c.req?.cookies[name] ?? null;\n\t},\n);\n\n/** Queue a Set-Cookie on the scope's response headers: the scope's\n * `cookieOptions` defaults, with per-call options merged on top. The\n * written cookie also lands in the request jar, so a later `getCookie`\n * in the same scope reads what was set. */\nexport const setCookie = ck.fn(\n\t\"set\",\n\t{\n\t\tinput: {\n\t\t\tname: v.string(),\n\t\t\tvalue: v.string(),\n\t\t\toptions: cookieOptionsField,\n\t\t},\n\t},\n\t(c) => {\n\t\tconst { name, value, options } = c.input;\n\t\tlet response = c.res;\n\t\tif (!response) {\n\t\t\tresponse = { headers: new Headers() };\n\t\t\tc.res = response;\n\t\t}\n\t\tresponse.headers.append(\n\t\t\t\"set-cookie\",\n\t\t\tserialize(name, value, { ...c.cookieOptions, ...options }),\n\t\t);\n\t\tconst current = c.req;\n\t\tif (current) {\n\t\t\tc.req = {\n\t\t\t\t...current,\n\t\t\t\tcookies: { ...current.cookies, [name]: value },\n\t\t\t};\n\t\t}\n\t\treturn { set: true };\n\t},\n);\n\n/** Expire a cookie: a Set-Cookie with Max-Age=0 - the attributes (path,\n * domain) must match the ones it was set with. */\nexport const deleteCookie = ck.fn(\n\t\"delete\",\n\t{\n\t\tinput: {\n\t\t\tname: v.string(),\n\t\t\toptions: cookieOptionsField,\n\t\t},\n\t\tuse: [{ setCookie }],\n\t},\n\t(c) => {\n\t\tconst { name, options } = c.input;\n\t\treturn c.setCookie({\n\t\t\tname,\n\t\t\tvalue: \"\",\n\t\t\toptions: { ...options, maxAge: 0 },\n\t\t});\n\t},\n);\n"],"mappings":"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"}