meridianjs 0.2.2 → 0.2.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +65 -160
  2. package/README.md +560 -93
  3. package/dist/analytics/collector.d.ts +28 -0
  4. package/dist/analytics/collector.d.ts.map +1 -0
  5. package/dist/analytics/collector.js +62 -0
  6. package/dist/analytics/collector.js.map +1 -0
  7. package/dist/analytics/index.d.ts +3 -0
  8. package/dist/analytics/index.d.ts.map +1 -0
  9. package/dist/analytics/index.js +2 -0
  10. package/dist/analytics/index.js.map +1 -0
  11. package/dist/capabilities/index.d.ts +3 -0
  12. package/dist/capabilities/index.d.ts.map +1 -0
  13. package/dist/capabilities/index.js +2 -0
  14. package/dist/capabilities/index.js.map +1 -0
  15. package/dist/capabilities/registry.d.ts +6 -0
  16. package/dist/capabilities/registry.d.ts.map +1 -0
  17. package/dist/capabilities/registry.js +61 -0
  18. package/dist/capabilities/registry.js.map +1 -0
  19. package/dist/core/pipeline.d.ts +3 -1
  20. package/dist/core/pipeline.d.ts.map +1 -1
  21. package/dist/core/pipeline.js +25 -0
  22. package/dist/core/pipeline.js.map +1 -1
  23. package/dist/core/types.d.ts +37 -1
  24. package/dist/core/types.d.ts.map +1 -1
  25. package/dist/core/types.js +4 -2
  26. package/dist/core/types.js.map +1 -1
  27. package/dist/debug/index.d.ts +3 -0
  28. package/dist/debug/index.d.ts.map +1 -0
  29. package/dist/debug/index.js +2 -0
  30. package/dist/debug/index.js.map +1 -0
  31. package/dist/debug/recorder.d.ts +32 -0
  32. package/dist/debug/recorder.d.ts.map +1 -0
  33. package/dist/debug/recorder.js +76 -0
  34. package/dist/debug/recorder.js.map +1 -0
  35. package/dist/generator/cli.d.ts +20 -0
  36. package/dist/generator/cli.d.ts.map +1 -0
  37. package/dist/generator/cli.js +56 -0
  38. package/dist/generator/cli.js.map +1 -0
  39. package/dist/generator/index.d.ts +9 -0
  40. package/dist/generator/index.d.ts.map +1 -0
  41. package/dist/generator/index.js +49 -0
  42. package/dist/generator/index.js.map +1 -0
  43. package/dist/generator/openapi.d.ts +13 -0
  44. package/dist/generator/openapi.d.ts.map +1 -0
  45. package/dist/generator/openapi.js +49 -0
  46. package/dist/generator/openapi.js.map +1 -0
  47. package/dist/generator/templates.d.ts +16 -0
  48. package/dist/generator/templates.d.ts.map +1 -0
  49. package/dist/generator/templates.js +290 -0
  50. package/dist/generator/templates.js.map +1 -0
  51. package/dist/index.d.ts +31 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +96 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/policies/builtin.d.ts +24 -0
  56. package/dist/policies/builtin.d.ts.map +1 -0
  57. package/dist/policies/builtin.js +94 -0
  58. package/dist/policies/builtin.js.map +1 -0
  59. package/dist/policies/index.d.ts +2 -0
  60. package/dist/policies/index.d.ts.map +1 -0
  61. package/dist/policies/index.js +2 -0
  62. package/dist/policies/index.js.map +1 -0
  63. package/dist/public.d.ts +15 -0
  64. package/dist/public.d.ts.map +1 -1
  65. package/dist/public.js +15 -0
  66. package/dist/public.js.map +1 -1
  67. package/dist/schema/index.d.ts +2 -0
  68. package/dist/schema/index.d.ts.map +1 -0
  69. package/dist/schema/index.js +2 -0
  70. package/dist/schema/index.js.map +1 -0
  71. package/dist/schema/monitor.d.ts +10 -0
  72. package/dist/schema/monitor.d.ts.map +1 -0
  73. package/dist/schema/monitor.js +46 -0
  74. package/dist/schema/monitor.js.map +1 -0
  75. package/dist/services/index.d.ts +2 -0
  76. package/dist/services/index.d.ts.map +1 -0
  77. package/dist/services/index.js +2 -0
  78. package/dist/services/index.js.map +1 -0
  79. package/dist/services/service-client.d.ts +34 -0
  80. package/dist/services/service-client.d.ts.map +1 -0
  81. package/dist/services/service-client.js +156 -0
  82. package/dist/services/service-client.js.map +1 -0
  83. package/dist/transactions/index.d.ts +3 -0
  84. package/dist/transactions/index.d.ts.map +1 -0
  85. package/dist/transactions/index.js +2 -0
  86. package/dist/transactions/index.js.map +1 -0
  87. package/dist/transactions/saga.d.ts +22 -0
  88. package/dist/transactions/saga.d.ts.map +1 -0
  89. package/dist/transactions/saga.js +58 -0
  90. package/dist/transactions/saga.js.map +1 -0
  91. package/dist/validation/drift-detector.d.ts.map +1 -1
  92. package/dist/validation/drift-detector.js +17 -8
  93. package/dist/validation/drift-detector.js.map +1 -1
  94. package/package.json +3 -2
