@krak-stack/registry 0.1.17 → 0.1.18

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.
@@ -1,4 +1,4 @@
1
- import { Context, Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect";
1
+ import { Cause, Context, Effect, FileSystem, Layer, Path, Stdio, Terminal } from "effect";
2
2
  import { Command } from "effect/unstable/cli";
3
3
  import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";
4
4
  import { ApiClient, type ApiClientService } from "./httpapi-client.js";
@@ -19,5 +19,6 @@ export declare const printHttpApiCliResult: (response: unknown, operation: HttpA
19
19
  export declare const makeHttpApiCliCommand: () => Effect.Effect<Command.Command<string, {}, {}, unknown, never>, never, ApiClient | HttpApiSpec>;
20
20
  export declare const httpApiCliEnvironmentLayer: (args: ReadonlyArray<string>) => Layer.Layer<ChildProcessSpawner | FileSystem.FileSystem | Path.Path | Stdio.Stdio | Terminal.Terminal, never, never>;
21
21
  export declare const httpApiCli: (args?: string[]) => Effect.Effect<void, unknown, HttpApiCli | Command.Environment>;
22
+ export declare const formatHttpApiCliCause: <E>(cause: Cause.Cause<E>) => string;
22
23
  export declare const runHttpApiCli: <E>(layer: Layer.Layer<HttpApiCli, E>, args?: string[]) => void;
23
24
  export {};
@@ -1,8 +1,10 @@
1
1
  // ../../src/lib/httpapi-cli.ts
2
2
  import {
3
+ Cause,
3
4
  Console,
4
5
  Context as Context3,
5
6
  Effect as Effect3,
7
+ Exit,
6
8
  FileSystem,
7
9
  Layer as Layer3,
8
10
  Path,
@@ -15,13 +17,22 @@ import { Command, Flag } from "effect/unstable/cli";
15
17
  import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";
16
18
 
17
19
  // ../../src/lib/httpapi-client.ts
18
- import { Context, Effect, Layer, Schema } from "effect";
20
+ import { Context, Effect, Layer, Schema, SchemaTransformation } from "effect";
19
21
  import { HttpClient } from "effect/unstable/http";
20
22
  import {
21
- HttpApiClient as EffectHttpApiClient
23
+ HttpApi,
24
+ HttpApiClient as EffectHttpApiClient,
25
+ OpenApi
22
26
  } from "effect/unstable/httpapi";
27
+ var UndefinedFromNull = Schema.Null.pipe(Schema.decodeTo(Schema.Undefined, SchemaTransformation.transform({
28
+ decode: () => {
29
+ return;
30
+ },
31
+ encode: () => null
32
+ })));
23
33
  var HttpApiOperationResultValue = Schema.suspend(() => Schema.Union([
24
34
  Schema.Null,
35
+ UndefinedFromNull,
25
36
  Schema.String,
26
37
  Schema.Number,
27
38
  Schema.Boolean,
@@ -35,6 +46,37 @@ var HttpApiOperationResult = Schema.Union([
35
46
  Schema.Undefined
36
47
  ]).annotate({ identifier: "HttpApiOperationResult" });
37
48
  var encodeHttpApiOperationResult = Effect.fn("HttpApiClient.encodeOperationResult")((result) => Schema.encodeUnknownEffect(HttpApiOperationResult)(result).pipe(Effect.map((encoded) => encoded ?? null), Effect.mapError((cause) => new Error("HTTP API result is not serializable", { cause }))));
49
+ var reflectedSchema = (schema) => Schema.make(schema.ast);
50
+ var operationResultSchemas = (api) => {
51
+ const schemas = new Map;
52
+ HttpApi.reflect(api, {
53
+ onGroup: () => {
54
+ return;
55
+ },
56
+ onEndpoint: ({ endpoint, group, successes }) => {
57
+ const operationId = Context.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
58
+ const operationSchemas = Array.from(successes.values()).flat().map(reflectedSchema);
59
+ if (operationSchemas.length === 1 && operationSchemas[0]) {
60
+ schemas.set(operationId, operationSchemas[0]);
61
+ } else if (operationSchemas.length > 1) {
62
+ schemas.set(operationId, Schema.Union(operationSchemas));
63
+ }
64
+ }
65
+ });
66
+ return schemas;
67
+ };
68
+ var makeHttpApiOperationResultEncoder = (api) => {
69
+ const schemas = operationResultSchemas(api);
70
+ return Effect.fn("HttpApiClient.encodeOperationResultWithSchema")((result, operation) => {
71
+ const operationId = operation.operation.operationId;
72
+ const schema = operationId ? schemas.get(operationId) : undefined;
73
+ if (!schema)
74
+ return encodeHttpApiOperationResult(result);
75
+ return Schema.encodeUnknownEffect(schema)(result).pipe(Effect.flatMap(encodeHttpApiOperationResult), Effect.mapError((cause) => new Error("HTTP API result does not match its success schema", {
76
+ cause
77
+ })));
78
+ });
79
+ };
38
80
  var GeneratedOperation = Schema.declare((value) => value instanceof Function).annotate({ identifier: "GeneratedOperation" });
39
81
  var GeneratedOperationEffect = Schema.declare((value) => Effect.isEffect(value)).annotate({ identifier: "GeneratedOperationEffect" });
40
82
  var makeGeneratedClient = (api, http, baseUrl) => EffectHttpApiClient.makeWith(api, {
@@ -70,9 +112,10 @@ var executeGeneratedOperation = Effect.fn("HttpApiClient.executeGeneratedOperati
70
112
  class ApiClient extends Context.Service()("ApiClient") {
71
113
  static layer = (config) => Layer.effect(this, Effect.gen(function* () {
72
114
  const http = yield* HttpClient.HttpClient;
115
+ const encodeResult = makeHttpApiOperationResultEncoder(config.api);
73
116
  const client = yield* makeGeneratedClient(config.api, http, config.baseUrl);
74
117
  return {
75
- encodeResult: config.encodeResult ?? ((result) => encodeHttpApiOperationResult(result)),
118
+ encodeResult: config.encodeResult ?? ((result, operation) => encodeResult(result, operation)),
76
119
  execute: Effect.fn("ApiClient.execute")(function* (options) {
77
120
  return yield* executeGeneratedOperation(client, options);
78
121
  })
@@ -90,7 +133,7 @@ import {
90
133
  Schema as Schema2,
91
134
  SchemaRepresentation
92
135
  } from "effect";
93
- import { HttpApi as HttpApi2, OpenApi } from "effect/unstable/httpapi";
136
+ import { HttpApi as HttpApi2, OpenApi as OpenApi2 } from "effect/unstable/httpapi";
94
137
  var JsonObjectSchema = Schema2.Record(Schema2.String, Schema2.Json).annotate({
95
138
  identifier: "HttpJsonObject",
96
139
  title: "HTTP JSON object",
@@ -263,7 +306,7 @@ var decodeHttpApiOperationInput = Effect2.fn("Http.decodeApiOperationInput")(fun
263
306
  query: pickParameters("query")
264
307
  };
265
308
  });
266
- var reflectedSchema = (schema) => Schema2.make(schema.ast);
309
+ var reflectedSchema2 = (schema) => Schema2.make(schema.ast);
267
310
  var reflectedOperationInputSchemas = (api) => {
268
311
  const schemas = new Map;
269
312
  HttpApi2.reflect(api, {
@@ -271,17 +314,17 @@ var reflectedOperationInputSchemas = (api) => {
271
314
  return;
272
315
  },
273
316
  onEndpoint: ({ endpoint, group }) => {
274
- const operationId = Context2.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
317
+ const operationId = Context2.getOrElse(endpoint.annotations, OpenApi2.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
275
318
  const fields = {};
276
319
  if (endpoint.params)
277
- fields.params = reflectedSchema(endpoint.params);
320
+ fields.params = reflectedSchema2(endpoint.params);
278
321
  if (endpoint.query) {
279
- fields.query = Schema2.optionalKey(reflectedSchema(endpoint.query));
322
+ fields.query = Schema2.optionalKey(reflectedSchema2(endpoint.query));
280
323
  }
281
324
  if (endpoint.headers) {
282
- fields.headers = Schema2.optionalKey(reflectedSchema(endpoint.headers));
325
+ fields.headers = Schema2.optionalKey(reflectedSchema2(endpoint.headers));
283
326
  }
284
- const payloadSchemas = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema));
327
+ const payloadSchemas = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema2));
285
328
  if (payloadSchemas.length === 1 && payloadSchemas[0]) {
286
329
  fields.body = payloadSchemas[0];
287
330
  } else if (payloadSchemas.length > 1) {
@@ -313,7 +356,7 @@ class HttpApiSpec extends Context2.Service()("HttpApiSpec", {
313
356
  if (!HttpApi2.isHttpApi(api)) {
314
357
  throw new Error("HttpApiSpec requires a valid HttpApi");
315
358
  }
316
- const spec = OpenApi.fromApi(api);
359
+ const spec = OpenApi2.fromApi(api);
317
360
  const reflectedSchemas = reflectedOperationInputSchemas(api);
318
361
  const operations = httpApiOperations({
319
362
  spec,
@@ -477,11 +520,17 @@ var httpApiCli = (args = process.argv.slice(2)) => Effect3.gen(function* () {
477
520
  const cli = yield* HttpApiCli;
478
521
  return yield* cli.run(args);
479
522
  });
523
+ var formatHttpApiCliCause = Cause.pretty;
480
524
  var runHttpApiCli = (layer, args = process.argv.slice(2)) => {
481
- Effect3.runPromise(httpApiCli(args).pipe(Effect3.provide(layer), Effect3.provide(httpApiCliEnvironmentLayer(args)))).catch((error) => {
482
- console.error(error instanceof Error ? error.message : error);
483
- process.exit(1);
484
- });
525
+ Effect3.runPromiseExit(httpApiCli(args).pipe(Effect3.provide(layer), Effect3.provide(httpApiCliEnvironmentLayer(args)))).then(Exit.match({
526
+ onSuccess: () => {
527
+ return;
528
+ },
529
+ onFailure: (cause) => {
530
+ console.error(formatHttpApiCliCause(cause));
531
+ process.exitCode = 1;
532
+ }
533
+ }));
485
534
  };
486
535
  export {
487
536
  runHttpApiCli,
@@ -489,5 +538,6 @@ export {
489
538
  makeHttpApiCliCommand,
490
539
  httpApiCliEnvironmentLayer,
491
540
  httpApiCli,
541
+ formatHttpApiCliCause,
492
542
  HttpApiCli
493
543
  };
@@ -12,12 +12,13 @@ export type ApiClientExecuteOptions = {
12
12
  readonly operation: HttpApiOperationEntry;
13
13
  readonly input: HttpApiOperationInput;
14
14
  };
15
- export type HttpApiOperationResultValue = null | string | number | boolean | Date | Uint8Array | ReadonlyArray<HttpApiOperationResultValue> | {
15
+ export type HttpApiOperationResultValue = null | undefined | string | number | boolean | Date | Uint8Array | ReadonlyArray<HttpApiOperationResultValue> | {
16
16
  readonly [key: string]: HttpApiOperationResultValue;
17
17
  };
18
18
  export declare const HttpApiOperationResult: Schema.Union<readonly [Schema.Codec<HttpApiOperationResultValue, Json, never, never>, Schema.Undefined]>;
19
19
  export type HttpApiOperationResult = typeof HttpApiOperationResult.Type;
20
20
  export declare const encodeHttpApiOperationResult: (result: unknown) => Effect.Effect<string | number | boolean | Schema.JsonArray | Schema.JsonObject | null, Error, never>;
21
+ export declare const makeHttpApiOperationResultEncoder: <Id extends string, Groups extends HttpApiGroup.Constraint>(api: HttpApi.HttpApi<Id, Groups>) => (result: unknown, operation: HttpApiOperationEntry) => Effect.Effect<string | number | boolean | Schema.JsonArray | Schema.JsonObject | null, Error, never>;
21
22
  export type ApiClientService = {
22
23
  readonly encodeResult: (result: ErrorOptions["cause"], operation: HttpApiOperationEntry) => Effect.Effect<Json, Error>;
23
24
  readonly execute: (options: ApiClientExecuteOptions) => Effect.Effect<ErrorOptions["cause"], Error>;
@@ -1,11 +1,20 @@
1
1
  // ../../src/lib/httpapi-client.ts
2
- import { Context, Effect, Layer, Schema } from "effect";
2
+ import { Context, Effect, Layer, Schema, SchemaTransformation } from "effect";
3
3
  import { HttpClient } from "effect/unstable/http";
4
4
  import {
5
- HttpApiClient as EffectHttpApiClient
5
+ HttpApi,
6
+ HttpApiClient as EffectHttpApiClient,
7
+ OpenApi
6
8
  } from "effect/unstable/httpapi";
9
+ var UndefinedFromNull = Schema.Null.pipe(Schema.decodeTo(Schema.Undefined, SchemaTransformation.transform({
10
+ decode: () => {
11
+ return;
12
+ },
13
+ encode: () => null
14
+ })));
7
15
  var HttpApiOperationResultValue = Schema.suspend(() => Schema.Union([
8
16
  Schema.Null,
17
+ UndefinedFromNull,
9
18
  Schema.String,
10
19
  Schema.Number,
11
20
  Schema.Boolean,
@@ -19,6 +28,37 @@ var HttpApiOperationResult = Schema.Union([
19
28
  Schema.Undefined
20
29
  ]).annotate({ identifier: "HttpApiOperationResult" });
21
30
  var encodeHttpApiOperationResult = Effect.fn("HttpApiClient.encodeOperationResult")((result) => Schema.encodeUnknownEffect(HttpApiOperationResult)(result).pipe(Effect.map((encoded) => encoded ?? null), Effect.mapError((cause) => new Error("HTTP API result is not serializable", { cause }))));
31
+ var reflectedSchema = (schema) => Schema.make(schema.ast);
32
+ var operationResultSchemas = (api) => {
33
+ const schemas = new Map;
34
+ HttpApi.reflect(api, {
35
+ onGroup: () => {
36
+ return;
37
+ },
38
+ onEndpoint: ({ endpoint, group, successes }) => {
39
+ const operationId = Context.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
40
+ const operationSchemas = Array.from(successes.values()).flat().map(reflectedSchema);
41
+ if (operationSchemas.length === 1 && operationSchemas[0]) {
42
+ schemas.set(operationId, operationSchemas[0]);
43
+ } else if (operationSchemas.length > 1) {
44
+ schemas.set(operationId, Schema.Union(operationSchemas));
45
+ }
46
+ }
47
+ });
48
+ return schemas;
49
+ };
50
+ var makeHttpApiOperationResultEncoder = (api) => {
51
+ const schemas = operationResultSchemas(api);
52
+ return Effect.fn("HttpApiClient.encodeOperationResultWithSchema")((result, operation) => {
53
+ const operationId = operation.operation.operationId;
54
+ const schema = operationId ? schemas.get(operationId) : undefined;
55
+ if (!schema)
56
+ return encodeHttpApiOperationResult(result);
57
+ return Schema.encodeUnknownEffect(schema)(result).pipe(Effect.flatMap(encodeHttpApiOperationResult), Effect.mapError((cause) => new Error("HTTP API result does not match its success schema", {
58
+ cause
59
+ })));
60
+ });
61
+ };
22
62
  var GeneratedOperation = Schema.declare((value) => value instanceof Function).annotate({ identifier: "GeneratedOperation" });
23
63
  var GeneratedOperationEffect = Schema.declare((value) => Effect.isEffect(value)).annotate({ identifier: "GeneratedOperationEffect" });
24
64
  var makeGeneratedClient = (api, http, baseUrl) => EffectHttpApiClient.makeWith(api, {
@@ -54,9 +94,10 @@ var executeGeneratedOperation = Effect.fn("HttpApiClient.executeGeneratedOperati
54
94
  class ApiClient extends Context.Service()("ApiClient") {
55
95
  static layer = (config) => Layer.effect(this, Effect.gen(function* () {
56
96
  const http = yield* HttpClient.HttpClient;
97
+ const encodeResult = makeHttpApiOperationResultEncoder(config.api);
57
98
  const client = yield* makeGeneratedClient(config.api, http, config.baseUrl);
58
99
  return {
59
- encodeResult: config.encodeResult ?? ((result) => encodeHttpApiOperationResult(result)),
100
+ encodeResult: config.encodeResult ?? ((result, operation) => encodeResult(result, operation)),
60
101
  execute: Effect.fn("ApiClient.execute")(function* (options) {
61
102
  return yield* executeGeneratedOperation(client, options);
62
103
  })
@@ -64,6 +105,7 @@ class ApiClient extends Context.Service()("ApiClient") {
64
105
  }));
65
106
  }
66
107
  export {
108
+ makeHttpApiOperationResultEncoder,
67
109
  encodeHttpApiOperationResult,
68
110
  HttpApiOperationResult,
69
111
  ApiClient
@@ -3,13 +3,22 @@ import { Context as Context3, Effect as Effect3, Layer as Layer3, Option as Opti
3
3
  import { McpSchema, McpServer } from "effect/unstable/ai";
4
4
 
5
5
  // ../../src/lib/httpapi-client.ts
6
- import { Context, Effect, Layer, Schema } from "effect";
6
+ import { Context, Effect, Layer, Schema, SchemaTransformation } from "effect";
7
7
  import { HttpClient } from "effect/unstable/http";
8
8
  import {
9
- HttpApiClient as EffectHttpApiClient
9
+ HttpApi,
10
+ HttpApiClient as EffectHttpApiClient,
11
+ OpenApi
10
12
  } from "effect/unstable/httpapi";
13
+ var UndefinedFromNull = Schema.Null.pipe(Schema.decodeTo(Schema.Undefined, SchemaTransformation.transform({
14
+ decode: () => {
15
+ return;
16
+ },
17
+ encode: () => null
18
+ })));
11
19
  var HttpApiOperationResultValue = Schema.suspend(() => Schema.Union([
12
20
  Schema.Null,
21
+ UndefinedFromNull,
13
22
  Schema.String,
14
23
  Schema.Number,
15
24
  Schema.Boolean,
@@ -23,6 +32,37 @@ var HttpApiOperationResult = Schema.Union([
23
32
  Schema.Undefined
24
33
  ]).annotate({ identifier: "HttpApiOperationResult" });
25
34
  var encodeHttpApiOperationResult = Effect.fn("HttpApiClient.encodeOperationResult")((result) => Schema.encodeUnknownEffect(HttpApiOperationResult)(result).pipe(Effect.map((encoded) => encoded ?? null), Effect.mapError((cause) => new Error("HTTP API result is not serializable", { cause }))));
35
+ var reflectedSchema = (schema) => Schema.make(schema.ast);
36
+ var operationResultSchemas = (api) => {
37
+ const schemas = new Map;
38
+ HttpApi.reflect(api, {
39
+ onGroup: () => {
40
+ return;
41
+ },
42
+ onEndpoint: ({ endpoint, group, successes }) => {
43
+ const operationId = Context.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
44
+ const operationSchemas = Array.from(successes.values()).flat().map(reflectedSchema);
45
+ if (operationSchemas.length === 1 && operationSchemas[0]) {
46
+ schemas.set(operationId, operationSchemas[0]);
47
+ } else if (operationSchemas.length > 1) {
48
+ schemas.set(operationId, Schema.Union(operationSchemas));
49
+ }
50
+ }
51
+ });
52
+ return schemas;
53
+ };
54
+ var makeHttpApiOperationResultEncoder = (api) => {
55
+ const schemas = operationResultSchemas(api);
56
+ return Effect.fn("HttpApiClient.encodeOperationResultWithSchema")((result, operation) => {
57
+ const operationId = operation.operation.operationId;
58
+ const schema = operationId ? schemas.get(operationId) : undefined;
59
+ if (!schema)
60
+ return encodeHttpApiOperationResult(result);
61
+ return Schema.encodeUnknownEffect(schema)(result).pipe(Effect.flatMap(encodeHttpApiOperationResult), Effect.mapError((cause) => new Error("HTTP API result does not match its success schema", {
62
+ cause
63
+ })));
64
+ });
65
+ };
26
66
  var GeneratedOperation = Schema.declare((value) => value instanceof Function).annotate({ identifier: "GeneratedOperation" });
27
67
  var GeneratedOperationEffect = Schema.declare((value) => Effect.isEffect(value)).annotate({ identifier: "GeneratedOperationEffect" });
28
68
  var makeGeneratedClient = (api, http, baseUrl) => EffectHttpApiClient.makeWith(api, {
@@ -58,9 +98,10 @@ var executeGeneratedOperation = Effect.fn("HttpApiClient.executeGeneratedOperati
58
98
  class ApiClient extends Context.Service()("ApiClient") {
59
99
  static layer = (config) => Layer.effect(this, Effect.gen(function* () {
60
100
  const http = yield* HttpClient.HttpClient;
101
+ const encodeResult = makeHttpApiOperationResultEncoder(config.api);
61
102
  const client = yield* makeGeneratedClient(config.api, http, config.baseUrl);
62
103
  return {
63
- encodeResult: config.encodeResult ?? ((result) => encodeHttpApiOperationResult(result)),
104
+ encodeResult: config.encodeResult ?? ((result, operation) => encodeResult(result, operation)),
64
105
  execute: Effect.fn("ApiClient.execute")(function* (options) {
65
106
  return yield* executeGeneratedOperation(client, options);
66
107
  })
@@ -78,7 +119,7 @@ import {
78
119
  Schema as Schema2,
79
120
  SchemaRepresentation
80
121
  } from "effect";
81
- import { HttpApi as HttpApi2, OpenApi } from "effect/unstable/httpapi";
122
+ import { HttpApi as HttpApi2, OpenApi as OpenApi2 } from "effect/unstable/httpapi";
82
123
  var JsonObjectSchema = Schema2.Record(Schema2.String, Schema2.Json).annotate({
83
124
  identifier: "HttpJsonObject",
84
125
  title: "HTTP JSON object",
@@ -251,7 +292,7 @@ var decodeHttpApiOperationInput = Effect2.fn("Http.decodeApiOperationInput")(fun
251
292
  query: pickParameters("query")
252
293
  };
253
294
  });
254
- var reflectedSchema = (schema) => Schema2.make(schema.ast);
295
+ var reflectedSchema2 = (schema) => Schema2.make(schema.ast);
255
296
  var reflectedOperationInputSchemas = (api) => {
256
297
  const schemas = new Map;
257
298
  HttpApi2.reflect(api, {
@@ -259,17 +300,17 @@ var reflectedOperationInputSchemas = (api) => {
259
300
  return;
260
301
  },
261
302
  onEndpoint: ({ endpoint, group }) => {
262
- const operationId = Context2.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
303
+ const operationId = Context2.getOrElse(endpoint.annotations, OpenApi2.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
263
304
  const fields = {};
264
305
  if (endpoint.params)
265
- fields.params = reflectedSchema(endpoint.params);
306
+ fields.params = reflectedSchema2(endpoint.params);
266
307
  if (endpoint.query) {
267
- fields.query = Schema2.optionalKey(reflectedSchema(endpoint.query));
308
+ fields.query = Schema2.optionalKey(reflectedSchema2(endpoint.query));
268
309
  }
269
310
  if (endpoint.headers) {
270
- fields.headers = Schema2.optionalKey(reflectedSchema(endpoint.headers));
311
+ fields.headers = Schema2.optionalKey(reflectedSchema2(endpoint.headers));
271
312
  }
272
- const payloadSchemas = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema));
313
+ const payloadSchemas = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema2));
273
314
  if (payloadSchemas.length === 1 && payloadSchemas[0]) {
274
315
  fields.body = payloadSchemas[0];
275
316
  } else if (payloadSchemas.length > 1) {
@@ -301,7 +342,7 @@ class HttpApiSpec extends Context2.Service()("HttpApiSpec", {
301
342
  if (!HttpApi2.isHttpApi(api)) {
302
343
  throw new Error("HttpApiSpec requires a valid HttpApi");
303
344
  }
304
- const spec = OpenApi.fromApi(api);
345
+ const spec = OpenApi2.fromApi(api);
305
346
  const reflectedSchemas = reflectedOperationInputSchemas(api);
306
347
  const operations = httpApiOperations({
307
348
  spec,
@@ -3,13 +3,22 @@ import { Effect as Effect3, Layer as Layer3, Schema as Schema3 } from "effect";
3
3
  import { Tool, Toolkit } from "effect/unstable/ai";
4
4
 
5
5
  // ../../src/lib/httpapi-client.ts
6
- import { Context, Effect, Layer, Schema } from "effect";
6
+ import { Context, Effect, Layer, Schema, SchemaTransformation } from "effect";
7
7
  import { HttpClient } from "effect/unstable/http";
8
8
  import {
9
- HttpApiClient as EffectHttpApiClient
9
+ HttpApi,
10
+ HttpApiClient as EffectHttpApiClient,
11
+ OpenApi
10
12
  } from "effect/unstable/httpapi";
13
+ var UndefinedFromNull = Schema.Null.pipe(Schema.decodeTo(Schema.Undefined, SchemaTransformation.transform({
14
+ decode: () => {
15
+ return;
16
+ },
17
+ encode: () => null
18
+ })));
11
19
  var HttpApiOperationResultValue = Schema.suspend(() => Schema.Union([
12
20
  Schema.Null,
21
+ UndefinedFromNull,
13
22
  Schema.String,
14
23
  Schema.Number,
15
24
  Schema.Boolean,
@@ -23,6 +32,37 @@ var HttpApiOperationResult = Schema.Union([
23
32
  Schema.Undefined
24
33
  ]).annotate({ identifier: "HttpApiOperationResult" });
25
34
  var encodeHttpApiOperationResult = Effect.fn("HttpApiClient.encodeOperationResult")((result) => Schema.encodeUnknownEffect(HttpApiOperationResult)(result).pipe(Effect.map((encoded) => encoded ?? null), Effect.mapError((cause) => new Error("HTTP API result is not serializable", { cause }))));
35
+ var reflectedSchema = (schema) => Schema.make(schema.ast);
36
+ var operationResultSchemas = (api) => {
37
+ const schemas = new Map;
38
+ HttpApi.reflect(api, {
39
+ onGroup: () => {
40
+ return;
41
+ },
42
+ onEndpoint: ({ endpoint, group, successes }) => {
43
+ const operationId = Context.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
44
+ const operationSchemas = Array.from(successes.values()).flat().map(reflectedSchema);
45
+ if (operationSchemas.length === 1 && operationSchemas[0]) {
46
+ schemas.set(operationId, operationSchemas[0]);
47
+ } else if (operationSchemas.length > 1) {
48
+ schemas.set(operationId, Schema.Union(operationSchemas));
49
+ }
50
+ }
51
+ });
52
+ return schemas;
53
+ };
54
+ var makeHttpApiOperationResultEncoder = (api) => {
55
+ const schemas = operationResultSchemas(api);
56
+ return Effect.fn("HttpApiClient.encodeOperationResultWithSchema")((result, operation) => {
57
+ const operationId = operation.operation.operationId;
58
+ const schema = operationId ? schemas.get(operationId) : undefined;
59
+ if (!schema)
60
+ return encodeHttpApiOperationResult(result);
61
+ return Schema.encodeUnknownEffect(schema)(result).pipe(Effect.flatMap(encodeHttpApiOperationResult), Effect.mapError((cause) => new Error("HTTP API result does not match its success schema", {
62
+ cause
63
+ })));
64
+ });
65
+ };
26
66
  var GeneratedOperation = Schema.declare((value) => value instanceof Function).annotate({ identifier: "GeneratedOperation" });
27
67
  var GeneratedOperationEffect = Schema.declare((value) => Effect.isEffect(value)).annotate({ identifier: "GeneratedOperationEffect" });
28
68
  var makeGeneratedClient = (api, http, baseUrl) => EffectHttpApiClient.makeWith(api, {
@@ -58,9 +98,10 @@ var executeGeneratedOperation = Effect.fn("HttpApiClient.executeGeneratedOperati
58
98
  class ApiClient extends Context.Service()("ApiClient") {
59
99
  static layer = (config) => Layer.effect(this, Effect.gen(function* () {
60
100
  const http = yield* HttpClient.HttpClient;
101
+ const encodeResult = makeHttpApiOperationResultEncoder(config.api);
61
102
  const client = yield* makeGeneratedClient(config.api, http, config.baseUrl);
62
103
  return {
63
- encodeResult: config.encodeResult ?? ((result) => encodeHttpApiOperationResult(result)),
104
+ encodeResult: config.encodeResult ?? ((result, operation) => encodeResult(result, operation)),
64
105
  execute: Effect.fn("ApiClient.execute")(function* (options) {
65
106
  return yield* executeGeneratedOperation(client, options);
66
107
  })
@@ -78,7 +119,7 @@ import {
78
119
  Schema as Schema2,
79
120
  SchemaRepresentation
80
121
  } from "effect";
81
- import { HttpApi as HttpApi2, OpenApi } from "effect/unstable/httpapi";
122
+ import { HttpApi as HttpApi2, OpenApi as OpenApi2 } from "effect/unstable/httpapi";
82
123
  var JsonObjectSchema = Schema2.Record(Schema2.String, Schema2.Json).annotate({
83
124
  identifier: "HttpJsonObject",
84
125
  title: "HTTP JSON object",
@@ -251,7 +292,7 @@ var decodeHttpApiOperationInput = Effect2.fn("Http.decodeApiOperationInput")(fun
251
292
  query: pickParameters("query")
252
293
  };
253
294
  });
254
- var reflectedSchema = (schema) => Schema2.make(schema.ast);
295
+ var reflectedSchema2 = (schema) => Schema2.make(schema.ast);
255
296
  var reflectedOperationInputSchemas = (api) => {
256
297
  const schemas = new Map;
257
298
  HttpApi2.reflect(api, {
@@ -259,17 +300,17 @@ var reflectedOperationInputSchemas = (api) => {
259
300
  return;
260
301
  },
261
302
  onEndpoint: ({ endpoint, group }) => {
262
- const operationId = Context2.getOrElse(endpoint.annotations, OpenApi.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
303
+ const operationId = Context2.getOrElse(endpoint.annotations, OpenApi2.Identifier, () => group.topLevel ? endpoint.identifier : `${group.identifier}.${endpoint.identifier}`);
263
304
  const fields = {};
264
305
  if (endpoint.params)
265
- fields.params = reflectedSchema(endpoint.params);
306
+ fields.params = reflectedSchema2(endpoint.params);
266
307
  if (endpoint.query) {
267
- fields.query = Schema2.optionalKey(reflectedSchema(endpoint.query));
308
+ fields.query = Schema2.optionalKey(reflectedSchema2(endpoint.query));
268
309
  }
269
310
  if (endpoint.headers) {
270
- fields.headers = Schema2.optionalKey(reflectedSchema(endpoint.headers));
311
+ fields.headers = Schema2.optionalKey(reflectedSchema2(endpoint.headers));
271
312
  }
272
- const payloadSchemas = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema));
313
+ const payloadSchemas = Array.from(endpoint.payload.values()).flatMap(({ schemas: schemas2 }) => schemas2.map(reflectedSchema2));
273
314
  if (payloadSchemas.length === 1 && payloadSchemas[0]) {
274
315
  fields.body = payloadSchemas[0];
275
316
  } else if (payloadSchemas.length > 1) {
@@ -301,7 +342,7 @@ class HttpApiSpec extends Context2.Service()("HttpApiSpec", {
301
342
  if (!HttpApi2.isHttpApi(api)) {
302
343
  throw new Error("HttpApiSpec requires a valid HttpApi");
303
344
  }
304
- const spec = OpenApi.fromApi(api);
345
+ const spec = OpenApi2.fromApi(api);
305
346
  const reflectedSchemas = reflectedOperationInputSchemas(api);
306
347
  const operations = httpApiOperations({
307
348
  spec,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krak-stack/registry",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Tree-shakable KrakStack components and Effect services.",
5
5
  "license": "MIT",
6
6
  "repository": {