@effect/platform 0.87.0 → 0.87.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.
- package/HttpLayerRouter/package.json +6 -0
- package/README.md +272 -2
- package/dist/cjs/HttpApiBuilder.js +15 -1
- package/dist/cjs/HttpApiBuilder.js.map +1 -1
- package/dist/cjs/HttpApiScalar.js +29 -11
- package/dist/cjs/HttpApiScalar.js.map +1 -1
- package/dist/cjs/HttpApiSwagger.js +32 -15
- package/dist/cjs/HttpApiSwagger.js.map +1 -1
- package/dist/cjs/HttpLayerRouter.js +494 -0
- package/dist/cjs/HttpLayerRouter.js.map +1 -0
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/internal/httpRouter.js +3 -1
- package/dist/cjs/internal/httpRouter.js.map +1 -1
- package/dist/dts/HttpApiBuilder.d.ts +6 -0
- package/dist/dts/HttpApiBuilder.d.ts.map +1 -1
- package/dist/dts/HttpApiScalar.d.ts +14 -2
- package/dist/dts/HttpApiScalar.d.ts.map +1 -1
- package/dist/dts/HttpApiSwagger.d.ts +12 -2
- package/dist/dts/HttpApiSwagger.d.ts.map +1 -1
- package/dist/dts/HttpLayerRouter.d.ts +481 -0
- package/dist/dts/HttpLayerRouter.d.ts.map +1 -0
- package/dist/dts/index.d.ts +4 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/httpRouter.d.ts.map +1 -1
- package/dist/esm/HttpApiBuilder.js +14 -0
- package/dist/esm/HttpApiBuilder.js.map +1 -1
- package/dist/esm/HttpApiScalar.js +28 -10
- package/dist/esm/HttpApiScalar.js.map +1 -1
- package/dist/esm/HttpApiSwagger.js +31 -14
- package/dist/esm/HttpApiSwagger.js.map +1 -1
- package/dist/esm/HttpLayerRouter.js +468 -0
- package/dist/esm/HttpLayerRouter.js.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/httpRouter.js +3 -1
- package/dist/esm/internal/httpRouter.js.map +1 -1
- package/package.json +10 -2
- package/src/HttpApiBuilder.ts +30 -0
- package/src/HttpApiScalar.ts +79 -41
- package/src/HttpApiSwagger.ts +49 -18
- package/src/HttpLayerRouter.ts +920 -0
- package/src/index.ts +5 -0
- package/src/internal/httpRouter.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect/platform",
|
|
3
|
-
"version": "0.87.
|
|
3
|
+
"version": "0.87.2",
|
|
4
4
|
"description": "Unified interfaces for common platform-specific services",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"multipasta": "^0.2.5"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"effect": "^3.16.
|
|
19
|
+
"effect": "^3.16.11"
|
|
20
20
|
},
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"provenance": true
|
|
@@ -171,6 +171,11 @@
|
|
|
171
171
|
"import": "./dist/esm/HttpIncomingMessage.js",
|
|
172
172
|
"default": "./dist/cjs/HttpIncomingMessage.js"
|
|
173
173
|
},
|
|
174
|
+
"./HttpLayerRouter": {
|
|
175
|
+
"types": "./dist/dts/HttpLayerRouter.d.ts",
|
|
176
|
+
"import": "./dist/esm/HttpLayerRouter.js",
|
|
177
|
+
"default": "./dist/cjs/HttpLayerRouter.js"
|
|
178
|
+
},
|
|
174
179
|
"./HttpMethod": {
|
|
175
180
|
"types": "./dist/dts/HttpMethod.d.ts",
|
|
176
181
|
"import": "./dist/esm/HttpMethod.js",
|
|
@@ -418,6 +423,9 @@
|
|
|
418
423
|
"HttpIncomingMessage": [
|
|
419
424
|
"./dist/dts/HttpIncomingMessage.d.ts"
|
|
420
425
|
],
|
|
426
|
+
"HttpLayerRouter": [
|
|
427
|
+
"./dist/dts/HttpLayerRouter.d.ts"
|
|
428
|
+
],
|
|
421
429
|
"HttpMethod": [
|
|
422
430
|
"./dist/dts/HttpMethod.d.ts"
|
|
423
431
|
],
|
package/src/HttpApiBuilder.ts
CHANGED
|
@@ -123,6 +123,36 @@ export const httpApp: Effect.Effect<
|
|
|
123
123
|
) as any
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* @since 1.0.0
|
|
128
|
+
* @category constructors
|
|
129
|
+
*/
|
|
130
|
+
export const buildMiddleware: <Id extends string, Groups extends HttpApiGroup.HttpApiGroup.Any, E, R>(
|
|
131
|
+
api: HttpApi.HttpApi<Id, Groups, E, R>
|
|
132
|
+
) => Effect.Effect<
|
|
133
|
+
(
|
|
134
|
+
effect: Effect.Effect<HttpServerResponse.HttpServerResponse, unknown>
|
|
135
|
+
) => Effect.Effect<HttpServerResponse.HttpServerResponse, unknown, never>
|
|
136
|
+
> = Effect.fnUntraced(
|
|
137
|
+
function*<Id extends string, Groups extends HttpApiGroup.HttpApiGroup.Any, E, R>(
|
|
138
|
+
api: HttpApi.HttpApi<Id, Groups, E, R>
|
|
139
|
+
) {
|
|
140
|
+
const context = yield* Effect.context<never>()
|
|
141
|
+
const middlewareMap = makeMiddlewareMap(api.middlewares, context)
|
|
142
|
+
const errorSchema = makeErrorSchema(api as any)
|
|
143
|
+
const encodeError = Schema.encodeUnknown(errorSchema)
|
|
144
|
+
return (effect: Effect.Effect<HttpServerResponse.HttpServerResponse, unknown>) =>
|
|
145
|
+
Effect.catchAllCause(
|
|
146
|
+
applyMiddleware(middlewareMap, effect),
|
|
147
|
+
(cause) =>
|
|
148
|
+
Effect.matchEffect(Effect.provide(encodeError(Cause.squash(cause)), context), {
|
|
149
|
+
onFailure: () => Effect.failCause(cause),
|
|
150
|
+
onSuccess: Effect.succeed
|
|
151
|
+
})
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
|
|
126
156
|
/**
|
|
127
157
|
* Construct an http web handler from an `HttpApi` instance.
|
|
128
158
|
*
|
package/src/HttpApiScalar.ts
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
4
|
import * as Effect from "effect/Effect"
|
|
5
|
-
import
|
|
5
|
+
import * as Layer from "effect/Layer"
|
|
6
6
|
import { Api } from "./HttpApi.js"
|
|
7
|
+
import type * as HttpApi from "./HttpApi.js"
|
|
7
8
|
import { Router } from "./HttpApiBuilder.js"
|
|
9
|
+
import * as HttpLayerRouter from "./HttpLayerRouter.js"
|
|
8
10
|
import * as HttpServerResponse from "./HttpServerResponse.js"
|
|
9
11
|
import * as Html from "./internal/html.js"
|
|
10
12
|
import * as internal from "./internal/httpApiScalar.js"
|
|
@@ -120,52 +122,45 @@ export type ScalarConfig = {
|
|
|
120
122
|
defaultOpenAllTags?: boolean
|
|
121
123
|
}
|
|
122
124
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* @category layers
|
|
126
|
-
*/
|
|
127
|
-
export const layer = (options?: {
|
|
128
|
-
readonly path?: `/${string}` | undefined
|
|
125
|
+
const makeHandler = (options: {
|
|
126
|
+
readonly api: HttpApi.HttpApi.Any
|
|
129
127
|
readonly source?: ScalarScriptSource
|
|
130
128
|
readonly scalar?: ScalarConfig
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
Effect.gen(function*() {
|
|
134
|
-
const { api } = yield* Api
|
|
135
|
-
const spec = OpenApi.fromApi(api)
|
|
129
|
+
}) => {
|
|
130
|
+
const spec = OpenApi.fromApi(options.api as any)
|
|
136
131
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
132
|
+
const source = options?.source
|
|
133
|
+
const defaultScript = internal.javascript
|
|
134
|
+
const src: string | null = source
|
|
135
|
+
? typeof source === "string"
|
|
136
|
+
? source
|
|
137
|
+
: source.type === "cdn"
|
|
138
|
+
? `https://cdn.jsdelivr.net/npm/@scalar/api-reference@${
|
|
139
|
+
source.version ?? "latest"
|
|
140
|
+
}/dist/browser/standalone.min.js`
|
|
141
|
+
: null
|
|
142
|
+
: null
|
|
148
143
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
144
|
+
const scalarConfig = {
|
|
145
|
+
_integration: "http",
|
|
146
|
+
...options?.scalar
|
|
147
|
+
}
|
|
153
148
|
|
|
154
|
-
|
|
149
|
+
const response = HttpServerResponse.html(`<!doctype html>
|
|
155
150
|
<html>
|
|
156
151
|
<head>
|
|
157
152
|
<meta charset="utf-8" />
|
|
158
153
|
<title>${Html.escape(spec.info.title)}</title>
|
|
159
154
|
${
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
!spec.info.description
|
|
156
|
+
? ""
|
|
157
|
+
: `<meta name="description" content="${Html.escape(spec.info.description)}"/>`
|
|
158
|
+
}
|
|
164
159
|
${
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
160
|
+
!spec.info.description
|
|
161
|
+
? ""
|
|
162
|
+
: `<meta name="og:description" content="${Html.escape(spec.info.description)}"/>`
|
|
163
|
+
}
|
|
169
164
|
<meta
|
|
170
165
|
name="viewport"
|
|
171
166
|
content="width=device-width, initial-scale=1" />
|
|
@@ -178,12 +173,55 @@ export const layer = (options?: {
|
|
|
178
173
|
document.getElementById('api-reference').dataset.configuration = JSON.stringify(${Html.escapeJson(scalarConfig)})
|
|
179
174
|
</script>
|
|
180
175
|
${
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
176
|
+
src
|
|
177
|
+
? `<script src="${src}" crossorigin></script>`
|
|
178
|
+
: `<script>${defaultScript}</script>`
|
|
179
|
+
}
|
|
185
180
|
</body>
|
|
186
181
|
</html>`)
|
|
187
|
-
|
|
182
|
+
|
|
183
|
+
return Effect.succeed(response)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @since 1.0.0
|
|
188
|
+
* @category layers
|
|
189
|
+
*/
|
|
190
|
+
export const layer = (options?: {
|
|
191
|
+
readonly path?: `/${string}` | undefined
|
|
192
|
+
readonly source?: ScalarScriptSource
|
|
193
|
+
readonly scalar?: ScalarConfig
|
|
194
|
+
}): Layer.Layer<never, never, Api> =>
|
|
195
|
+
Router.use((router) =>
|
|
196
|
+
Effect.gen(function*() {
|
|
197
|
+
const { api } = yield* Api
|
|
198
|
+
const handler = makeHandler({ ...options, api })
|
|
199
|
+
yield* router.get(options?.path ?? "/docs", handler)
|
|
188
200
|
})
|
|
189
201
|
)
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @since 1.0.0
|
|
205
|
+
* @category layers
|
|
206
|
+
*/
|
|
207
|
+
export const layerHttpLayerRouter: (
|
|
208
|
+
options: {
|
|
209
|
+
readonly api: HttpApi.HttpApi.Any
|
|
210
|
+
readonly path: `/${string}`
|
|
211
|
+
readonly source?: ScalarScriptSource
|
|
212
|
+
readonly scalar?: ScalarConfig
|
|
213
|
+
}
|
|
214
|
+
) => Layer.Layer<
|
|
215
|
+
never,
|
|
216
|
+
never,
|
|
217
|
+
HttpLayerRouter.HttpRouter
|
|
218
|
+
> = Effect.fnUntraced(function*(options: {
|
|
219
|
+
readonly api: HttpApi.HttpApi.Any
|
|
220
|
+
readonly path: `/${string}`
|
|
221
|
+
readonly source?: ScalarScriptSource
|
|
222
|
+
readonly scalar?: ScalarConfig
|
|
223
|
+
}) {
|
|
224
|
+
const router = yield* HttpLayerRouter.HttpRouter
|
|
225
|
+
const handler = makeHandler(options)
|
|
226
|
+
yield* router.add("GET", options.path, handler)
|
|
227
|
+
}, Layer.effectDiscard)
|
package/src/HttpApiSwagger.ts
CHANGED
|
@@ -2,30 +2,21 @@
|
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
4
|
import * as Effect from "effect/Effect"
|
|
5
|
-
import
|
|
5
|
+
import * as Layer from "effect/Layer"
|
|
6
6
|
import { Api } from "./HttpApi.js"
|
|
7
|
+
import type * as HttpApi from "./HttpApi.js"
|
|
7
8
|
import { Router } from "./HttpApiBuilder.js"
|
|
9
|
+
import * as HttpLayerRouter from "./HttpLayerRouter.js"
|
|
8
10
|
import * as HttpServerResponse from "./HttpServerResponse.js"
|
|
9
11
|
import * as Html from "./internal/html.js"
|
|
10
12
|
import * as internal from "./internal/httpApiSwagger.js"
|
|
11
13
|
import * as OpenApi from "./OpenApi.js"
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* @since 1.0.0
|
|
19
|
-
* @category layers
|
|
20
|
-
*/
|
|
21
|
-
export const layer = (options?: {
|
|
22
|
-
readonly path?: `/${string}` | undefined
|
|
23
|
-
}): Layer<never, never, Api> =>
|
|
24
|
-
Router.use((router) =>
|
|
25
|
-
Effect.gen(function*() {
|
|
26
|
-
const { api } = yield* Api
|
|
27
|
-
const spec = OpenApi.fromApi(api)
|
|
28
|
-
const response = HttpServerResponse.html(`<!DOCTYPE html>
|
|
15
|
+
const makeHandler = (options: {
|
|
16
|
+
readonly api: HttpApi.HttpApi.Any
|
|
17
|
+
}) => {
|
|
18
|
+
const spec = OpenApi.fromApi(options.api as any)
|
|
19
|
+
const response = HttpServerResponse.html(`<!DOCTYPE html>
|
|
29
20
|
<html lang="en">
|
|
30
21
|
<head>
|
|
31
22
|
<meta charset="utf-8" />
|
|
@@ -49,6 +40,46 @@ export const layer = (options?: {
|
|
|
49
40
|
</script>
|
|
50
41
|
</body>
|
|
51
42
|
</html>`)
|
|
52
|
-
|
|
43
|
+
return Effect.succeed(response)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Exported layer mounting Swagger/OpenAPI documentation UI.
|
|
48
|
+
*
|
|
49
|
+
* @param options.path Optional mount path (default "/docs").
|
|
50
|
+
*
|
|
51
|
+
* @since 1.0.0
|
|
52
|
+
* @category layers
|
|
53
|
+
*/
|
|
54
|
+
export const layer = (options?: {
|
|
55
|
+
readonly path?: `/${string}` | undefined
|
|
56
|
+
}): Layer.Layer<never, never, Api> =>
|
|
57
|
+
Router.use((router) =>
|
|
58
|
+
Effect.gen(function*() {
|
|
59
|
+
const { api } = yield* Api
|
|
60
|
+
const handler = makeHandler({ api })
|
|
61
|
+
yield* router.get(options?.path ?? "/docs", handler)
|
|
53
62
|
})
|
|
54
63
|
)
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @since 1.0.0
|
|
67
|
+
* @category layers
|
|
68
|
+
*/
|
|
69
|
+
export const layerHttpLayerRouter: (
|
|
70
|
+
options: {
|
|
71
|
+
readonly api: HttpApi.HttpApi.Any
|
|
72
|
+
readonly path: `/${string}`
|
|
73
|
+
}
|
|
74
|
+
) => Layer.Layer<
|
|
75
|
+
never,
|
|
76
|
+
never,
|
|
77
|
+
HttpLayerRouter.HttpRouter
|
|
78
|
+
> = Effect.fnUntraced(function*(options: {
|
|
79
|
+
readonly api: HttpApi.HttpApi.Any
|
|
80
|
+
readonly path: `/${string}`
|
|
81
|
+
}) {
|
|
82
|
+
const router = yield* HttpLayerRouter.HttpRouter
|
|
83
|
+
const handler = makeHandler(options)
|
|
84
|
+
yield* router.add("GET", options.path, handler)
|
|
85
|
+
}, Layer.effectDiscard)
|