capability-worker 0.1.1 → 0.1.4

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/README.md CHANGED
@@ -41,6 +41,12 @@ pnpm exec capability-build-assets --validate
41
41
  pnpm exec capability-validate
42
42
  ```
43
43
 
44
+ ## Publishing
45
+
46
+ Pushes to `main` are released by `.github/workflows/publish.yml`. The workflow prepares a new `v<version>` tag and publishes to npm through Trusted Publishing in the same GitHub Actions run, without an npm token.
47
+
48
+ Configure the npm package Trusted Publisher before relying on the workflow. The required npmjs.com settings are documented in [trusted-publishing.md](https://github.com/Iliasnolsson/capability-worker/blob/main/trusted-publishing.md).
49
+
44
50
  ## Mental Model
45
51
 
46
52
  A capability worker has two parts:
@@ -378,9 +384,11 @@ import {
378
384
  HttpError,
379
385
  errorJson,
380
386
  errorResponse,
387
+ corsHeaders,
381
388
  jsonResponse,
382
389
  okJson,
383
- textResponse
390
+ textResponse,
391
+ withCors
384
392
  } from "capability-worker/http";
385
393
 
386
394
  export async function readMeeting(request: Request, env: Env) {
@@ -425,6 +433,9 @@ htmlResponse(value, init);
425
433
  redirectResponse(location, status);
426
434
  errorJson(code, message, status, extra);
427
435
  errorResponse(error);
436
+ corsHeaders(request, options);
437
+ withCors(request, response, options);
438
+ isCorsOriginAllowed(request, options);
428
439
  parseJsonBody(request);
429
440
  readJsonObject(request);
430
441
  isJsonRequested(url, body);
File without changes
File without changes
@@ -6,9 +6,23 @@ declare class HttpError extends Error {
6
6
  expose?: boolean;
7
7
  });
8
8
  }
9
+ type CorsAllowedOrigins = Iterable<string> | ((origin: string, request: Request) => boolean);
10
+ type CorsVaryMode = boolean | "always" | "allowed";
11
+ type CorsOptions = {
12
+ allowedOrigins?: CorsAllowedOrigins;
13
+ allowCredentials?: boolean;
14
+ allowOriginForNoOrigin?: boolean;
15
+ methods?: string | string[];
16
+ headers?: string | string[];
17
+ maxAgeSeconds?: number;
18
+ vary?: CorsVaryMode;
19
+ };
9
20
  declare function jsonResponse(value: unknown, init?: ResponseInit | number): Response;
10
21
  declare function okJson(data: unknown, init?: ResponseInit | number): Response;
11
22
  declare function textResponse(value: string, init?: ResponseInit | number): Response;
23
+ declare function corsHeaders(request: Request, options?: CorsOptions): Headers;
24
+ declare function withCors(request: Request, response: Response, options?: CorsOptions): Response;
25
+ declare function isCorsOriginAllowed(request: Request, options?: Pick<CorsOptions, "allowedOrigins">): boolean;
12
26
  declare function htmlResponse(value: string, init?: ResponseInit | number): Response;
13
27
  declare function redirectResponse(location: string, status?: number): Response;
14
28
  declare function errorJson(code: string, message: string, status?: number, extra?: Record<string, unknown>): Response;
@@ -22,4 +36,5 @@ declare function booleanParam(value: unknown): boolean;
22
36
  declare function limitParam(value: unknown, defaultValue?: number, max?: number): number;
23
37
  declare function getRepeated(url: URL, key: string): string[];
24
38
 
25
- export { HttpError, booleanParam, errorJson, errorResponse, getRepeated, htmlResponse, isJsonRequested, jsonResponse, limitParam, okJson, parseJsonBody, readJsonObject, redirectResponse, stringArrayParam, stringParam, textResponse };
39
+ export { HttpError, booleanParam, corsHeaders, errorJson, errorResponse, getRepeated, htmlResponse, isCorsOriginAllowed, isJsonRequested, jsonResponse, limitParam, okJson, parseJsonBody, readJsonObject, redirectResponse, stringArrayParam, stringParam, textResponse, withCors };
40
+ export type { CorsAllowedOrigins, CorsOptions, CorsVaryMode };
@@ -1 +1 @@
1
- class t extends Error{status;code;expose;constructor(t,e,n,r){super(n),this.name="HttpError",this.status=t,this.code=e,this.expose=r?.expose??t<500}}function e(t,e=200){const n=m(e);return new Response(JSON.stringify(t,null,2),{...n,headers:x(n.headers,"content-type","application/json; charset=utf-8")})}function n(t,n=200){return e({ok:!0,data:t},n)}function r(t,e=200){return new Response(t.endsWith("\n")?t:`${t}\n`,{...m(e),headers:x(m(e).headers,"content-type","text/plain; charset=utf-8")})}function o(t,e=200){const n=m(e);return new Response(t,{...n,headers:x(n.headers,"content-type","text/html; charset=utf-8")})}function s(t,e=302){return new Response(null,{status:e,headers:{location:t,"cache-control":"no-store"}})}function a(t,n,r=400,o={}){return e({ok:!1,error:{code:t,message:n},...o},r)}function c(e){return e instanceof t?a(e.code,e.expose?e.message:"Internal error.",e.status):a("internal_error","Internal error.",500)}async function u(t){if(!t.body)return{};try{const e=await t.json();return!e||"object"!=typeof e||Array.isArray(e)?{}:e}catch{return{}}}async function i(e){const n=await e.json().catch(()=>null);if(!n||"object"!=typeof n||Array.isArray(n))throw new t(400,"invalid_json","Expected a JSON object.");return n}function f(t,e){const n=t.searchParams.get("json");return""===n||"1"===n||"true"===n||!0===e?.json}function h(t){if("string"!=typeof t)return;const e=t.trim();return e.length>0?e:void 0}function p(t){if(Array.isArray(t))return t.filter(t=>"string"==typeof t).map(t=>t.trim()).filter(Boolean);const e=h(t);return e?[e]:[]}function l(t){return!0===t||"true"===t||"1"===t||""===t}function y(t,e=20,n=100){const r="number"==typeof t?t:Number(t);return Number.isFinite(r)?Math.max(1,Math.min(n,Math.floor(r))):e}function d(t,e){return t.searchParams.getAll(e).map(t=>t.trim()).filter(Boolean)}function m(t){return"number"==typeof t?{status:t}:t}function x(t,e,n){const r=new Headers(t);return r.has(e)||r.set(e,n),r}export{t as HttpError,l as booleanParam,a as errorJson,c as errorResponse,d as getRepeated,o as htmlResponse,f as isJsonRequested,e as jsonResponse,y as limitParam,n as okJson,u as parseJsonBody,i as readJsonObject,s as redirectResponse,p as stringArrayParam,h as stringParam,r as textResponse};
1
+ class t extends Error{status;code;expose;constructor(t,e,n,r){super(n),this.name="HttpError",this.status=t,this.code=e,this.expose=r?.expose??t<500}}function e(t,e=200){const n=x(e);return new Response(JSON.stringify(t,null,2),{...n,headers:b(n.headers,"content-type","application/json; charset=utf-8")})}function n(t,n=200){return e({ok:!0,data:t},n)}function r(t,e=200){return new Response(t.endsWith("\n")?t:`${t}\n`,{...x(e),headers:b(x(e).headers,"content-type","text/plain; charset=utf-8")})}function o(t,e={}){const n=new Headers,r=t.headers.get("origin"),o=!!r&&A(r,t,e.allowedOrigins);r&&o?(n.set("access-control-allow-origin",r),e.allowCredentials&&n.set("access-control-allow-credentials","true")):!r&&e.allowOriginForNoOrigin&&n.set("access-control-allow-origin","*");const s=e.vary??"allowed";return("always"===s||!0===s&&r||"allowed"===s&&o)&&n.set("vary","Origin"),n.set("access-control-allow-methods",j(e.methods,"GET,POST,PUT,PATCH,DELETE,OPTIONS")),n.set("access-control-allow-headers",j(e.headers,"content-type,x-capability-account-id,x-capability-timestamp,x-capability-key-id,x-capability-signature")),n.set("access-control-max-age",String(e.maxAgeSeconds??86400)),n}function s(t,e,n={}){const r=new Headers(e.headers);return o(t,n).forEach((t,e)=>r.set(e,t)),new Response(e.body,{status:e.status,statusText:e.statusText,headers:r})}function a(t,e={}){const n=t.headers.get("origin");return Boolean(n&&A(n,t,e.allowedOrigins))}function i(t,e=200){const n=x(e);return new Response(t,{...n,headers:b(n.headers,"content-type","text/html; charset=utf-8")})}function c(t,e=302){return new Response(null,{status:e,headers:{location:t,"cache-control":"no-store"}})}function u(t,n,r=400,o={}){return e({ok:!1,error:{code:t,message:n},...o},r)}function l(e){return e instanceof t?u(e.code,e.expose?e.message:"Internal error.",e.status):u("internal_error","Internal error.",500)}async function f(t){if(!t.body)return{};try{const e=await t.json();return!e||"object"!=typeof e||Array.isArray(e)?{}:e}catch{return{}}}async function d(e){const n=await e.json().catch(()=>null);if(!n||"object"!=typeof n||Array.isArray(n))throw new t(400,"invalid_json","Expected a JSON object.");return n}function h(t,e){const n=t.searchParams.get("json");return""===n||"1"===n||"true"===n||!0===e?.json}function p(t){if("string"!=typeof t)return;const e=t.trim();return e.length>0?e:void 0}function y(t){if(Array.isArray(t))return t.filter(t=>"string"==typeof t).map(t=>t.trim()).filter(Boolean);const e=p(t);return e?[e]:[]}function g(t){return!0===t||"true"===t||"1"===t||""===t}function w(t,e=20,n=100){const r="number"==typeof t?t:Number(t);return Number.isFinite(r)?Math.max(1,Math.min(n,Math.floor(r))):e}function m(t,e){return t.searchParams.getAll(e).map(t=>t.trim()).filter(Boolean)}function x(t){return"number"==typeof t?{status:t}:t}function b(t,e,n){const r=new Headers(t);return r.has(e)||r.set(e,n),r}function A(t,e,n){if(!n)return!0;if("function"==typeof n)return n(t,e);for(const e of n)if("*"===e||e===t)return!0;return!1}function j(t,e){return"string"==typeof t?t:Array.isArray(t)?t.join(","):e}export{t as HttpError,g as booleanParam,o as corsHeaders,u as errorJson,l as errorResponse,m as getRepeated,i as htmlResponse,a as isCorsOriginAllowed,h as isJsonRequested,e as jsonResponse,w as limitParam,n as okJson,f as parseJsonBody,d as readJsonObject,c as redirectResponse,y as stringArrayParam,p as stringParam,r as textResponse,s as withCors};
package/package.json CHANGED
@@ -1,8 +1,13 @@
1
1
  {
2
2
  "name": "capability-worker",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "Shared toolkit for Cloudflare Workers that expose CLI-like capabilities over HTTP.",
5
5
  "type": "module",
6
+ "packageManager": "pnpm@11.9.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Iliasnolsson/capability-worker.git"
10
+ },
6
11
  "sideEffects": false,
7
12
  "files": [
8
13
  "dist",
@@ -10,6 +15,15 @@
10
15
  "README.md",
11
16
  "LICENSE"
12
17
  ],
18
+ "scripts": {
19
+ "clean": "rm -rf dist",
20
+ "build": "pnpm clean && rollup -c",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "vitest run",
23
+ "prepack": "pnpm build",
24
+ "pack:check": "pnpm build && pnpm pack --dry-run",
25
+ "publish:npm": "pnpm typecheck && pnpm test && pnpm pack:check && pnpm publish --access public"
26
+ },
13
27
  "bin": {
14
28
  "capability-build-assets": "dist/node/build-capability-assets-cli.js",
15
29
  "capability-validate": "dist/node/validate-cli.js"
@@ -66,13 +80,5 @@
66
80
  "rollup-plugin-esbuild": "^6.0.0",
67
81
  "typescript": "^5.9.0",
68
82
  "vitest": "^4.1.0"
69
- },
70
- "scripts": {
71
- "clean": "rm -rf dist",
72
- "build": "pnpm clean && rollup -c",
73
- "typecheck": "tsc --noEmit",
74
- "test": "vitest run",
75
- "pack:check": "pnpm build && pnpm pack --dry-run",
76
- "publish:npm": "pnpm typecheck && pnpm test && pnpm pack:check && pnpm publish --access public"
77
83
  }
78
- }
84
+ }
@@ -2,5 +2,4 @@ packages:
2
2
  - worker
3
3
 
4
4
  minimumReleaseAgeExclude:
5
- - capability-worker@0.1.1
6
-
5
+ - capability-worker@0.1.4
@@ -9,7 +9,7 @@
9
9
  "deploy": "pnpm run build:capability-assets && wrangler deploy"
10
10
  },
11
11
  "dependencies": {
12
- "capability-worker": "^0.1.1"
12
+ "capability-worker": "^0.1.4"
13
13
  },
14
14
  "devDependencies": {
15
15
  "@cloudflare/workers-types": "^4.20260627.0",
@@ -17,4 +17,3 @@
17
17
  "wrangler": "^4.51.0"
18
18
  }
19
19
  }
20
-