@@ -0,0 +1,76 @@
1
+ export class DebugRecorder {
2
+ _enabled = false;
3
+ log = [];
4
+ pending = new Map();
5
+ rawData = new Map();
6
+ get enabled() {
7
+ return this._enabled;
8
+ }
9
+ enable() {
10
+ this._enabled = true;
11
+ }
12
+ disable() {
13
+ this._enabled = false;
14
+ }
15
+ recordRaw(requestId, options) {
16
+ if (!this._enabled)
17
+ return;
18
+ this.rawData.set(requestId, options);
19
+ }
20
+ logRequest(ctx) {
21
+ if (!this._enabled)
22
+ return;
23
+ this.pending.set(ctx.requestId, {
24
+ requestId: ctx.requestId,
25
+ provider: ctx.provider,
26
+ endpoint: ctx.endpoint,
27
+ method: ctx.method,
28
+ timestamp: ctx.timestamp,
29
+ });
30
+ }
31
+ logResponse(ctx) {
32
+ if (!this._enabled)
33
+ return;
34
+ const rec = this.pending.get(ctx.requestId);
35
+ if (rec) {
36
+ rec.statusCode = ctx.statusCode;
37
+ rec.duration = ctx.duration;
38
+ if (ctx.trace !== undefined)
39
+ rec.trace = ctx.trace;
40
+ const rawOpts = this.rawData.get(ctx.requestId);
41
+ if (rawOpts !== undefined) {
42
+ rec.options = rawOpts;
43
+ this.rawData.delete(ctx.requestId);
44
+ }
45
+ this.log.push(rec);
46
+ this.pending.delete(ctx.requestId);
47
+ }
48
+ }
49
+ logError(ctx) {
50
+ if (!this._enabled)
51
+ return;
52
+ const rec = this.pending.get(ctx.requestId);
53
+ if (rec) {
54
+ rec.duration = ctx.duration;
55
+ rec.error = ctx.error.message;
56
+ const rawOpts = this.rawData.get(ctx.requestId);
57
+ if (rawOpts !== undefined) {
58
+ rec.options = rawOpts;
59
+ this.rawData.delete(ctx.requestId);
60
+ }
61
+ this.log.push(rec);
62
+ this.pending.delete(ctx.requestId);
63
+ }
64
+ }
65
+ logWarning() { }
66
+ recordMetric(_metric) { }
67
+ recordings() {
68
+ return [...this.log];
69
+ }
70
+ clear() {
71
+ this.log = [];
72
+ this.pending.clear();
73
+ this.rawData.clear();
74
+ }
75
+ }
76
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/debug/recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Meridian Generator CLI
4
+ *
5
+ * Usage:
6
+ * npx meridian generate --provider <name> [options]
7
+ *
8
+ * Options:
9
+ * --provider <name> Provider name, e.g. "myapi" (required)
10
+ * --openapi <path> Path to an OpenAPI 3.x JSON spec
11
+ * --base-url <url> Base URL override
12
+ * --auth <type> Auth type: apiKey | bearer | basic | oauth2
13
+ * --output <dir> Output directory (default: src/providers/<name>)
14
+ *
15
+ * Examples:
16
+ * npx meridian generate --provider acme --base-url https://api.acme.com
17
+ * npx meridian generate --provider acme --openapi ./acme-openapi.json
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/generator/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;GAgBG"}
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Meridian Generator CLI
4
+ *
5
+ * Usage:
6
+ * npx meridian generate --provider <name> [options]
7
+ *
8
+ * Options:
9
+ * --provider <name> Provider name, e.g. "myapi" (required)
10
+ * --openapi <path> Path to an OpenAPI 3.x JSON spec
11
+ * --base-url <url> Base URL override
12
+ * --auth <type> Auth type: apiKey | bearer | basic | oauth2
13
+ * --output <dir> Output directory (default: src/providers/<name>)
14
+ *
15
+ * Examples:
16
+ * npx meridian generate --provider acme --base-url https://api.acme.com
17
+ * npx meridian generate --provider acme --openapi ./acme-openapi.json
18
+ */
19
+ import { generate } from "./index.js";
20
+ function parseArgs(argv) {
21
+ const out = {};
22
+ for (let i = 0; i < argv.length; i++) {
23
+ const arg = argv[i];
24
+ if (arg?.startsWith("--") && i + 1 < argv.length) {
25
+ const key = arg.slice(2);
26
+ out[key] = argv[i + 1] ?? "";
27
+ i++;
28
+ }
29
+ }
30
+ return out;
31
+ }
32
+ const args = process.argv.slice(2);
33
+ if (args[0] !== "generate" && args[0] !== "gen") {
34
+ process.stderr.write("Usage: meridian generate --provider <name> [--openapi <path>] [--base-url <url>] [--auth <type>]\n");
35
+ process.exit(1);
36
+ }
37
+ const flags = parseArgs(args.slice(1));
38
+ if (!flags.provider) {
39
+ process.stderr.write("Error: --provider is required\n");
40
+ process.stderr.write("Example: meridian generate --provider myapi --base-url https://api.myapi.com\n");
41
+ process.exit(1);
42
+ }
43
+ const opts = { provider: flags.provider };
44
+ if (flags.openapi !== undefined)
45
+ opts.openapi = flags.openapi;
46
+ if (flags["base-url"] !== undefined)
47
+ opts.baseUrl = flags["base-url"];
48
+ if (flags.auth !== undefined)
49
+ opts.auth = flags.auth;
50
+ if (flags.output !== undefined)
51
+ opts.output = flags.output;
52
+ generate(opts).catch((err) => {
53
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
54
+ process.exit(1);
55
+ });
56
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/generator/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACjD,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7B,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;IAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oGAAoG,CACrG,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gFAAgF,CACjF,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,IAAI,GAAqB,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC5D,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;IAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AAC9D,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,SAAS;IAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;AACtE,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;IAAE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAgD,CAAC;AACjG,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;IAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;AAE3D,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface GeneratorOptions {
2
+ provider: string;
3
+ openapi?: string;
4
+ baseUrl?: string;
5
+ auth?: "apiKey" | "bearer" | "basic" | "oauth2";
6
+ output?: string;
7
+ }
8
+ export declare function generate(opts: GeneratorOptions): Promise<void>;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDpE"}
@@ -0,0 +1,49 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { parseOpenAPI } from "./openapi.js";
4
+ import { generateAdapter, generateIndex, generatePagination, generateTest } from "./templates.js";
5
+ export async function generate(opts) {
6
+ const { provider } = opts;
7
+ const outputDir = opts.output ?? join("src", "providers", provider);
8
+ let ctx = {
9
+ provider,
10
+ baseUrl: opts.baseUrl ?? `https://api.${provider}.com`,
11
+ authType: opts.auth ?? "apiKey",
12
+ authKeyName: "apiKey",
13
+ endpoints: [],
14
+ };
15
+ if (opts.openapi) {
16
+ const raw = await readFile(opts.openapi, "utf-8");
17
+ const spec = parseOpenAPI(JSON.parse(raw));
18
+ ctx = {
19
+ provider,
20
+ baseUrl: opts.baseUrl ?? spec.baseUrl,
21
+ authType: opts.auth ?? spec.authType,
22
+ authKeyName: spec.authKeyName,
23
+ endpoints: spec.endpoints,
24
+ };
25
+ }
26
+ await mkdir(outputDir, { recursive: true });
27
+ await Promise.all([
28
+ writeFile(join(outputDir, "adapter.ts"), generateAdapter(ctx), "utf-8"),
29
+ writeFile(join(outputDir, "adapter.test.ts"), generateTest(ctx), "utf-8"),
30
+ writeFile(join(outputDir, "pagination.ts"), generatePagination(ctx), "utf-8"),
31
+ writeFile(join(outputDir, "index.ts"), generateIndex(ctx), "utf-8"),
32
+ ]);
33
+ const lines = [
34
+ `✓ Generated adapter for "${provider}" → ${outputDir}/`,
35
+ " adapter.ts core adapter (auth, error mapping, rate-limit headers)",
36
+ " adapter.test.ts 8 tests that pass immediately",
37
+ " pagination.ts pagination strategy stub",
38
+ " index.ts barrel export",
39
+ "",
40
+ "Next steps:",
41
+ ` 1. Add "${provider}" to BUILTIN_ADAPTER_CLASSES in src/index.ts`,
42
+ " 2. Fill in the TODO comments in adapter.ts and pagination.ts",
43
+ ` 3. npm test -- --reporter=verbose src/providers/${provider}/adapter.test.ts`,
44
+ ];
45
+ for (const line of lines) {
46
+ process.stdout.write(`${line}\n`);
47
+ }
48
+ }
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAWlG,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAsB;IACnD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEpE,IAAI,GAAG,GAAqB;QAC1B,QAAQ;QACR,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,eAAe,QAAQ,MAAM;QACtD,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,QAAQ;QAC/B,WAAW,EAAE,QAAQ;QACrB,SAAS,EAAE,EAAE;KACd,CAAC;IAEF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,GAAG,GAAG;YACJ,QAAQ;YACR,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;YACrC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ;YACpC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5C,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QACvE,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QACzE,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QAC7E,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;KACpE,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG;QACZ,6BAA6B,QAAQ,OAAO,SAAS,GAAG;QACxD,4EAA4E;QAC5E,mDAAmD;QACnD,8CAA8C;QAC9C,mCAAmC;QACnC,EAAE;QACF,aAAa;QACb,aAAa,QAAQ,8CAA8C;QACnE,gEAAgE;QAChE,qDAAqD,QAAQ,kBAAkB;KAChF,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IACpC,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface ParsedSpec {
2
+ title: string;
3
+ baseUrl: string;
4
+ authType: "apiKey" | "bearer" | "basic" | "oauth2";
5
+ authKeyName: string;
6
+ endpoints: Array<{
7
+ method: string;
8
+ path: string;
9
+ operationId?: string;
10
+ }>;
11
+ }
12
+ export declare function parseOpenAPI(doc: unknown): ParsedSpec;
13
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/generator/openapi.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAkDrD"}
@@ -0,0 +1,49 @@
1
+ export function parseOpenAPI(doc) {
2
+ const spec = doc;
3
+ const title = spec.info?.title ?? "Unknown";
4
+ let baseUrl = "https://api.example.com";
5
+ if (spec.servers?.[0]?.url) {
6
+ baseUrl = spec.servers[0].url;
7
+ }
8
+ else if (spec.host) {
9
+ baseUrl = `https://${spec.host}${spec.basePath ?? ""}`;
10
+ }
11
+ let authType = "apiKey";
12
+ let authKeyName = "apiKey";
13
+ const schemes = spec.components?.securitySchemes ?? spec.securityDefinitions ?? {};
14
+ for (const scheme of Object.values(schemes)) {
15
+ if (scheme.type === "http" && scheme.scheme === "basic") {
16
+ authType = "basic";
17
+ break;
18
+ }
19
+ if (scheme.type === "http" && scheme.scheme === "bearer") {
20
+ authType = "bearer";
21
+ break;
22
+ }
23
+ if (scheme.type === "oauth2") {
24
+ authType = "oauth2";
25
+ break;
26
+ }
27
+ if (scheme.type === "apiKey") {
28
+ authType = "apiKey";
29
+ authKeyName = scheme.name ?? "x-api-key";
30
+ }
31
+ }
32
+ const endpoints = [];
33
+ const httpMethods = new Set(["get", "post", "put", "patch", "delete"]);
34
+ for (const [path, methods] of Object.entries(spec.paths ?? {})) {
35
+ for (const [method, op] of Object.entries(methods)) {
36
+ if (httpMethods.has(method)) {
37
+ const ep = {
38
+ method: method.toUpperCase(),
39
+ path,
40
+ };
41
+ if (op.operationId !== undefined)
42
+ ep.operationId = op.operationId;
43
+ endpoints.push(ep);
44
+ }
45
+ }
46
+ }
47
+ return { title, baseUrl, authType, authKeyName, endpoints };
48
+ }
49
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/generator/openapi.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,IAAI,GAAG,GAAiB,CAAC;IAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,SAAS,CAAC;IAE5C,IAAI,OAAO,GAAG,yBAAyB,CAAC;IACxC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAC3B,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAChC,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,GAAG,WAAW,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;IACzD,CAAC;IAED,IAAI,QAAQ,GAA2B,QAAQ,CAAC;IAChD,IAAI,WAAW,GAAG,QAAQ,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,eAAe,IAAI,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC;IACnF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YACxD,QAAQ,GAAG,OAAO,CAAC;YACnB,MAAM;QACR,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACzD,QAAQ,GAAG,QAAQ,CAAC;YACpB,MAAM;QACR,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,QAAQ,GAAG,QAAQ,CAAC;YACpB,MAAM;QACR,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,QAAQ,GAAG,QAAQ,CAAC;YACpB,WAAW,GAAG,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/D,KAAK,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,MAAM,EAAE,GAA2D;oBACjE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;oBAC5B,IAAI;iBACL,CAAC;gBACF,IAAI,EAAE,CAAC,WAAW,KAAK,SAAS;oBAAE,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC;gBAClE,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface GeneratorContext {
2
+ provider: string;
3
+ baseUrl: string;
4
+ authType: "apiKey" | "bearer" | "basic" | "oauth2";
5
+ authKeyName: string;
6
+ endpoints: Array<{
7
+ method: string;
8
+ path: string;
9
+ operationId?: string;
10
+ }>;
11
+ }
12
+ export declare function generateAdapter(ctx: GeneratorContext): string;
13
+ export declare function generatePagination(ctx: GeneratorContext): string;
14
+ export declare function generateIndex(ctx: GeneratorContext): string;
15
+ export declare function generateTest(ctx: GeneratorContext): string;
16
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/generator/templates.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAwCD,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAqH7D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAiChE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAI3D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAoG1D"}
@@ -0,0 +1,290 @@
1
+ function pascal(name) {
2
+ return name
3
+ .split(/[-_\s]+/)
4
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
5
+ .join("");
6
+ }
7
+ function authHeaderLine(ctx) {
8
+ if (ctx.authType === "basic") {
9
+ return `"Authorization": \`Basic \${Buffer.from(\`\${authToken.token}:\${authToken.secret ?? ""}\`).toString("base64")}\``;
10
+ }
11
+ return '"Authorization": `Bearer ${authToken.token}`';
12
+ }
13
+ function authStrategyBody(ctx) {
14
+ const className = `${pascal(ctx.provider)}`;
15
+ if (ctx.authType === "basic") {
16
+ return ` const user = config.username ?? config.apiKey ?? "";
17
+ const pass = config.password ?? "";
18
+ if (!user) throw new Error("${className}: username or apiKey is required");
19
+ return { token: user, secret: pass };`;
20
+ }
21
+ return ` const key = config.apiKey ?? config.token ?? "";
22
+ if (!key) throw new Error("${className}: apiKey or token is required");
23
+ return { token: key };`;
24
+ }
25
+ function endpointComments(ctx) {
26
+ if (ctx.endpoints.length === 0)
27
+ return "";
28
+ const lines = ctx.endpoints
29
+ .slice(0, 20)
30
+ .map((e) => ` // ${e.method.padEnd(7)} ${e.path}${e.operationId ? ` (${e.operationId})` : ""}`)
31
+ .join("\n");
32
+ return `\n // Known endpoints from OpenAPI spec:\n${lines}\n`;
33
+ }
34
+ export function generateAdapter(ctx) {
35
+ const name = pascal(ctx.provider);
36
+ return `import { ResponseNormalizer } from "../../core/normalizer.js";
37
+ import type {
38
+ AdapterInput,
39
+ AuthConfig,
40
+ AuthToken,
41
+ BuiltRequest,
42
+ IdempotencyConfig,
43
+ NormalizedResponse,
44
+ PaginationStrategy,
45
+ ProviderAdapter,
46
+ RateLimitInfo,
47
+ RawResponse,
48
+ } from "../../core/types.js";
49
+ import { MeridianError, SDK_VERSION } from "../../core/types.js";
50
+ import { ${name}PaginationStrategy } from "./pagination.js";
51
+ ${endpointComments(ctx)}
52
+ export class ${name}Adapter implements ProviderAdapter {
53
+ private baseUrl: string;
54
+
55
+ constructor(baseUrl = "${ctx.baseUrl}") {
56
+ this.baseUrl = baseUrl;
57
+ }
58
+
59
+ buildRequest(input: AdapterInput): BuiltRequest {
60
+ const { endpoint, options, authToken, baseUrl } = input;
61
+ const effectiveBaseUrl = baseUrl ?? this.baseUrl;
62
+
63
+ const url = new URL(endpoint, effectiveBaseUrl);
64
+
65
+ if (options.query) {
66
+ for (const [key, value] of Object.entries(options.query)) {
67
+ url.searchParams.set(key, String(value));
68
+ }
69
+ }
70
+
71
+ const headers: Record<string, string> = {
72
+ ${authHeaderLine(ctx)},
73
+ "User-Agent": \`Meridian-SDK/\${SDK_VERSION}\`,
74
+ "Content-Type": "application/json",
75
+ ...options.headers,
76
+ };
77
+
78
+ let body: string | undefined;
79
+ const method = options.method ?? "GET";
80
+ if (options.body && method !== "GET" && method !== "HEAD") {
81
+ body = JSON.stringify(options.body);
82
+ }
83
+
84
+ const built: BuiltRequest = { url: url.toString(), method, headers };
85
+ if (body !== undefined) built.body = body;
86
+ return built;
87
+ }
88
+
89
+ parseResponse(raw: RawResponse): NormalizedResponse {
90
+ return new ResponseNormalizer("${ctx.provider}").normalize(raw);
91
+ }
92
+
93
+ parseError(raw: unknown): MeridianError {
94
+ if (typeof raw === "object" && raw !== null && "status" in raw) {
95
+ const status = (raw as { status: number }).status;
96
+ const body = (raw as { body?: unknown }).body;
97
+
98
+ // TODO: extract provider-specific error message from body
99
+ const message =
100
+ typeof body === "object" && body !== null && "message" in body
101
+ ? String((body as { message: unknown }).message)
102
+ : \`HTTP \${status}\`;
103
+
104
+ if (status === 401 || status === 403) {
105
+ return new MeridianError(message, "auth", "${ctx.provider}", false, "", {}, undefined, status);
106
+ }
107
+ if (status === 429) {
108
+ return new MeridianError(message, "rate_limit", "${ctx.provider}", true, "", {}, undefined, status);
109
+ }
110
+ if (status >= 400 && status < 500) {
111
+ return new MeridianError(message, "validation", "${ctx.provider}", false, "", {}, undefined, status);
112
+ }
113
+ if (status >= 500) {
114
+ return new MeridianError(message, "provider", "${ctx.provider}", true, "", {}, undefined, status);
115
+ }
116
+ }
117
+ if (raw instanceof Error) {
118
+ return new MeridianError(raw.message, "network", "${ctx.provider}", true);
119
+ }
120
+ return new MeridianError("Unknown error", "provider", "${ctx.provider}", false);
121
+ }
122
+
123
+ async authStrategy(config: AuthConfig): Promise<AuthToken> {
124
+ ${authStrategyBody(ctx)}
125
+ }
126
+
127
+ rateLimitPolicy(headers: Headers): RateLimitInfo {
128
+ // TODO: verify ${ctx.provider} rate-limit header names
129
+ const reset = Number(headers.get("x-ratelimit-reset") ?? headers.get("x-rate-limit-reset") ?? 0);
130
+ return {
131
+ limit: Number(headers.get("x-ratelimit-limit") ?? headers.get("x-rate-limit-limit") ?? 100),
132
+ remaining: Number(
133
+ headers.get("x-ratelimit-remaining") ?? headers.get("x-rate-limit-remaining") ?? 100,
134
+ ),
135
+ reset: new Date(reset > 1_000_000_000 ? reset * 1000 : Date.now() + 60_000),
136
+ };
137
+ }
138
+
139
+ paginationStrategy(): PaginationStrategy {
140
+ return new ${name}PaginationStrategy();
141
+ }
142
+
143
+ getIdempotencyConfig(): IdempotencyConfig {
144
+ return {
145
+ defaultSafeOperations: new Set(["GET", "HEAD"]),
146
+ operationOverrides: new Map(),
147
+ };
148
+ }
149
+ }
150
+ `;
151
+ }
152
+ export function generatePagination(ctx) {
153
+ const name = pascal(ctx.provider);
154
+ return `import type { PaginationStrategy, RawResponse, RequestOptions } from "../../core/types.js";
155
+
156
+ export class ${name}PaginationStrategy implements PaginationStrategy {
157
+ extractCursor(response: RawResponse): string | null {
158
+ // TODO: update with actual ${ctx.provider} pagination field names
159
+ const body = response.body as Record<string, unknown>;
160
+ return (body.next_cursor as string) ?? (body.cursor as string) ?? (body.next as string) ?? null;
161
+ }
162
+
163
+ extractTotal(response: RawResponse): number | null {
164
+ const body = response.body as Record<string, unknown>;
165
+ return typeof body.total === "number" ? body.total : null;
166
+ }
167
+
168
+ hasNext(response: RawResponse): boolean {
169
+ return this.extractCursor(response) !== null;
170
+ }
171
+
172
+ buildNextRequest(
173
+ endpoint: string,
174
+ options: RequestOptions,
175
+ cursor: string,
176
+ ): { endpoint: string; options: RequestOptions } {
177
+ // TODO: update with the actual ${ctx.provider} cursor param name
178
+ return {
179
+ endpoint,
180
+ options: { ...options, query: { ...options.query, cursor } },
181
+ };
182
+ }
183
+ }
184
+ `;
185
+ }
186
+ export function generateIndex(ctx) {
187
+ const name = pascal(ctx.provider);
188
+ return `export { ${name}Adapter } from "./adapter.js";
189
+ `;
190
+ }
191
+ export function generateTest(ctx) {
192
+ const name = pascal(ctx.provider);
193
+ const authArg = ctx.authType === "basic"
194
+ ? "{ username: 'testuser', password: 'testpass' }"
195
+ : "{ apiKey: 'test-key' }";
196
+ return `import { describe, expect, it } from "vitest";
197
+ import { ${name}Adapter } from "./adapter.js";
198
+
199
+ const adapter = new ${name}Adapter();
200
+
201
+ describe("${name}Adapter", () => {
202
+ describe("buildRequest", () => {
203
+ it("builds a GET request with auth header", () => {
204
+ const req = adapter.buildRequest({
205
+ endpoint: "/test",
206
+ options: { method: "GET" },
207
+ authToken: { token: "test-key" },
208
+ });
209
+ expect(req.url).toContain("/test");
210
+ expect(req.method).toBe("GET");
211
+ expect(req.headers["Authorization"]).toBeDefined();
212
+ });
213
+
214
+ it("appends query parameters", () => {
215
+ const req = adapter.buildRequest({
216
+ endpoint: "/test",
217
+ options: { method: "GET", query: { page: 1, limit: 10 } },
218
+ authToken: { token: "test-key" },
219
+ });
220
+ expect(req.url).toContain("page=1");
221
+ expect(req.url).toContain("limit=10");
222
+ });
223
+
224
+ it("serialises POST body as JSON", () => {
225
+ const req = adapter.buildRequest({
226
+ endpoint: "/test",
227
+ options: { method: "POST", body: { name: "test" } },
228
+ authToken: { token: "test-key" },
229
+ });
230
+ expect(req.body).toBe(JSON.stringify({ name: "test" }));
231
+ });
232
+
233
+ it("omits body for GET requests", () => {
234
+ const req = adapter.buildRequest({
235
+ endpoint: "/test",
236
+ options: { method: "GET", body: { should: "be-ignored" } },
237
+ authToken: { token: "test-key" },
238
+ });
239
+ expect(req.body).toBeUndefined();
240
+ });
241
+ });
242
+
243
+ describe("parseError", () => {
244
+ it("returns auth error for 401", () => {
245
+ const err = adapter.parseError({ status: 401, headers: new Headers(), body: {} });
246
+ expect(err.category).toBe("auth");
247
+ expect(err.retryable).toBe(false);
248
+ });
249
+
250
+ it("returns auth error for 403", () => {
251
+ const err = adapter.parseError({ status: 403, headers: new Headers(), body: {} });
252
+ expect(err.category).toBe("auth");
253
+ });
254
+
255
+ it("returns rate_limit error for 429", () => {
256
+ const err = adapter.parseError({ status: 429, headers: new Headers(), body: {} });
257
+ expect(err.category).toBe("rate_limit");
258
+ expect(err.retryable).toBe(true);
259
+ });
260
+
261
+ it("returns retryable provider error for 500", () => {
262
+ const err = adapter.parseError({ status: 500, headers: new Headers(), body: {} });
263
+ expect(err.category).toBe("provider");
264
+ expect(err.retryable).toBe(true);
265
+ });
266
+
267
+ it("extracts message from error body", () => {
268
+ const err = adapter.parseError({
269
+ status: 400,
270
+ headers: new Headers(),
271
+ body: { message: "Invalid request" },
272
+ });
273
+ expect(err.message).toBe("Invalid request");
274
+ });
275
+ });
276
+
277
+ describe("authStrategy", () => {
278
+ it("throws when no credentials provided", async () => {
279
+ await expect(adapter.authStrategy({})).rejects.toThrow();
280
+ });
281
+
282
+ it("resolves token from config", async () => {
283
+ const token = await adapter.authStrategy(${authArg});
284
+ expect(token.token).toBeTruthy();
285
+ });
286
+ });
287
+ });
288
+ `;
289
+ }
290
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/generator/templates.ts"],"names":[],"mappings":"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"}