@tetrascience-npm/request 0.2.0-beta.106.2

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 (81) hide show
  1. package/README.md +169 -0
  2. package/client.d.ts +1 -0
  3. package/client.js +1 -0
  4. package/dist/cli/generate-client.d.ts +3 -0
  5. package/dist/cli/generate-client.d.ts.map +1 -0
  6. package/dist/cli/generate-client.js +208 -0
  7. package/dist/cli/generate-schemas.d.ts +7 -0
  8. package/dist/cli/generate-schemas.d.ts.map +1 -0
  9. package/dist/cli/generate-schemas.js +210 -0
  10. package/dist/cli/templates.d.ts +27 -0
  11. package/dist/cli/templates.d.ts.map +1 -0
  12. package/dist/cli/templates.js +165 -0
  13. package/dist/client/console-logger.d.ts +10 -0
  14. package/dist/client/console-logger.d.ts.map +1 -0
  15. package/dist/client/console-logger.js +42 -0
  16. package/dist/client/index.d.ts +4 -0
  17. package/dist/client/index.d.ts.map +1 -0
  18. package/dist/client/index.js +19 -0
  19. package/dist/client/install-middleware.d.ts +31 -0
  20. package/dist/client/install-middleware.d.ts.map +1 -0
  21. package/dist/client/install-middleware.js +117 -0
  22. package/dist/client/types.d.ts +13 -0
  23. package/dist/client/types.d.ts.map +1 -0
  24. package/dist/client/types.js +2 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +17 -0
  28. package/dist/server/index.d.ts +5 -0
  29. package/dist/server/index.d.ts.map +1 -0
  30. package/dist/server/index.js +24 -0
  31. package/dist/server/request-context.d.ts +27 -0
  32. package/dist/server/request-context.d.ts.map +1 -0
  33. package/dist/server/request-context.js +42 -0
  34. package/dist/server/request-middleware.d.ts +14 -0
  35. package/dist/server/request-middleware.d.ts.map +1 -0
  36. package/dist/server/request-middleware.js +82 -0
  37. package/dist/server/types.d.ts +13 -0
  38. package/dist/server/types.d.ts.map +1 -0
  39. package/dist/server/types.js +2 -0
  40. package/dist/shared/client-types.d.ts +63 -0
  41. package/dist/shared/client-types.d.ts.map +1 -0
  42. package/dist/shared/client-types.js +7 -0
  43. package/dist/shared/constants.d.ts +7 -0
  44. package/dist/shared/constants.d.ts.map +1 -0
  45. package/dist/shared/constants.js +9 -0
  46. package/dist/shared/generate-request-id.d.ts +10 -0
  47. package/dist/shared/generate-request-id.d.ts.map +1 -0
  48. package/dist/shared/generate-request-id.js +21 -0
  49. package/dist/shared/index.d.ts +8 -0
  50. package/dist/shared/index.d.ts.map +1 -0
  51. package/dist/shared/index.js +29 -0
  52. package/dist/shared/middleware/auth.d.ts +39 -0
  53. package/dist/shared/middleware/auth.d.ts.map +1 -0
  54. package/dist/shared/middleware/auth.js +164 -0
  55. package/dist/shared/middleware/default.d.ts +29 -0
  56. package/dist/shared/middleware/default.d.ts.map +1 -0
  57. package/dist/shared/middleware/default.js +67 -0
  58. package/dist/shared/middleware/index.d.ts +6 -0
  59. package/dist/shared/middleware/index.d.ts.map +1 -0
  60. package/dist/shared/middleware/index.js +21 -0
  61. package/dist/shared/middleware/safe-response.d.ts +22 -0
  62. package/dist/shared/middleware/safe-response.d.ts.map +1 -0
  63. package/dist/shared/middleware/safe-response.js +41 -0
  64. package/dist/shared/middleware/tracing.d.ts +23 -0
  65. package/dist/shared/middleware/tracing.d.ts.map +1 -0
  66. package/dist/shared/middleware/tracing.js +67 -0
  67. package/dist/shared/middleware/utils.d.ts +4 -0
  68. package/dist/shared/middleware/utils.d.ts.map +1 -0
  69. package/dist/shared/middleware/utils.js +13 -0
  70. package/dist/shared/middleware/validation.d.ts +43 -0
  71. package/dist/shared/middleware/validation.d.ts.map +1 -0
  72. package/dist/shared/middleware/validation.js +42 -0
  73. package/dist/shared/sanitize-url.d.ts +3 -0
  74. package/dist/shared/sanitize-url.d.ts.map +1 -0
  75. package/dist/shared/sanitize-url.js +12 -0
  76. package/dist/shared/types.d.ts +10 -0
  77. package/dist/shared/types.d.ts.map +1 -0
  78. package/dist/shared/types.js +2 -0
  79. package/package.json +98 -0
  80. package/server.d.ts +1 -0
  81. package/server.js +1 -0
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTracingMiddleware = createTracingMiddleware;
4
+ const constants_1 = require("../constants");
5
+ const generate_request_id_1 = require("../generate-request-id");
6
+ const sanitize_url_1 = require("../sanitize-url");
7
+ const utils_1 = require("./utils");
8
+ /**
9
+ * Create middleware that injects tracing headers and optionally logs
10
+ * requests, responses, and errors.
11
+ *
12
+ * Headers injected (only if not already present):
13
+ * - ts-request-id (auto-generates UUID if not provided)
14
+ * - ts-session-id (if provided)
15
+ * - ts-initiating-service-name (if provided)
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * client.use(createTracingMiddleware({
20
+ * requestId: () => getRequestId(),
21
+ * sessionId: () => getRequestContext().sessionId,
22
+ * serviceName: 'my-service',
23
+ * logger: console,
24
+ * }))
25
+ * ```
26
+ */
27
+ function createTracingMiddleware(options) {
28
+ const logger = options?.logger;
29
+ return {
30
+ onRequest({ request, schemaPath }) {
31
+ (0, utils_1.setIfAbsent)(request, constants_1.REQUEST_ID_HEADER, () => (0, utils_1.resolve)(options?.requestId) ?? (0, generate_request_id_1.generateRequestId)());
32
+ (0, utils_1.setIfAbsent)(request, constants_1.SESSION_ID_HEADER, options?.sessionId);
33
+ (0, utils_1.setIfAbsent)(request, constants_1.INITIATING_SERVICE_NAME_HEADER, options?.serviceName);
34
+ if (logger) {
35
+ logger.debug('Outgoing request', {
36
+ requestId: request.headers.get(constants_1.REQUEST_ID_HEADER),
37
+ method: request.method,
38
+ path: (0, sanitize_url_1.sanitizeUrl)(request.url),
39
+ schemaPath,
40
+ });
41
+ }
42
+ return request;
43
+ },
44
+ onResponse({ request, response, schemaPath }) {
45
+ if (logger) {
46
+ logger.debug('Response received', {
47
+ requestId: request.headers.get(constants_1.REQUEST_ID_HEADER),
48
+ method: request.method,
49
+ path: (0, sanitize_url_1.sanitizeUrl)(request.url),
50
+ schemaPath,
51
+ status: response.status,
52
+ });
53
+ }
54
+ },
55
+ onError({ request, error, schemaPath }) {
56
+ if (logger) {
57
+ logger.error('Request failed', {
58
+ requestId: request.headers.get(constants_1.REQUEST_ID_HEADER),
59
+ method: request.method,
60
+ path: (0, sanitize_url_1.sanitizeUrl)(request.url),
61
+ schemaPath,
62
+ error: error instanceof Error ? error.message : String(error),
63
+ });
64
+ }
65
+ },
66
+ };
67
+ }
@@ -0,0 +1,4 @@
1
+ import type { HeaderValue } from '../types';
2
+ export declare function resolve(value: HeaderValue | undefined): string | undefined;
3
+ export declare function setIfAbsent(request: Request, header: string, value: HeaderValue | undefined): void;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/shared/middleware/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,UAAU,CAAC;AAE1C,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAKlG"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolve = resolve;
4
+ exports.setIfAbsent = setIfAbsent;
5
+ function resolve(value) {
6
+ return typeof value === 'function' ? value() : value;
7
+ }
8
+ function setIfAbsent(request, header, value) {
9
+ const resolved = resolve(value);
10
+ if (resolved && !request.headers.has(header)) {
11
+ request.headers.set(header, resolved);
12
+ }
13
+ }
@@ -0,0 +1,43 @@
1
+ import type { Middleware } from 'openapi-fetch';
2
+ /**
3
+ * Any object with a `.parse()` method, compatible with both Zod 3 and Zod 4.
4
+ */
5
+ export interface Parseable {
6
+ parse(data: unknown): unknown;
7
+ }
8
+ /**
9
+ * A map of "METHOD /path" → schema for request body validation.
10
+ *
11
+ * Values must have a `.parse()` method (any Zod version works).
12
+ *
13
+ * Keys use the OpenAPI path template format, e.g.:
14
+ * "POST /v1/dataapps/apps/manage"
15
+ * "PUT /v1/dataapps/apps/{id}/labels"
16
+ */
17
+ export type RequestBodySchemaMap = Record<string, Parseable>;
18
+ export interface RequestValidationMiddlewareOptions {
19
+ /** Map of "METHOD /path" → Zod schema for request body validation. */
20
+ schemas: RequestBodySchemaMap;
21
+ }
22
+ /**
23
+ * Create openapi-fetch middleware that validates request bodies against
24
+ * Zod schemas before the request is sent over the wire.
25
+ *
26
+ * If the request body contains malformed JSON, `JSON.parse()` throws a
27
+ * `SyntaxError` and the request is never sent. If JSON parsing succeeds but
28
+ * schema validation fails, the schema's `.parse()` method throws (e.g. a
29
+ * `ZodError`) and the request is never sent.
30
+ * Endpoints without a matching schema are passed through without validation.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import createClient from 'openapi-fetch';
35
+ * import {createRequestValidationMiddleware} from '@tetrascience-npm/request';
36
+ * import {requestBodySchemas} from './generated/request-schemas';
37
+ *
38
+ * const client = createClient<paths>({baseUrl: '...'});
39
+ * client.use(createRequestValidationMiddleware({schemas: requestBodySchemas}));
40
+ * ```
41
+ */
42
+ export declare function createRequestValidationMiddleware(options: RequestValidationMiddlewareOptions): Middleware;
43
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/shared/middleware/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE7D,MAAM,WAAW,kCAAkC;IAClD,sEAAsE;IACtE,OAAO,EAAE,oBAAoB,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,kCAAkC,GAAG,UAAU,CAqBzG"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRequestValidationMiddleware = createRequestValidationMiddleware;
4
+ /**
5
+ * Create openapi-fetch middleware that validates request bodies against
6
+ * Zod schemas before the request is sent over the wire.
7
+ *
8
+ * If the request body contains malformed JSON, `JSON.parse()` throws a
9
+ * `SyntaxError` and the request is never sent. If JSON parsing succeeds but
10
+ * schema validation fails, the schema's `.parse()` method throws (e.g. a
11
+ * `ZodError`) and the request is never sent.
12
+ * Endpoints without a matching schema are passed through without validation.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import createClient from 'openapi-fetch';
17
+ * import {createRequestValidationMiddleware} from '@tetrascience-npm/request';
18
+ * import {requestBodySchemas} from './generated/request-schemas';
19
+ *
20
+ * const client = createClient<paths>({baseUrl: '...'});
21
+ * client.use(createRequestValidationMiddleware({schemas: requestBodySchemas}));
22
+ * ```
23
+ */
24
+ function createRequestValidationMiddleware(options) {
25
+ const { schemas } = options;
26
+ return {
27
+ async onRequest({ request, schemaPath }) {
28
+ const key = `${request.method} ${schemaPath}`;
29
+ const schema = schemas[key];
30
+ if (!schema)
31
+ return request;
32
+ const cloned = request.clone();
33
+ const rawText = await cloned.text();
34
+ if (rawText === '') {
35
+ return request;
36
+ }
37
+ const body = JSON.parse(rawText);
38
+ schema.parse(body);
39
+ return request;
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,3 @@
1
+ /** Extract pathname from a URL, stripping query string and hash. */
2
+ export declare function sanitizeUrl(url: string): string;
3
+ //# sourceMappingURL=sanitize-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-url.d.ts","sourceRoot":"","sources":["../../src/shared/sanitize-url.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM/C"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitizeUrl = sanitizeUrl;
4
+ /** Extract pathname from a URL, stripping query string and hash. */
5
+ function sanitizeUrl(url) {
6
+ try {
7
+ return new URL(url).pathname;
8
+ }
9
+ catch {
10
+ return url.split(/[?#]/)[0];
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ /** Logger interface for request tracking middleware. */
2
+ export interface RequestTrackingLogger {
3
+ info(message: string, meta?: Record<string, unknown>): void;
4
+ warn(message: string, meta?: Record<string, unknown>): void;
5
+ error(message: string, meta?: Record<string, unknown>): void;
6
+ debug(message: string, meta?: Record<string, unknown>): void;
7
+ }
8
+ /** A header value: static string or function resolved per-request. */
9
+ export type HeaderValue = string | (() => string | undefined);
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7D;AAED,sEAAsE;AACtE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@tetrascience-npm/request",
3
+ "version": "0.2.0-beta.106.2",
4
+ "description": "Request tracking middleware for TetraScience services and data apps (client + server).",
5
+ "license": "Apache-2.0",
6
+ "packageManager": "yarn@4.1.0",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "generate-request-schemas": "dist/cli/generate-schemas.js",
11
+ "generate-service-client": "dist/cli/generate-client.js"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./client": {
19
+ "types": "./dist/client/index.d.ts",
20
+ "default": "./dist/client/index.js"
21
+ },
22
+ "./server": {
23
+ "types": "./dist/server/index.d.ts",
24
+ "default": "./dist/server/index.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist/**/*.js",
29
+ "dist/**/*.d.ts",
30
+ "dist/**/*.d.ts.map",
31
+ "server.js",
32
+ "server.d.ts",
33
+ "client.js",
34
+ "client.d.ts"
35
+ ],
36
+ "peerDependencies": {
37
+ "js-yaml": ">=4.0.0",
38
+ "openapi-fetch": ">=0.17.0",
39
+ "openapi-typescript": ">=7.0.0",
40
+ "openapi-zod-client": ">=1.0.0",
41
+ "zod": ">=3.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "js-yaml": {
45
+ "optional": true
46
+ },
47
+ "openapi-typescript": {
48
+ "optional": true
49
+ },
50
+ "openapi-zod-client": {
51
+ "optional": true
52
+ },
53
+ "zod": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "resolutions": {
58
+ "vite": ">=7.3.2"
59
+ },
60
+ "devDependencies": {
61
+ "@types/js-yaml": "^4.0.9",
62
+ "@types/node": "^20.11.17",
63
+ "@typescript-eslint/eslint-plugin": "^5.59.11",
64
+ "@typescript-eslint/parser": "^5.59.11",
65
+ "@vitest/coverage-v8": "^3.1.1",
66
+ "eslint": "^8.49.0",
67
+ "eslint-config-prettier": "^9.0.0",
68
+ "husky": "^8.0.3",
69
+ "jsdom": "^26.1.0",
70
+ "lint-staged": "^14.0.1",
71
+ "openapi-fetch": "^0.17.0",
72
+ "prettier": "^3.0.3",
73
+ "typescript": "^5.3.3",
74
+ "vitest": "^3.1.1",
75
+ "zod": "^3.24.0"
76
+ },
77
+ "scripts": {
78
+ "lint": "eslint .",
79
+ "test": "vitest run",
80
+ "test:coverage": "vitest run --coverage",
81
+ "build": "tsc -p tsconfig.build.json",
82
+ "clean": "tsc -b --clean",
83
+ "check": "tsc --noEmit",
84
+ "prepare": "husky"
85
+ },
86
+ "prettier": {
87
+ "printWidth": 120,
88
+ "useTabs": true,
89
+ "bracketSpacing": false,
90
+ "trailingComma": "all"
91
+ },
92
+ "lint-staged": {
93
+ "*.{yml,json,ts,js,md,yaml,html}": "prettier --write"
94
+ },
95
+ "publishConfig": {
96
+ "access": "public"
97
+ }
98
+ }
package/server.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './dist/server/index';
package/server.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/server/index.js');