effect 4.0.0-beta.11 → 4.0.0-beta.13
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/dist/Config.d.ts +157 -0
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +56 -1
- package/dist/Config.js.map +1 -1
- package/dist/Effect.d.ts +79 -0
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +26 -0
- package/dist/Effect.js.map +1 -1
- package/dist/Fiber.d.ts +2 -2
- package/dist/Fiber.d.ts.map +1 -1
- package/dist/Fiber.js.map +1 -1
- package/dist/Graph.d.ts.map +1 -1
- package/dist/Graph.js +3 -6
- package/dist/Graph.js.map +1 -1
- package/dist/ManagedRuntime.d.ts +1 -1
- package/dist/ManagedRuntime.js +1 -1
- package/dist/Random.d.ts +17 -0
- package/dist/Random.d.ts.map +1 -1
- package/dist/Random.js +17 -0
- package/dist/Random.js.map +1 -1
- package/dist/Schedule.js +1 -1
- package/dist/Schedule.js.map +1 -1
- package/dist/Schema.d.ts +3 -1
- package/dist/Schema.d.ts.map +1 -1
- package/dist/SchemaAST.js +1 -1
- package/dist/SchemaAST.js.map +1 -1
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/effect.js +59 -44
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/request.js +2 -2
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/annotations.js +2 -0
- package/dist/internal/schema/annotations.js.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js +49 -18
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/ai/McpSchema.d.ts +134 -58
- package/dist/unstable/ai/McpSchema.d.ts.map +1 -1
- package/dist/unstable/ai/McpSchema.js +49 -12
- package/dist/unstable/ai/McpSchema.js.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +33 -6
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts +16 -0
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +14 -0
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/cli/CliOutput.js +24 -2
- package/dist/unstable/cli/CliOutput.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +41 -6
- package/dist/unstable/cli/Command.d.ts.map +1 -1
- package/dist/unstable/cli/Command.js +64 -31
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cli/GlobalFlag.d.ts +162 -0
- package/dist/unstable/cli/GlobalFlag.d.ts.map +1 -0
- package/dist/unstable/cli/GlobalFlag.js +164 -0
- package/dist/unstable/cli/GlobalFlag.js.map +1 -0
- package/dist/unstable/cli/HelpDoc.d.ts +10 -0
- package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
- package/dist/unstable/cli/index.d.ts +4 -0
- package/dist/unstable/cli/index.d.ts.map +1 -1
- package/dist/unstable/cli/index.js +4 -0
- package/dist/unstable/cli/index.js.map +1 -1
- package/dist/unstable/cli/internal/command.d.ts +1 -5
- package/dist/unstable/cli/internal/command.d.ts.map +1 -1
- package/dist/unstable/cli/internal/command.js +4 -22
- package/dist/unstable/cli/internal/command.js.map +1 -1
- package/dist/unstable/cli/internal/help.d.ts +19 -0
- package/dist/unstable/cli/internal/help.d.ts.map +1 -0
- package/dist/unstable/cli/internal/help.js +54 -0
- package/dist/unstable/cli/internal/help.js.map +1 -0
- package/dist/unstable/cli/internal/parser.js +20 -35
- package/dist/unstable/cli/internal/parser.js.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js +2 -2
- package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/unstable/http/HttpClient.d.ts +28 -4
- package/dist/unstable/http/HttpClient.d.ts.map +1 -1
- package/dist/unstable/http/HttpClient.js.map +1 -1
- package/dist/unstable/http/HttpEffect.d.ts +3 -8
- package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
- package/dist/unstable/http/HttpEffect.js +13 -24
- package/dist/unstable/http/HttpEffect.js.map +1 -1
- package/dist/unstable/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/unstable/http/HttpMiddleware.js +4 -8
- package/dist/unstable/http/HttpMiddleware.js.map +1 -1
- package/dist/unstable/http/HttpServerError.d.ts +6 -1
- package/dist/unstable/http/HttpServerError.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerError.js +26 -17
- package/dist/unstable/http/HttpServerError.js.map +1 -1
- package/dist/unstable/http/internal/preResponseHandler.d.ts +2 -0
- package/dist/unstable/http/internal/preResponseHandler.d.ts.map +1 -0
- package/dist/unstable/http/internal/preResponseHandler.js +10 -0
- package/dist/unstable/http/internal/preResponseHandler.js.map +1 -0
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.d.ts +4 -4
- package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.js +1 -1
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/dist/unstable/rpc/Rpc.d.ts +1 -1
- package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSchema.d.ts +13 -0
- package/dist/unstable/rpc/RpcSchema.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSchema.js +14 -0
- package/dist/unstable/rpc/RpcSchema.js.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.js +34 -9
- package/dist/unstable/rpc/RpcSerialization.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts +0 -7
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +5 -10
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/schema/Model.d.ts +1 -1
- package/dist/unstable/schema/Model.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts +3 -3
- package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.js +3 -3
- package/dist/unstable/schema/VariantSchema.js.map +1 -1
- package/dist/unstable/sql/SqlError.d.ts +14 -14
- package/dist/unstable/sql/SqlError.d.ts.map +1 -1
- package/dist/unstable/sql/SqlError.js +9 -3
- package/dist/unstable/sql/SqlError.js.map +1 -1
- package/package.json +1 -1
- package/src/Config.ts +171 -9
- package/src/Effect.ts +80 -0
- package/src/Fiber.ts +9 -2
- package/src/Graph.ts +16 -6
- package/src/ManagedRuntime.ts +1 -1
- package/src/Random.ts +18 -0
- package/src/Schedule.ts +1 -1
- package/src/Schema.ts +1 -1
- package/src/SchemaAST.ts +1 -1
- package/src/index.ts +47 -0
- package/src/internal/effect.ts +82 -49
- package/src/internal/request.ts +2 -2
- package/src/internal/schema/annotations.ts +2 -0
- package/src/unstable/ai/LanguageModel.ts +54 -24
- package/src/unstable/ai/McpSchema.ts +59 -13
- package/src/unstable/ai/McpServer.ts +44 -6
- package/src/unstable/ai/Tool.ts +15 -0
- package/src/unstable/cli/CliOutput.ts +32 -2
- package/src/unstable/cli/Command.ts +95 -38
- package/src/unstable/cli/GlobalFlag.ts +342 -0
- package/src/unstable/cli/HelpDoc.ts +12 -0
- package/src/unstable/cli/index.ts +5 -0
- package/src/unstable/cli/internal/command.ts +5 -30
- package/src/unstable/cli/internal/help.ts +66 -0
- package/src/unstable/cli/internal/parser.ts +23 -52
- package/src/unstable/cluster/ClusterWorkflowEngine.ts +2 -2
- package/src/unstable/http/HttpClient.ts +45 -10
- package/src/unstable/http/HttpEffect.ts +20 -39
- package/src/unstable/http/HttpMiddleware.ts +4 -14
- package/src/unstable/http/HttpServerError.ts +29 -18
- package/src/unstable/http/internal/preResponseHandler.ts +15 -0
- package/src/unstable/httpapi/HttpApiBuilder.ts +1 -1
- package/src/unstable/reactivity/Atom.ts +7 -7
- package/src/unstable/rpc/Rpc.ts +1 -1
- package/src/unstable/rpc/RpcSchema.ts +17 -0
- package/src/unstable/rpc/RpcSerialization.ts +44 -9
- package/src/unstable/rpc/RpcServer.ts +10 -19
- package/src/unstable/schema/VariantSchema.ts +6 -6
- package/src/unstable/sql/SqlError.ts +11 -9
- package/dist/unstable/cli/internal/builtInFlags.d.ts +0 -7
- package/dist/unstable/cli/internal/builtInFlags.d.ts.map +0 -1
- package/dist/unstable/cli/internal/builtInFlags.js +0 -44
- package/dist/unstable/cli/internal/builtInFlags.js.map +0 -1
- package/src/unstable/cli/internal/builtInFlags.ts +0 -78
package/src/Config.ts
CHANGED
|
@@ -886,18 +886,19 @@ export function schema<T, E>(codec: Schema.Codec<T, E>, path?: string | ConfigPr
|
|
|
886
886
|
const decodeUnknownEffect = Parser.decodeUnknownEffect(toCodecStringTree)
|
|
887
887
|
const toCodecStringTreeEncoded = AST.toEncoded(toCodecStringTree.ast)
|
|
888
888
|
const defaultPath = typeof path === "string" ? [path] : path ?? []
|
|
889
|
-
return make((provider) =>
|
|
890
|
-
|
|
889
|
+
return make((provider) => {
|
|
890
|
+
const path = provider.prefix ? [...provider.prefix, ...defaultPath] : defaultPath
|
|
891
|
+
return recur(toCodecStringTreeEncoded, provider, defaultPath).pipe(
|
|
891
892
|
Effect.flatMapEager((tree) =>
|
|
892
|
-
decodeUnknownEffect(tree).pipe(
|
|
893
|
-
|
|
894
|
-
|
|
893
|
+
decodeUnknownEffect(tree).pipe(
|
|
894
|
+
Effect.mapErrorEager((issue) =>
|
|
895
|
+
new Schema.SchemaError(path.length > 0 ? new Issue.Pointer(path, issue) : issue)
|
|
896
|
+
)
|
|
897
|
+
)
|
|
895
898
|
),
|
|
896
|
-
Effect.mapErrorEager((cause) =>
|
|
897
|
-
new ConfigError(cause)
|
|
898
|
-
)
|
|
899
|
+
Effect.mapErrorEager((cause) => new ConfigError(cause))
|
|
899
900
|
)
|
|
900
|
-
)
|
|
901
|
+
})
|
|
901
902
|
}
|
|
902
903
|
|
|
903
904
|
/** @internal */
|
|
@@ -1446,3 +1447,164 @@ export function url(name?: string) {
|
|
|
1446
1447
|
export function date(name?: string) {
|
|
1447
1448
|
return schema(Schema.DateValid, name)
|
|
1448
1449
|
}
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* Scopes a config under a named prefix.
|
|
1453
|
+
*
|
|
1454
|
+
* When to use:
|
|
1455
|
+
* - Grouping related config keys under a common namespace (e.g.
|
|
1456
|
+
* `"database"`, `"redis"`).
|
|
1457
|
+
* - Building reusable config fragments that callers nest at different paths.
|
|
1458
|
+
*
|
|
1459
|
+
* The prefix is prepended to every key the inner config reads. With
|
|
1460
|
+
* `fromUnknown` this means an extra object level; with `fromEnv` it means
|
|
1461
|
+
* a `_`-separated prefix on env var names.
|
|
1462
|
+
*
|
|
1463
|
+
* Multiple `nested` calls compose: the outermost name becomes the
|
|
1464
|
+
* outermost path segment.
|
|
1465
|
+
*
|
|
1466
|
+
* **Example** (Nesting a struct config under `"database"`)
|
|
1467
|
+
*
|
|
1468
|
+
* ```ts
|
|
1469
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1470
|
+
*
|
|
1471
|
+
* const dbConfig = Config.all({
|
|
1472
|
+
* host: Config.string("host"),
|
|
1473
|
+
* port: Config.number("port")
|
|
1474
|
+
* }).pipe(Config.nested("database"))
|
|
1475
|
+
*
|
|
1476
|
+
* const provider = ConfigProvider.fromUnknown({
|
|
1477
|
+
* database: { host: "localhost", port: "5432" }
|
|
1478
|
+
* })
|
|
1479
|
+
* // Effect.runSync(dbConfig.parse(provider))
|
|
1480
|
+
* // { host: "localhost", port: 5432 }
|
|
1481
|
+
* ```
|
|
1482
|
+
*
|
|
1483
|
+
* **Example** (Env vars with nested prefix)
|
|
1484
|
+
*
|
|
1485
|
+
* ```ts
|
|
1486
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1487
|
+
*
|
|
1488
|
+
* const host = Config.string("host").pipe(Config.nested("database"))
|
|
1489
|
+
*
|
|
1490
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1491
|
+
* env: { database_host: "localhost" }
|
|
1492
|
+
* })
|
|
1493
|
+
* // Effect.runSync(host.parse(provider)) // "localhost"
|
|
1494
|
+
* ```
|
|
1495
|
+
*
|
|
1496
|
+
* @see {@link all} – combine multiple configs into a struct
|
|
1497
|
+
* @see {@link schema} – read structured config from a schema
|
|
1498
|
+
*
|
|
1499
|
+
* @category Combinators
|
|
1500
|
+
* @since 4.0.0
|
|
1501
|
+
*/
|
|
1502
|
+
export const nested: {
|
|
1503
|
+
/**
|
|
1504
|
+
* Scopes a config under a named prefix.
|
|
1505
|
+
*
|
|
1506
|
+
* When to use:
|
|
1507
|
+
* - Grouping related config keys under a common namespace (e.g.
|
|
1508
|
+
* `"database"`, `"redis"`).
|
|
1509
|
+
* - Building reusable config fragments that callers nest at different paths.
|
|
1510
|
+
*
|
|
1511
|
+
* The prefix is prepended to every key the inner config reads. With
|
|
1512
|
+
* `fromUnknown` this means an extra object level; with `fromEnv` it means
|
|
1513
|
+
* a `_`-separated prefix on env var names.
|
|
1514
|
+
*
|
|
1515
|
+
* Multiple `nested` calls compose: the outermost name becomes the
|
|
1516
|
+
* outermost path segment.
|
|
1517
|
+
*
|
|
1518
|
+
* **Example** (Nesting a struct config under `"database"`)
|
|
1519
|
+
*
|
|
1520
|
+
* ```ts
|
|
1521
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1522
|
+
*
|
|
1523
|
+
* const dbConfig = Config.all({
|
|
1524
|
+
* host: Config.string("host"),
|
|
1525
|
+
* port: Config.number("port")
|
|
1526
|
+
* }).pipe(Config.nested("database"))
|
|
1527
|
+
*
|
|
1528
|
+
* const provider = ConfigProvider.fromUnknown({
|
|
1529
|
+
* database: { host: "localhost", port: "5432" }
|
|
1530
|
+
* })
|
|
1531
|
+
* // Effect.runSync(dbConfig.parse(provider))
|
|
1532
|
+
* // { host: "localhost", port: 5432 }
|
|
1533
|
+
* ```
|
|
1534
|
+
*
|
|
1535
|
+
* **Example** (Env vars with nested prefix)
|
|
1536
|
+
*
|
|
1537
|
+
* ```ts
|
|
1538
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1539
|
+
*
|
|
1540
|
+
* const host = Config.string("host").pipe(Config.nested("database"))
|
|
1541
|
+
*
|
|
1542
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1543
|
+
* env: { database_host: "localhost" }
|
|
1544
|
+
* })
|
|
1545
|
+
* // Effect.runSync(host.parse(provider)) // "localhost"
|
|
1546
|
+
* ```
|
|
1547
|
+
*
|
|
1548
|
+
* @see {@link all} – combine multiple configs into a struct
|
|
1549
|
+
* @see {@link schema} – read structured config from a schema
|
|
1550
|
+
*
|
|
1551
|
+
* @category Combinators
|
|
1552
|
+
* @since 4.0.0
|
|
1553
|
+
*/
|
|
1554
|
+
(name: string): <A>(self: Config<A>) => Config<A>
|
|
1555
|
+
/**
|
|
1556
|
+
* Scopes a config under a named prefix.
|
|
1557
|
+
*
|
|
1558
|
+
* When to use:
|
|
1559
|
+
* - Grouping related config keys under a common namespace (e.g.
|
|
1560
|
+
* `"database"`, `"redis"`).
|
|
1561
|
+
* - Building reusable config fragments that callers nest at different paths.
|
|
1562
|
+
*
|
|
1563
|
+
* The prefix is prepended to every key the inner config reads. With
|
|
1564
|
+
* `fromUnknown` this means an extra object level; with `fromEnv` it means
|
|
1565
|
+
* a `_`-separated prefix on env var names.
|
|
1566
|
+
*
|
|
1567
|
+
* Multiple `nested` calls compose: the outermost name becomes the
|
|
1568
|
+
* outermost path segment.
|
|
1569
|
+
*
|
|
1570
|
+
* **Example** (Nesting a struct config under `"database"`)
|
|
1571
|
+
*
|
|
1572
|
+
* ```ts
|
|
1573
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1574
|
+
*
|
|
1575
|
+
* const dbConfig = Config.all({
|
|
1576
|
+
* host: Config.string("host"),
|
|
1577
|
+
* port: Config.number("port")
|
|
1578
|
+
* }).pipe(Config.nested("database"))
|
|
1579
|
+
*
|
|
1580
|
+
* const provider = ConfigProvider.fromUnknown({
|
|
1581
|
+
* database: { host: "localhost", port: "5432" }
|
|
1582
|
+
* })
|
|
1583
|
+
* // Effect.runSync(dbConfig.parse(provider))
|
|
1584
|
+
* // { host: "localhost", port: 5432 }
|
|
1585
|
+
* ```
|
|
1586
|
+
*
|
|
1587
|
+
* **Example** (Env vars with nested prefix)
|
|
1588
|
+
*
|
|
1589
|
+
* ```ts
|
|
1590
|
+
* import { Config, ConfigProvider, Effect } from "effect"
|
|
1591
|
+
*
|
|
1592
|
+
* const host = Config.string("host").pipe(Config.nested("database"))
|
|
1593
|
+
*
|
|
1594
|
+
* const provider = ConfigProvider.fromEnv({
|
|
1595
|
+
* env: { database_host: "localhost" }
|
|
1596
|
+
* })
|
|
1597
|
+
* // Effect.runSync(host.parse(provider)) // "localhost"
|
|
1598
|
+
* ```
|
|
1599
|
+
*
|
|
1600
|
+
* @see {@link all} – combine multiple configs into a struct
|
|
1601
|
+
* @see {@link schema} – read structured config from a schema
|
|
1602
|
+
*
|
|
1603
|
+
* @category Combinators
|
|
1604
|
+
* @since 4.0.0
|
|
1605
|
+
*/
|
|
1606
|
+
<A>(self: Config<A>, name: string): Config<A>
|
|
1607
|
+
} = dual(
|
|
1608
|
+
2,
|
|
1609
|
+
<A>(self: Config<A>, name: string): Config<A> => make((provider) => self.parse(ConfigProvider.nested(provider, name)))
|
|
1610
|
+
)
|
package/src/Effect.ts
CHANGED
|
@@ -20846,6 +20846,86 @@ export const annotateLogs = dual<
|
|
|
20846
20846
|
})
|
|
20847
20847
|
)
|
|
20848
20848
|
|
|
20849
|
+
/**
|
|
20850
|
+
* Adds log annotations to the current scope.
|
|
20851
|
+
*
|
|
20852
|
+
* This differs from `annotateLogs`, which only annotates a specific effect.
|
|
20853
|
+
* `annotateLogsScoped` updates annotations for the entire current `Scope` and
|
|
20854
|
+
* restores the previous annotations when the scope closes.
|
|
20855
|
+
*
|
|
20856
|
+
* @example
|
|
20857
|
+
* ```ts
|
|
20858
|
+
* import { Effect } from "effect"
|
|
20859
|
+
*
|
|
20860
|
+
* const program = Effect.scoped(
|
|
20861
|
+
* Effect.gen(function*() {
|
|
20862
|
+
* yield* Effect.log("before")
|
|
20863
|
+
* yield* Effect.annotateLogsScoped({ requestId: "req-123" })
|
|
20864
|
+
* yield* Effect.log("inside scope")
|
|
20865
|
+
* })
|
|
20866
|
+
* )
|
|
20867
|
+
*
|
|
20868
|
+
* Effect.runPromise(program)
|
|
20869
|
+
* ```
|
|
20870
|
+
*
|
|
20871
|
+
* @since 4.0.0
|
|
20872
|
+
* @category Logging
|
|
20873
|
+
*/
|
|
20874
|
+
export const annotateLogsScoped: {
|
|
20875
|
+
/**
|
|
20876
|
+
* Adds log annotations to the current scope.
|
|
20877
|
+
*
|
|
20878
|
+
* This differs from `annotateLogs`, which only annotates a specific effect.
|
|
20879
|
+
* `annotateLogsScoped` updates annotations for the entire current `Scope` and
|
|
20880
|
+
* restores the previous annotations when the scope closes.
|
|
20881
|
+
*
|
|
20882
|
+
* @example
|
|
20883
|
+
* ```ts
|
|
20884
|
+
* import { Effect } from "effect"
|
|
20885
|
+
*
|
|
20886
|
+
* const program = Effect.scoped(
|
|
20887
|
+
* Effect.gen(function*() {
|
|
20888
|
+
* yield* Effect.log("before")
|
|
20889
|
+
* yield* Effect.annotateLogsScoped({ requestId: "req-123" })
|
|
20890
|
+
* yield* Effect.log("inside scope")
|
|
20891
|
+
* })
|
|
20892
|
+
* )
|
|
20893
|
+
*
|
|
20894
|
+
* Effect.runPromise(program)
|
|
20895
|
+
* ```
|
|
20896
|
+
*
|
|
20897
|
+
* @since 4.0.0
|
|
20898
|
+
* @category Logging
|
|
20899
|
+
*/
|
|
20900
|
+
(key: string, value: unknown): Effect<void, never, Scope>
|
|
20901
|
+
/**
|
|
20902
|
+
* Adds log annotations to the current scope.
|
|
20903
|
+
*
|
|
20904
|
+
* This differs from `annotateLogs`, which only annotates a specific effect.
|
|
20905
|
+
* `annotateLogsScoped` updates annotations for the entire current `Scope` and
|
|
20906
|
+
* restores the previous annotations when the scope closes.
|
|
20907
|
+
*
|
|
20908
|
+
* @example
|
|
20909
|
+
* ```ts
|
|
20910
|
+
* import { Effect } from "effect"
|
|
20911
|
+
*
|
|
20912
|
+
* const program = Effect.scoped(
|
|
20913
|
+
* Effect.gen(function*() {
|
|
20914
|
+
* yield* Effect.log("before")
|
|
20915
|
+
* yield* Effect.annotateLogsScoped({ requestId: "req-123" })
|
|
20916
|
+
* yield* Effect.log("inside scope")
|
|
20917
|
+
* })
|
|
20918
|
+
* )
|
|
20919
|
+
*
|
|
20920
|
+
* Effect.runPromise(program)
|
|
20921
|
+
* ```
|
|
20922
|
+
*
|
|
20923
|
+
* @since 4.0.0
|
|
20924
|
+
* @category Logging
|
|
20925
|
+
*/
|
|
20926
|
+
(values: Record<string, unknown>): Effect<void, never, Scope>
|
|
20927
|
+
} = internal.annotateLogsScoped
|
|
20928
|
+
|
|
20849
20929
|
/**
|
|
20850
20930
|
* Adds a span to each log line in this effect.
|
|
20851
20931
|
*
|
package/src/Fiber.ts
CHANGED
|
@@ -338,7 +338,10 @@ export const interruptAs: {
|
|
|
338
338
|
* @since 2.0.0
|
|
339
339
|
* @category interruption
|
|
340
340
|
*/
|
|
341
|
-
(
|
|
341
|
+
(
|
|
342
|
+
fiberId: number | undefined,
|
|
343
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
344
|
+
): <A, E>(self: Fiber<A, E>) => Effect<void>
|
|
342
345
|
/**
|
|
343
346
|
* Interrupts a fiber with a specific fiber ID as the interruptor. This allows
|
|
344
347
|
* tracking which fiber initiated the interruption.
|
|
@@ -361,7 +364,11 @@ export const interruptAs: {
|
|
|
361
364
|
* @since 2.0.0
|
|
362
365
|
* @category interruption
|
|
363
366
|
*/
|
|
364
|
-
<A, E>(
|
|
367
|
+
<A, E>(
|
|
368
|
+
self: Fiber<A, E>,
|
|
369
|
+
fiberId: number | undefined,
|
|
370
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
371
|
+
): Effect<void>
|
|
365
372
|
} = effect.fiberInterruptAs
|
|
366
373
|
|
|
367
374
|
/**
|
package/src/Graph.ts
CHANGED
|
@@ -2529,13 +2529,23 @@ export interface MermaidOptions<N, E> {
|
|
|
2529
2529
|
* Escapes special characters in labels for Mermaid syntax compatibility.
|
|
2530
2530
|
*/
|
|
2531
2531
|
const escapeMermaidLabel = (label: string): string => {
|
|
2532
|
+
// Escape special characters for Mermaid using HTML entity codes
|
|
2533
|
+
// According to: https://mermaid.js.org/syntax/flowchart.html#special-characters-that-break-syntax
|
|
2532
2534
|
return label
|
|
2533
|
-
.replace(
|
|
2534
|
-
.replace(/"/g, "
|
|
2535
|
-
.replace(
|
|
2536
|
-
.replace(
|
|
2537
|
-
.replace(
|
|
2538
|
-
.replace(/\
|
|
2535
|
+
.replace(/#/g, "#35;")
|
|
2536
|
+
.replace(/"/g, "#quot;")
|
|
2537
|
+
.replace(/</g, "#lt;")
|
|
2538
|
+
.replace(/>/g, "#gt;")
|
|
2539
|
+
.replace(/&/g, "#amp;")
|
|
2540
|
+
.replace(/\[/g, "#91;")
|
|
2541
|
+
.replace(/\]/g, "#93;")
|
|
2542
|
+
.replace(/\{/g, "#123;")
|
|
2543
|
+
.replace(/\}/g, "#125;")
|
|
2544
|
+
.replace(/\(/g, "#40;")
|
|
2545
|
+
.replace(/\)/g, "#41;")
|
|
2546
|
+
.replace(/\|/g, "#124;")
|
|
2547
|
+
.replace(/\\/g, "#92;")
|
|
2548
|
+
.replace(/\n/g, "<br/>");
|
|
2539
2549
|
}
|
|
2540
2550
|
|
|
2541
2551
|
/**
|
package/src/ManagedRuntime.ts
CHANGED
|
@@ -140,7 +140,7 @@ export interface ManagedRuntime<in R, out ER> {
|
|
|
140
140
|
* class Notifications extends ServiceMap.Service<Notifications, {
|
|
141
141
|
* readonly notify: (message: string) => Effect.Effect<void>
|
|
142
142
|
* }>()("Notifications") {
|
|
143
|
-
* static layer = Layer.succeed(this)({
|
|
143
|
+
* static readonly layer = Layer.succeed(this)({
|
|
144
144
|
* notify: (message) => Console.log(message)
|
|
145
145
|
* })
|
|
146
146
|
* }
|
package/src/Random.ts
CHANGED
|
@@ -76,6 +76,24 @@ const randomWith = <A>(f: (random: typeof Random["Service"]) => A): Effect.Effec
|
|
|
76
76
|
*/
|
|
77
77
|
export const next: Effect.Effect<number> = randomWith((r) => r.nextDoubleUnsafe())
|
|
78
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Generates a random boolean value.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { Effect, Random } from "effect"
|
|
85
|
+
*
|
|
86
|
+
* const program = Effect.gen(function*() {
|
|
87
|
+
* const value = yield* Random.nextBoolean
|
|
88
|
+
* console.log("Random boolean:", value)
|
|
89
|
+
* })
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @since 4.0.0
|
|
93
|
+
* @category Random Number Generators
|
|
94
|
+
*/
|
|
95
|
+
export const nextBoolean: Effect.Effect<boolean> = randomWith((r) => r.nextDoubleUnsafe() > 0.5)
|
|
96
|
+
|
|
79
97
|
/**
|
|
80
98
|
* Generates a random integer between `Number.MIN_SAFE_INTEGER` (inclusive)
|
|
81
99
|
* and `Number.MAX_SAFE_INTEGER` (inclusive).
|
package/src/Schedule.ts
CHANGED
|
@@ -4015,7 +4015,7 @@ export const fixed = (interval: Duration.Input): Schedule<number> => {
|
|
|
4015
4015
|
return fromStepWithMetadata(effect.succeed((meta) =>
|
|
4016
4016
|
effect.succeed([
|
|
4017
4017
|
meta.attempt - 1,
|
|
4018
|
-
window === 0
|
|
4018
|
+
window === 0
|
|
4019
4019
|
? Duration.zero
|
|
4020
4020
|
: Duration.millis(window - (meta.elapsed % window))
|
|
4021
4021
|
])
|
package/src/Schema.ts
CHANGED
|
@@ -1717,7 +1717,7 @@ export function fieldsAssign<const NewFields extends Struct.Fields>(fields: NewF
|
|
|
1717
1717
|
* @since 4.0.0
|
|
1718
1718
|
*/
|
|
1719
1719
|
export function encodeKeys<
|
|
1720
|
-
S extends Struct
|
|
1720
|
+
S extends Top & { readonly fields: Struct.Fields },
|
|
1721
1721
|
const M extends { readonly [K in keyof S["fields"]]?: PropertyKey }
|
|
1722
1722
|
>(mapping: M) {
|
|
1723
1723
|
return function(
|
package/src/SchemaAST.ts
CHANGED
|
@@ -594,7 +594,7 @@ export class Declaration extends Base {
|
|
|
594
594
|
}
|
|
595
595
|
/** @internal */
|
|
596
596
|
getExpected(): string {
|
|
597
|
-
const expected = this.annotations?.
|
|
597
|
+
const expected = this.annotations?.expected
|
|
598
598
|
if (typeof expected === "string") return expected
|
|
599
599
|
return "<Declaration>"
|
|
600
600
|
}
|
package/src/index.ts
CHANGED
|
@@ -1120,6 +1120,53 @@ export * as Equal from "./Equal.ts"
|
|
|
1120
1120
|
export * as Equivalence from "./Equivalence.ts"
|
|
1121
1121
|
|
|
1122
1122
|
/**
|
|
1123
|
+
* Pluggable error reporting for Effect programs.
|
|
1124
|
+
*
|
|
1125
|
+
* Reporting is triggered by `Effect.withErrorReporting`,
|
|
1126
|
+
* `ErrorReporter.report`, or built-in reporting boundaries in the HTTP and
|
|
1127
|
+
* RPC server modules.
|
|
1128
|
+
*
|
|
1129
|
+
* Each reporter receives a structured callback with the failing `Cause`, a
|
|
1130
|
+
* pretty-printed `Error`, severity, and any extra attributes attached to the
|
|
1131
|
+
* original error — making it straightforward to forward failures to Sentry,
|
|
1132
|
+
* Datadog, or a custom logging backend.
|
|
1133
|
+
*
|
|
1134
|
+
* Use the annotation symbols (`ignore`, `severity`, `attributes`) on your
|
|
1135
|
+
* error classes to control reporting behavior per-error.
|
|
1136
|
+
*
|
|
1137
|
+
* @example
|
|
1138
|
+
* ```ts
|
|
1139
|
+
* import { Data, Effect, ErrorReporter } from "effect"
|
|
1140
|
+
*
|
|
1141
|
+
* // A reporter that logs to the console
|
|
1142
|
+
* const consoleReporter = ErrorReporter.make(({ error, severity }) => {
|
|
1143
|
+
* console.error(`[${severity}]`, error.message)
|
|
1144
|
+
* })
|
|
1145
|
+
*
|
|
1146
|
+
* // An error that should be ignored by reporters
|
|
1147
|
+
* class NotFoundError extends Data.TaggedError("NotFoundError")<{}> {
|
|
1148
|
+
* readonly [ErrorReporter.ignore] = true
|
|
1149
|
+
* }
|
|
1150
|
+
*
|
|
1151
|
+
* // An error with custom severity and attributes
|
|
1152
|
+
* class RateLimitError extends Data.TaggedError("RateLimitError")<{
|
|
1153
|
+
* readonly retryAfter: number
|
|
1154
|
+
* }> {
|
|
1155
|
+
* readonly [ErrorReporter.severity] = "Warn" as const
|
|
1156
|
+
* readonly [ErrorReporter.attributes] = {
|
|
1157
|
+
* retryAfter: this.retryAfter
|
|
1158
|
+
* }
|
|
1159
|
+
* }
|
|
1160
|
+
*
|
|
1161
|
+
* // Opt in to error reporting with Effect.withErrorReporting
|
|
1162
|
+
* const program = Effect.gen(function*() {
|
|
1163
|
+
* yield* new RateLimitError({ retryAfter: 60 })
|
|
1164
|
+
* }).pipe(
|
|
1165
|
+
* Effect.withErrorReporting,
|
|
1166
|
+
* Effect.provide(ErrorReporter.layer([consoleReporter]))
|
|
1167
|
+
* )
|
|
1168
|
+
* ```
|
|
1169
|
+
*
|
|
1123
1170
|
* @since 4.0.0
|
|
1124
1171
|
*/
|
|
1125
1172
|
export * as ErrorReporter from "./ErrorReporter.ts"
|
package/src/internal/effect.ts
CHANGED
|
@@ -492,33 +492,33 @@ const fiberIdStore = { id: 0 }
|
|
|
492
492
|
export const getCurrentFiber = (): Fiber.Fiber<any, any> | undefined => (globalThis as any)[currentFiberTypeId]
|
|
493
493
|
|
|
494
494
|
const keepAlive = (() => {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
495
|
+
let isAvailable: boolean | undefined
|
|
496
|
+
const start = () => {
|
|
497
|
+
if (isAvailable === true) return setInterval(constVoid, 2_147_483_647)
|
|
498
|
+
else if (isAvailable === false) return undefined
|
|
499
|
+
|
|
498
500
|
try {
|
|
499
501
|
const running = setInterval(constVoid, 2_147_483_647)
|
|
500
|
-
|
|
501
|
-
return
|
|
502
|
-
setInterval,
|
|
503
|
-
clearInterval
|
|
504
|
-
}
|
|
502
|
+
isAvailable = true
|
|
503
|
+
return running
|
|
505
504
|
} catch {
|
|
505
|
+
isAvailable = false
|
|
506
506
|
return undefined
|
|
507
507
|
}
|
|
508
|
-
}
|
|
508
|
+
}
|
|
509
509
|
let count = 0
|
|
510
510
|
let running: ReturnType<typeof globalThis.setInterval> | undefined = undefined
|
|
511
511
|
return ({
|
|
512
512
|
increment() {
|
|
513
513
|
count++
|
|
514
|
-
if (
|
|
515
|
-
running = start
|
|
514
|
+
if (running === undefined) {
|
|
515
|
+
running = start()
|
|
516
516
|
}
|
|
517
517
|
},
|
|
518
518
|
decrement() {
|
|
519
519
|
count--
|
|
520
|
-
if (count === 0 &&
|
|
521
|
-
|
|
520
|
+
if (count === 0 && running !== undefined) {
|
|
521
|
+
clearInterval(running)
|
|
522
522
|
running = undefined
|
|
523
523
|
}
|
|
524
524
|
}
|
|
@@ -832,13 +832,29 @@ export const fiberInterrupt = <A, E>(
|
|
|
832
832
|
|
|
833
833
|
/** @internal */
|
|
834
834
|
export const fiberInterruptAs: {
|
|
835
|
-
(
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
835
|
+
(
|
|
836
|
+
fiberId: number | undefined,
|
|
837
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
838
|
+
): <A, E>(self: Fiber.Fiber<A, E>) => Effect.Effect<void>
|
|
839
|
+
<A, E>(
|
|
840
|
+
self: Fiber.Fiber<A, E>,
|
|
841
|
+
fiberId: number | undefined,
|
|
842
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
843
|
+
): Effect.Effect<void>
|
|
844
|
+
} = dual(
|
|
845
|
+
(args) => hasProperty(args[0], FiberTypeId),
|
|
846
|
+
<A, E>(
|
|
847
|
+
self: Fiber.Fiber<A, E>,
|
|
848
|
+
fiberId: number | undefined,
|
|
849
|
+
annotations?: ServiceMap.ServiceMap<never> | undefined
|
|
850
|
+
): Effect.Effect<void> =>
|
|
851
|
+
withFiber((parent) => {
|
|
852
|
+
let ann = fiberStackAnnotations(parent)
|
|
853
|
+
ann = ann && annotations ? ServiceMap.merge(ann, annotations) : ann ?? annotations
|
|
854
|
+
self.interruptUnsafe(fiberId, ann)
|
|
855
|
+
return asVoid(fiberAwait(self))
|
|
856
|
+
})
|
|
857
|
+
)
|
|
842
858
|
|
|
843
859
|
/** @internal */
|
|
844
860
|
export const fiberInterruptAll = <A extends Iterable<Fiber.Fiber<any, any>>>(
|
|
@@ -2003,23 +2019,8 @@ export const updateServices: {
|
|
|
2003
2019
|
const nextServices = f(prev)
|
|
2004
2020
|
if (prev === nextServices) return self as any
|
|
2005
2021
|
fiber.setServices(nextServices)
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
if (!prev.mapUnsafe.has(key) || value !== prev.mapUnsafe.get(key)) {
|
|
2009
|
-
newServices.set(key, value)
|
|
2010
|
-
}
|
|
2011
|
-
}
|
|
2012
|
-
return onExitPrimitive(self as any, () => {
|
|
2013
|
-
const map = new Map(fiber.services.mapUnsafe)
|
|
2014
|
-
for (const [key, value] of newServices) {
|
|
2015
|
-
if (value !== map.get(key)) continue
|
|
2016
|
-
if (prev.mapUnsafe.has(key)) {
|
|
2017
|
-
map.set(key, prev.mapUnsafe.get(key))
|
|
2018
|
-
} else {
|
|
2019
|
-
map.delete(key)
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
fiber.setServices(ServiceMap.makeUnsafe(map))
|
|
2022
|
+
return onExitPrimitive(self, () => {
|
|
2023
|
+
fiber.setServices(prev)
|
|
2023
2024
|
return undefined
|
|
2024
2025
|
})
|
|
2025
2026
|
})
|
|
@@ -2043,12 +2044,11 @@ export const updateService: {
|
|
|
2043
2044
|
service: ServiceMap.Service<I, A>,
|
|
2044
2045
|
f: (value: A) => A
|
|
2045
2046
|
): Effect.Effect<XA, E, R | I> =>
|
|
2046
|
-
|
|
2047
|
-
const prev = ServiceMap.getUnsafe(
|
|
2047
|
+
updateServices(self, (s) => {
|
|
2048
|
+
const prev = ServiceMap.getUnsafe(s, service)
|
|
2048
2049
|
const next = f(prev)
|
|
2049
|
-
if (prev === next) return
|
|
2050
|
-
|
|
2051
|
-
return onExit(self, () => sync(() => fiber.setServices(ServiceMap.add(fiber.services, service, prev))))
|
|
2050
|
+
if (prev === next) return s
|
|
2051
|
+
return ServiceMap.add(s, service, next)
|
|
2052
2052
|
})
|
|
2053
2053
|
)
|
|
2054
2054
|
|
|
@@ -2115,11 +2115,10 @@ const provideServiceImpl = <A, E, R, I, S>(
|
|
|
2115
2115
|
service: ServiceMap.Service<I, S>,
|
|
2116
2116
|
implementation: S
|
|
2117
2117
|
): Effect.Effect<A, E, Exclude<R, I>> =>
|
|
2118
|
-
|
|
2119
|
-
const prev =
|
|
2120
|
-
if (prev
|
|
2121
|
-
|
|
2122
|
-
return onExit(self, () => sync(() => fiber.setServices(ServiceMap.addOrOmit(fiber.services, service, prev))))
|
|
2118
|
+
updateServices(self, (s) => {
|
|
2119
|
+
const prev = s.mapUnsafe.get(service.key)
|
|
2120
|
+
if (prev === implementation) return s
|
|
2121
|
+
return ServiceMap.add(s, service, implementation)
|
|
2123
2122
|
}) as any
|
|
2124
2123
|
|
|
2125
2124
|
/** @internal */
|
|
@@ -3666,11 +3665,11 @@ export const provideScope: {
|
|
|
3666
3665
|
/** @internal */
|
|
3667
3666
|
export const scoped = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, Scope.Scope>> =>
|
|
3668
3667
|
withFiber((fiber) => {
|
|
3669
|
-
const prev =
|
|
3668
|
+
const prev = fiber.services
|
|
3670
3669
|
const scope = scopeMakeUnsafe()
|
|
3671
3670
|
fiber.setServices(ServiceMap.add(fiber.services, scopeTag, scope))
|
|
3672
3671
|
return onExitPrimitive(self, (exit) => {
|
|
3673
|
-
fiber.setServices(
|
|
3672
|
+
fiber.setServices(prev)
|
|
3674
3673
|
return scopeCloseUnsafe(scope, exit)
|
|
3675
3674
|
})
|
|
3676
3675
|
}) as any
|
|
@@ -5555,6 +5554,40 @@ export const LogToStderr = ServiceMap.Reference<boolean>("effect/Logger/LogToStd
|
|
|
5555
5554
|
defaultValue: constFalse
|
|
5556
5555
|
})
|
|
5557
5556
|
|
|
5557
|
+
/** @internal */
|
|
5558
|
+
export const annotateLogsScoped: {
|
|
5559
|
+
(key: string, value: unknown): Effect.Effect<void, never, Scope.Scope>
|
|
5560
|
+
(values: Record<string, unknown>): Effect.Effect<void, never, Scope.Scope>
|
|
5561
|
+
} = function() {
|
|
5562
|
+
const entries = typeof arguments[0] === "string" ?
|
|
5563
|
+
[[arguments[0], arguments[1]]] :
|
|
5564
|
+
Object.entries(arguments[0])
|
|
5565
|
+
return uninterruptible(withFiber((fiber) => {
|
|
5566
|
+
const prev = fiber.getRef(CurrentLogAnnotations)
|
|
5567
|
+
const next = { ...prev }
|
|
5568
|
+
for (let i = 0; i < entries.length; i++) {
|
|
5569
|
+
const [key, value] = entries[i]
|
|
5570
|
+
next[key] = value
|
|
5571
|
+
}
|
|
5572
|
+
fiber.setServices(ServiceMap.add(fiber.services, CurrentLogAnnotations, next))
|
|
5573
|
+
return scopeAddFinalizerExit(ServiceMap.getUnsafe(fiber.services, scopeTag), (_) => {
|
|
5574
|
+
const current = fiber.getRef(CurrentLogAnnotations)
|
|
5575
|
+
const next = { ...current }
|
|
5576
|
+
for (let i = 0; i < entries.length; i++) {
|
|
5577
|
+
const [key, value] = entries[i]
|
|
5578
|
+
if (current[key] !== value) continue
|
|
5579
|
+
if (key in prev) {
|
|
5580
|
+
next[key] = prev[key]
|
|
5581
|
+
} else {
|
|
5582
|
+
delete next[key]
|
|
5583
|
+
}
|
|
5584
|
+
}
|
|
5585
|
+
fiber.setServices(ServiceMap.add(fiber.services, CurrentLogAnnotations, next))
|
|
5586
|
+
return void_
|
|
5587
|
+
})
|
|
5588
|
+
}))
|
|
5589
|
+
}
|
|
5590
|
+
|
|
5558
5591
|
/** @internal */
|
|
5559
5592
|
export const LoggerTypeId = "~effect/Logger"
|
|
5560
5593
|
|
package/src/internal/request.ts
CHANGED
|
@@ -159,7 +159,7 @@ const addEntry = <A extends Request.Any>(
|
|
|
159
159
|
batch = newBatch
|
|
160
160
|
}
|
|
161
161
|
batchMap.set(key, batch)
|
|
162
|
-
batch.fiber = effect.
|
|
162
|
+
batch.fiber = effect.runForkWith(fiber.services)(batch.delayEffect, { scheduler: fiber.currentScheduler })
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
batch.entrySet.add(entry)
|
|
@@ -167,7 +167,7 @@ const addEntry = <A extends Request.Any>(
|
|
|
167
167
|
if (batch.resolver.collectWhile(batch.entries)) return entry
|
|
168
168
|
|
|
169
169
|
batch.fiber!.interruptUnsafe(fiber.id)
|
|
170
|
-
batch.fiber = effect.
|
|
170
|
+
batch.fiber = effect.runForkWith(fiber.services)(runBatch(batch), { scheduler: fiber.currentScheduler })
|
|
171
171
|
return entry
|
|
172
172
|
}
|
|
173
173
|
|
|
@@ -26,6 +26,8 @@ export const resolveBrands = resolveAt<ReadonlyArray<string>>("brands")
|
|
|
26
26
|
|
|
27
27
|
/** @internal */
|
|
28
28
|
export const getExpected = memoize((ast: AST.AST): string => {
|
|
29
|
+
const identifier = resolveIdentifier(ast)
|
|
30
|
+
if (typeof identifier === "string") return identifier
|
|
29
31
|
return ast.getExpected(getExpected)
|
|
30
32
|
})
|
|
31
33
|
|