diff --git a/.changeset/fair-guests-walk.md b/.changeset/fair-guests-walk.md new file mode 100644 index 0000000000..58eb1ec334 --- /dev/null +++ b/.changeset/fair-guests-walk.md @@ -0,0 +1,65 @@ +--- +"@effect/platform-node-shared": minor +"@effect/platform-browser": minor +"@effect/opentelemetry": minor +"@effect/platform-node": minor +"@effect/experimental": minor +"@effect/platform-bun": minor +"@effect/rpc-workers": minor +"@effect/platform": minor +"@effect/rpc-http": minor +"effect": minor +"@effect/schema": minor +"@effect/cli": minor +"@effect/rpc": minor +--- + +With this change we now require a string key to be provided for all tags and renames the dear old `Tag` to `GenericTag`, so when previously you could do: + +```ts +import { Effect, Context } from "effect"; +interface Service { + readonly _: unique symbol; +} +const Service = Context.Tag< + Service, + { + number: Effect.Effect; + } +>(); +``` + +you are now mandated to do: + +```ts +import { Effect, Context } from "effect"; +interface Service { + readonly _: unique symbol; +} +const Service = Context.GenericTag< + Service, + { + number: Effect.Effect; + } +>("Service"); +``` + +This makes by default all tags globals and ensures better debuggaility when unexpected errors arise. + +Furthermore we introduce a new way of constructing tags that should be considered the new default: + +```ts +import { Effect, Context } from "effect"; +class Service extends Context.Tag("Service")< + Service, + { + number: Effect.Effect; + } +>() {} + +const program = Effect.flatMap(Service, ({ number }) => number).pipe( + Effect.flatMap((_) => Effect.log(`number: ${_}`)) +); +``` + +this will use "Service" as the key and will create automatically an opaque identifier (the class) to be used at the type level, it does something similar to the above in a single shot. diff --git a/.changeset/warm-keys-search.md b/.changeset/warm-keys-search.md new file mode 100644 index 0000000000..a0c0ef30b7 --- /dev/null +++ b/.changeset/warm-keys-search.md @@ -0,0 +1,30 @@ +--- +"@effect/platform-node-shared": minor +"@effect/platform-browser": minor +"@effect/opentelemetry": minor +"@effect/platform-node": minor +"@effect/experimental": minor +"@effect/platform-bun": minor +"@effect/rpc-workers": minor +"@effect/platform": minor +"@effect/rpc-http": minor +"effect": minor +"@effect/schema": minor +"@effect/cli": minor +"@effect/rpc": minor +--- + +This change enables `Effect.serviceConstants` and `Effect.serviceMembers` to access any constant in the service, not only the effects, namely it is now possible to do: + +```ts +import { Effect, Context } from "effect"; + +class NumberRepo extends Context.TagClass("NumberRepo")< + NumberRepo, + { + readonly numbers: Array; + } +>() { + static numbers = Effect.serviceConstants(NumberRepo).numbers; +} +``` diff --git a/packages/cli/examples/naval-fate/store.ts b/packages/cli/examples/naval-fate/store.ts index dbee4564c2..fb14fe174a 100644 --- a/packages/cli/examples/naval-fate/store.ts +++ b/packages/cli/examples/naval-fate/store.ts @@ -23,7 +23,7 @@ export interface NavalFateStore { removeMine(x: number, y: number): Effect.Effect } -export const NavalFateStore = Context.Tag() +export const NavalFateStore = Context.GenericTag("NavalFateStore") export const make = Effect.gen(function*($) { const shipsStore = yield* $(Effect.map( diff --git a/packages/cli/src/internal/cliConfig.ts b/packages/cli/src/internal/cliConfig.ts index 6a9d448ebe..d2b163f1e9 100644 --- a/packages/cli/src/internal/cliConfig.ts +++ b/packages/cli/src/internal/cliConfig.ts @@ -10,7 +10,7 @@ export const make = (params?: Partial): CliConfig.CliConfig }) /** @internal */ -export const Tag = Context.Tag() +export const Tag = Context.GenericTag("@effect/cli/CliConfig") /** @internal */ export const defaultConfig: CliConfig.CliConfig = { diff --git a/packages/cli/src/internal/command.ts b/packages/cli/src/internal/command.ts index 0df07ba4ce..cc80b33c54 100644 --- a/packages/cli/src/internal/command.ts +++ b/packages/cli/src/internal/command.ts @@ -136,14 +136,14 @@ const getDescriptor = (self: Command.Command( descriptor: Descriptor.Command, handler: (_: A) => Effect.Effect, - tag?: Context.Tag, + tag: Context.Tag, transform: Command.Command.Transform = identity ): Command.Command => { const self = Object.create(Prototype) self.descriptor = descriptor self.handler = handler self.transform = transform - self.tag = tag ?? Context.Tag() + self.tag = tag return self } @@ -190,7 +190,8 @@ export const fromDescriptor = dual< const self: Command.Command = makeProto( descriptor, handler ?? - ((_) => Effect.failSync(() => ValidationError.helpRequested(getDescriptor(self)))) + ((_) => Effect.failSync(() => ValidationError.helpRequested(getDescriptor(self)))), + Context.GenericTag(`@effect/cli/Command/(${Array.from(InternalDescriptor.getNames(descriptor)).join("|")})`) ) return self as any } @@ -305,7 +306,8 @@ export const prompt = ( InternalDescriptor.prompt(name, prompt), (_) => _.value ), - handler + handler, + Context.GenericTag(`@effect/cli/Prompt/${name}`) ) /** @internal */ diff --git a/packages/cli/test/Command.test.ts b/packages/cli/test/Command.test.ts index a47901e1bc..ee251c8d63 100644 --- a/packages/cli/test/Command.test.ts +++ b/packages/cli/test/Command.test.ts @@ -33,7 +33,7 @@ const clone = Command.make("clone", { } })).pipe(Command.withDescription("Clone a repository into a new directory")) -const AddService = Context.Tag<"AddService">() +const AddService = Context.GenericTag<"AddService">("AddService") const add = Command.make("add", { pathspec: Args.text({ name: "pathspec" }) @@ -138,7 +138,7 @@ interface Messages { readonly log: (message: string) => Effect.Effect readonly messages: Effect.Effect> } -const Messages = Context.Tag() +const Messages = Context.GenericTag("Messages") const MessagesLive = Layer.sync(Messages, () => { const messages: Array = [] return Messages.of({ diff --git a/packages/cli/test/services/MockConsole.ts b/packages/cli/test/services/MockConsole.ts index fea14f0713..fbbbf33e80 100644 --- a/packages/cli/test/services/MockConsole.ts +++ b/packages/cli/test/services/MockConsole.ts @@ -12,7 +12,7 @@ export interface MockConsole extends Console.Console { ) => Effect.Effect> } -export const MockConsole = Context.Tag( +export const MockConsole = Context.GenericTag( "effect/Console" ) const pattern = new RegExp( diff --git a/packages/cli/test/services/MockTerminal.ts b/packages/cli/test/services/MockTerminal.ts index cfeec6a1e7..883a4ece6f 100644 --- a/packages/cli/test/services/MockTerminal.ts +++ b/packages/cli/test/services/MockTerminal.ts @@ -31,7 +31,7 @@ export declare namespace MockTerminal { // Context // ============================================================================= -export const MockTerminal = Context.Tag( +export const MockTerminal = Context.GenericTag( "@effect/platform/Terminal" ) diff --git a/packages/effect/src/Context.ts b/packages/effect/src/Context.ts index 7a7c8d176c..2a6ff6b5a9 100644 --- a/packages/effect/src/Context.ts +++ b/packages/effect/src/Context.ts @@ -37,12 +37,31 @@ export interface Tag extends Pipeable, Inspec of(self: Service): Service context(self: Service): Context readonly stack?: string | undefined - readonly identifier?: unknown + readonly key: string [Unify.typeSymbol]?: unknown [Unify.unifySymbol]?: TagUnify [Unify.ignoreSymbol]?: TagUnifyIgnore } +/** + * @since 2.0.0 + * @category models + */ +export interface TagClassShape { + readonly [TagTypeId]: { + readonly Id: Id + readonly Shape: Shape + } +} + +/** + * @since 2.0.0 + * @category models + */ +export interface TagClass extends Tag { + new(_: never): TagClassShape +} + /** * @category models * @since 2.0.0 @@ -64,35 +83,32 @@ export declare namespace Tag { /** * @since 2.0.0 */ - export type Service> = T extends Tag ? A : never + export type Service | TagClassShape> = T extends Tag ? A + : T extends TagClassShape ? A + : never /** * @since 2.0.0 */ - export type Identifier> = T extends Tag ? A : never + export type Identifier | TagClassShape> = T extends Tag ? A + : T extends TagClassShape ? A + : never } /** * Creates a new `Tag` instance with an optional key parameter. * - * Specifying the `key` will make the `Tag` global, meaning two tags with the same - * key will map to the same instance. - * - * Note: this is useful for cases where live reload can happen and it is - * desireable to preserve the instance across reloads. - * - * @param key - An optional key that makes the `Tag` global. + * @param key - A key that will be used to compare tags. * * @example * import * as Context from "effect/Context" * - * assert.strictEqual(Context.Tag() === Context.Tag(), false) - * assert.strictEqual(Context.Tag("PORT") === Context.Tag("PORT"), true) + * assert.strictEqual(Context.GenericTag("PORT").key === Context.GenericTag("PORT").key, true) * * @since 2.0.0 * @category constructors */ -export const Tag: (identifier?: unknown) => Tag = - internal.makeTag +export const GenericTag: (key: string) => Tag = + internal.makeGenericTag const TypeId: unique symbol = internal.TypeId as TypeId @@ -116,14 +132,14 @@ export interface Context extends Equal, Pipeable, Inspectable { readonly [TypeId]: { readonly _Services: Types.Contravariant } - readonly unsafeMap: Map, any> + readonly unsafeMap: Map } /** * @since 2.0.0 * @category constructors */ -export const unsafeMake: (unsafeMap: Map, any>) => Context = internal.makeContext +export const unsafeMake: (unsafeMap: Map) => Context = internal.makeContext /** * Checks if the provided argument is a `Context`. @@ -148,7 +164,7 @@ export const isContext: (input: unknown) => input is Context = internal.i * @example * import * as Context from "effect/Context" * - * assert.strictEqual(Context.isTag(Context.Tag()), true) + * assert.strictEqual(Context.isTag(Context.GenericTag("Tag")), true) * * @since 2.0.0 * @category guards @@ -174,7 +190,7 @@ export const empty: () => Context = internal.empty * @example * import * as Context from "effect/Context" * - * const Port = Context.Tag<{ PORT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") * * const Services = Context.make(Port, { PORT: 8080 }) * @@ -193,8 +209,8 @@ export const make: >(tag: T, service: Tag.Service) => * import * as Context from "effect/Context" * import { pipe } from "effect/Function" * - * const Port = Context.Tag<{ PORT: number }>() - * const Timeout = Context.Tag<{ TIMEOUT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") + * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const someContext = Context.make(Port, { PORT: 8080 }) * @@ -230,8 +246,8 @@ export const add: { * import * as Context from "effect/Context" * import { pipe } from "effect/Function" * - * const Port = Context.Tag<{ PORT: number }>() - * const Timeout = Context.Tag<{ TIMEOUT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") + * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = pipe( * Context.make(Port, { PORT: 8080 }), @@ -260,8 +276,8 @@ export const get: { * @example * import * as Context from "effect/Context" * - * const Port = Context.Tag<{ PORT: number }>() - * const Timeout = Context.Tag<{ TIMEOUT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") + * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * @@ -287,8 +303,8 @@ export const unsafeGet: { * import * as Context from "effect/Context" * import * as O from "effect/Option" * - * const Port = Context.Tag<{ PORT: number }>() - * const Timeout = Context.Tag<{ TIMEOUT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") + * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const Services = Context.make(Port, { PORT: 8080 }) * @@ -312,8 +328,8 @@ export const getOption: { * @example * import * as Context from "effect/Context" * - * const Port = Context.Tag<{ PORT: number }>() - * const Timeout = Context.Tag<{ TIMEOUT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") + * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const firstContext = Context.make(Port, { PORT: 8080 }) * const secondContext = Context.make(Timeout, { TIMEOUT: 5000 }) @@ -341,8 +357,8 @@ export const merge: { * import { pipe } from "effect/Function" * import * as O from "effect/Option" * - * const Port = Context.Tag<{ PORT: number }>() - * const Timeout = Context.Tag<{ TIMEOUT: number }>() + * const Port = Context.GenericTag<{ PORT: number }>("Port") + * const Timeout = Context.GenericTag<{ TIMEOUT: number }>("Timeout") * * const someContext = pipe( * Context.make(Port, { PORT: 8080 }), @@ -367,3 +383,9 @@ export const omit: >>( ...tags: S ) => (self: Context) => Context }[keyof S]>> = internal.omit + +/** + * @since 2.0.0 + * @category constructors + */ +export const Tag: (id: Id) => () => TagClass = internal.Tag diff --git a/packages/effect/src/Effect.ts b/packages/effect/src/Effect.ts index 759d318f50..47262e6af0 100644 --- a/packages/effect/src/Effect.ts +++ b/packages/effect/src/Effect.ts @@ -3168,24 +3168,26 @@ export const serviceFunctions: ( export const serviceConstants: ( getService: Effect ) => { - [k in { [k in keyof S]: S[k] extends Effect ? k : never }[keyof S]]: S[k] extends - Effect ? Effect : never + [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect ? Effect + : Effect } = effect.serviceConstants /** * @since 2.0.0 * @category context */ -export const serviceMembers: (getService: Effect) => { +export const serviceMembers: ( + getService: Effect +) => { functions: { [k in { [k in keyof S]: S[k] extends (...args: Array) => Effect ? k : never }[keyof S]]: S[k] extends (...args: infer Args) => Effect ? - (...args: Args) => Effect : - never + (...args: Args) => Effect + : never } constants: { - [k in { [k in keyof S]: S[k] extends Effect ? k : never }[keyof S]]: S[k] extends - Effect ? Effect : never + [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect ? Effect + : Effect } } = effect.serviceMembers diff --git a/packages/effect/src/FiberMap.ts b/packages/effect/src/FiberMap.ts index 45edece3af..a626d0fd19 100644 --- a/packages/effect/src/FiberMap.ts +++ b/packages/effect/src/FiberMap.ts @@ -324,9 +324,9 @@ export const run: { * interface Users { * readonly _: unique symbol * } - * const Users = Context.Tag> - * }>() + * }>("Users") * * Effect.gen(function*(_) { * const map = yield* _(FiberMap.make()) diff --git a/packages/effect/src/FiberSet.ts b/packages/effect/src/FiberSet.ts index 43dec21fe4..bc28abe9aa 100644 --- a/packages/effect/src/FiberSet.ts +++ b/packages/effect/src/FiberSet.ts @@ -217,9 +217,9 @@ export const run: { * interface Users { * readonly _: unique symbol * } - * const Users = Context.Tag> - * }>() + * }>("Users") * * Effect.gen(function*(_) { * const set = yield* _(FiberSet.make()) diff --git a/packages/effect/src/TestAnnotation.ts b/packages/effect/src/TestAnnotation.ts index 33953a0de3..2819cb9cc2 100644 --- a/packages/effect/src/TestAnnotation.ts +++ b/packages/effect/src/TestAnnotation.ts @@ -2,7 +2,6 @@ * @since 2.0.0 */ import * as Chunk from "./Chunk.js" -import * as Context from "./Context.js" import * as Either from "./Either.js" import * as Equal from "./Equal.js" import type * as Fiber from "./Fiber.js" @@ -34,7 +33,6 @@ export interface TestAnnotation extends Equal.Equal { readonly _A: Types.Invariant } readonly identifier: string - readonly tag: Context.Tag readonly initial: A combine(a: A, b: A): A } @@ -46,21 +44,18 @@ class TestAnnotationImpl implements Equal.Equal { } constructor( readonly identifier: string, - readonly tag: Context.Tag, readonly initial: A, readonly combine: (a: A, b: A) => A ) {} [Hash.symbol](): number { return pipe( Hash.hash(TestAnnotationSymbolKey), - Hash.combine(Hash.hash(this.identifier)), - Hash.combine(Hash.hash(this.tag)) + Hash.combine(Hash.hash(this.identifier)) ) } [Equal.symbol](that: unknown): boolean { return isTestAnnotation(that) && - this.identifier === that.identifier && - Equal.equals(this.tag, that.tag) + this.identifier === that.identifier } } @@ -74,11 +69,10 @@ export const isTestAnnotation = (u: unknown): u is TestAnnotation => ha */ export const make = ( identifier: string, - tag: Context.Tag, initial: A, combine: (a: A, b: A) => A ): TestAnnotation => { - return new TestAnnotationImpl(identifier, tag, initial, combine) + return new TestAnnotationImpl(identifier, initial, combine) } /** @@ -111,11 +105,10 @@ export const fibers: TestAnnotation< number, Chunk.Chunk>>> > -> = make( +> = make< + Either.Either>>>> +>( "fibers", - Context.Tag< - Either.Either>>>> - >(), Either.left(0), compose ) @@ -127,7 +120,6 @@ export const fibers: TestAnnotation< */ export const ignored: TestAnnotation = make( "ignored", - Context.Tag(Symbol.for("effect/TestAnnotation/ignored")), 0, (a, b) => a + b ) @@ -139,7 +131,6 @@ export const ignored: TestAnnotation = make( */ export const repeated: TestAnnotation = make( "repeated", - Context.Tag(Symbol.for("effect/TestAnnotation/repeated")), 0, (a, b) => a + b ) @@ -151,7 +142,6 @@ export const repeated: TestAnnotation = make( */ export const retried: TestAnnotation = make( "retried", - Context.Tag(Symbol.for("effect/TestAnnotation/retired")), 0, (a, b) => a + b ) @@ -163,7 +153,6 @@ export const retried: TestAnnotation = make( */ export const tagged: TestAnnotation> = make( "tagged", - Context.Tag>(Symbol.for("effect/TestAnnotation/tagged")), HashSet.empty(), (a, b) => pipe(a, HashSet.union(b)) ) diff --git a/packages/effect/src/TestAnnotations.ts b/packages/effect/src/TestAnnotations.ts index 8ddc9223af..ebf613418a 100644 --- a/packages/effect/src/TestAnnotations.ts +++ b/packages/effect/src/TestAnnotations.ts @@ -99,8 +99,8 @@ class AnnotationsImpl implements TestAnnotations { /** * @since 2.0.0 */ -export const TestAnnotations: Context.Tag = Context.Tag( - Symbol.for("effect/Annotations") +export const TestAnnotations: Context.Tag = Context.GenericTag( + "effect/Annotations" ) /** diff --git a/packages/effect/src/TestClock.ts b/packages/effect/src/TestClock.ts index 5ab2fd1ee0..573cd5e223 100644 --- a/packages/effect/src/TestClock.ts +++ b/packages/effect/src/TestClock.ts @@ -107,9 +107,7 @@ export const makeData = ( /** * @since 2.0.0 */ -export const TestClock: Context.Tag = Context.Tag( - Symbol.for("effect/TestClock") -) +export const TestClock: Context.Tag = Context.GenericTag("effect/TestClock") /** * The warning message that will be displayed if a test is using time but is diff --git a/packages/effect/src/TestConfig.ts b/packages/effect/src/TestConfig.ts index 4f6cd10c6c..fae2172232 100644 --- a/packages/effect/src/TestConfig.ts +++ b/packages/effect/src/TestConfig.ts @@ -34,9 +34,7 @@ export interface TestConfig { /** * @since 2.0.0 */ -export const TestConfig: Context.Tag = Context.Tag( - Symbol.for("effect/TestConfig") -) +export const TestConfig: Context.Tag = Context.GenericTag("effect/TestConfig") /** * @since 2.0.0 diff --git a/packages/effect/src/TestLive.ts b/packages/effect/src/TestLive.ts index d83a303ac0..1b2be26070 100644 --- a/packages/effect/src/TestLive.ts +++ b/packages/effect/src/TestLive.ts @@ -33,9 +33,7 @@ export interface TestLive { /** * @since 2.0.0 */ -export const TestLive: Context.Tag = Context.Tag( - Symbol.for("effect/TestLive") -) +export const TestLive: Context.Tag = Context.GenericTag("effect/TestLive") /** @internal */ class LiveImpl implements TestLive { diff --git a/packages/effect/src/TestSized.ts b/packages/effect/src/TestSized.ts index 59c24c8768..1de8a75d84 100644 --- a/packages/effect/src/TestSized.ts +++ b/packages/effect/src/TestSized.ts @@ -29,7 +29,7 @@ export interface TestSized { /** * @since 2.0.0 */ -export const TestSized: Context.Tag = Context.Tag(TestSizedTypeId) +export const TestSized: Context.Tag = Context.GenericTag("effect/TestSized") /** @internal */ class SizedImpl implements TestSized { diff --git a/packages/effect/src/internal/clock.ts b/packages/effect/src/internal/clock.ts index 1277d2cd1b..aa3994ccc8 100644 --- a/packages/effect/src/internal/clock.ts +++ b/packages/effect/src/internal/clock.ts @@ -14,7 +14,7 @@ const ClockSymbolKey = "effect/Clock" export const ClockTypeId: Clock.ClockTypeId = Symbol.for(ClockSymbolKey) as Clock.ClockTypeId /** @internal */ -export const clockTag: Context.Tag = Context.Tag(ClockTypeId) +export const clockTag: Context.Tag = Context.GenericTag("effect/Clock") /** @internal */ export const MAX_TIMER_MILLIS = 2 ** 31 - 1 diff --git a/packages/effect/src/internal/configProvider.ts b/packages/effect/src/internal/configProvider.ts index 105102e61c..b4edfe9f3a 100644 --- a/packages/effect/src/internal/configProvider.ts +++ b/packages/effect/src/internal/configProvider.ts @@ -33,9 +33,10 @@ export const ConfigProviderTypeId: ConfigProvider.ConfigProviderTypeId = Symbol. ) as ConfigProvider.ConfigProviderTypeId /** @internal */ -export const configProviderTag: Context.Tag = Context.Tag( - ConfigProviderTypeId -) +export const configProviderTag: Context.Tag = Context + .GenericTag( + "effect/ConfigProvider" + ) /** @internal */ const FlatConfigProviderSymbolKey = "effect/ConfigProviderFlat" diff --git a/packages/effect/src/internal/context.ts b/packages/effect/src/internal/context.ts index 3fe386030d..39ea659f88 100644 --- a/packages/effect/src/internal/context.ts +++ b/packages/effect/src/internal/context.ts @@ -1,7 +1,6 @@ import type * as C from "../Context.js" import * as Equal from "../Equal.js" import { dual } from "../Function.js" -import { globalValue } from "../GlobalValue.js" import * as Hash from "../Hash.js" import { format, NodeInspectSymbol, toJSON } from "../Inspectable.js" import type * as O from "../Option.js" @@ -23,7 +22,7 @@ export const STMTypeId: STM.STMTypeId = Symbol.for( ) as STM.STMTypeId /** @internal */ -export const TagProto: C.Tag = { +export const TagProto: any = { ...EffectPrototype, _tag: "Tag", _op: "Tag", @@ -38,7 +37,7 @@ export const TagProto: C.Tag = { toJSON(this: C.Tag) { return { _id: "Tag", - identifier: this.identifier, + key: this.key, stack: this.stack } }, @@ -56,13 +55,8 @@ export const TagProto: C.Tag = { } } -const tagRegistry = globalValue("effect/Context/Tag/tagRegistry", () => new Map>()) - /** @internal */ -export const makeTag = (identifier?: unknown): C.Tag => { - if (identifier && tagRegistry.has(identifier)) { - return tagRegistry.get(identifier)! - } +export const makeGenericTag = (key: string): C.Tag => { const limit = Error.stackTraceLimit Error.stackTraceLimit = 2 const creationError = new Error() @@ -73,13 +67,28 @@ export const makeTag = (identifier?: unknown): return creationError.stack } }) - if (identifier) { - tag.identifier = identifier - tagRegistry.set(identifier, tag) - } + tag.key = key return tag } +/** @internal */ +export const Tag = (id: Id) => (): C.TagClass => { + const limit = Error.stackTraceLimit + Error.stackTraceLimit = 2 + const creationError = new Error() + Error.stackTraceLimit = limit + + function TagClass() {} + Object.setPrototypeOf(TagClass, TagProto) + TagClass.key = id + Object.defineProperty(TagClass, "stack", { + get() { + return creationError.stack + } + }) + return TagClass as any +} + /** @internal */ export const TypeId: C.TypeId = Symbol.for("effect/Context") as C.TypeId @@ -122,14 +131,14 @@ export const ContextProto: Omit, "unsafeMap"> = { } /** @internal */ -export const makeContext = (unsafeMap: Map, any>): C.Context => { +export const makeContext = (unsafeMap: Map): C.Context => { const context = Object.create(ContextProto) context.unsafeMap = unsafeMap return context } const serviceNotFoundError = (tag: C.Tag) => { - const error = new Error(`Service not found${tag.identifier ? `: ${String(tag.identifier)}` : ""}`) + const error = new Error(`Service not found${tag.key ? `: ${String(tag.key)}` : ""}`) if (tag.stack) { const lines = tag.stack.split("\n") if (lines.length > 2) { @@ -162,7 +171,7 @@ export const empty = (): C.Context => _empty export const make = >( tag: T, service: C.Tag.Service -): C.Context> => makeContext(new Map([[tag, service]])) +): C.Context> => makeContext(new Map([[tag.key, service]])) /** @internal */ export const add = dual< @@ -179,7 +188,7 @@ export const add = dual< ) => C.Context> >(3, (self, tag, service) => { const map = new Map(self.unsafeMap) - map.set(tag as C.Tag, service) + map.set(tag.key, service) return makeContext(map) }) @@ -188,10 +197,10 @@ export const unsafeGet = dual< (tag: C.Tag) => (self: C.Context) => S, (self: C.Context, tag: C.Tag) => S >(2, (self, tag) => { - if (!self.unsafeMap.has(tag)) { + if (!self.unsafeMap.has(tag.key)) { throw serviceNotFoundError(tag as any) } - return self.unsafeMap.get(tag)! as any + return self.unsafeMap.get(tag.key)! as any }) /** @internal */ @@ -205,10 +214,10 @@ export const getOption = dual< (tag: C.Tag) => (self: C.Context) => O.Option, (self: C.Context, tag: C.Tag) => O.Option >(2, (self, tag) => { - if (!self.unsafeMap.has(tag)) { + if (!self.unsafeMap.has(tag.key)) { return option.none } - return option.some(self.unsafeMap.get(tag)! as any) + return option.some(self.unsafeMap.get(tag.key)! as any) }) /** @internal */ @@ -229,7 +238,7 @@ export const pick = (self: C.Context): C.Context< { [k in keyof S]: C.Tag.Identifier }[number] > => { - const tagSet = new Set(tags) + const tagSet = new Set(tags.map((_) => _.key)) const newEnv = new Map() for (const [tag, s] of self.unsafeMap.entries()) { if (tagSet.has(tag)) { @@ -247,7 +256,7 @@ export const omit = > => { const newEnv = new Map(self.unsafeMap) for (const tag of tags) { - newEnv.delete(tag) + newEnv.delete(tag.key) } return makeContext(newEnv) } diff --git a/packages/effect/src/internal/core-effect.ts b/packages/effect/src/internal/core-effect.ts index 7b000c45a5..510209eccb 100644 --- a/packages/effect/src/internal/core-effect.ts +++ b/packages/effect/src/internal/core-effect.ts @@ -1864,12 +1864,13 @@ export const serviceFunctions = ( export const serviceConstants = ( getService: Effect.Effect ): { - [k in { [k in keyof S]: S[k] extends Effect.Effect ? k : never }[keyof S]]: S[k] extends - Effect.Effect ? Effect.Effect : never + [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect.Effect ? + Effect.Effect : + Effect.Effect } => new Proxy({} as any, { get(_target: any, prop: any, _receiver) { - return core.flatMap(getService, (s: any) => s[prop]) + return core.flatMap(getService, (s: any) => core.isEffect(s[prop]) ? s[prop] : core.succeed(s[prop])) } }) @@ -1882,8 +1883,9 @@ export const serviceMembers = (getService: Effect.Effect): : never } constants: { - [k in { [k in keyof S]: S[k] extends Effect.Effect ? k : never }[keyof S]]: S[k] extends - Effect.Effect ? Effect.Effect : never + [k in { [k in keyof S]: k }[keyof S]]: S[k] extends Effect.Effect ? + Effect.Effect : + Effect.Effect } } => ({ functions: serviceFunctions(getService), @@ -1961,7 +1963,7 @@ export const currentParentSpan: Effect.Effect = core.flatMap( core.context(), (context) => { - const span = context.unsafeMap.get(internalTracer.spanTag) as Tracer.ParentSpan | undefined + const span = context.unsafeMap.get(internalTracer.spanTag.key) as Tracer.ParentSpan | undefined return span !== undefined && span._tag === "Span" ? core.succeed(span) : core.fail(new core.NoSuchElementException()) diff --git a/packages/effect/src/internal/core.ts b/packages/effect/src/internal/core.ts index f673070941..89799edbb3 100644 --- a/packages/effect/src/internal/core.ts +++ b/packages/effect/src/internal/core.ts @@ -3008,6 +3008,8 @@ export const mapInputContext = dual< /** @internal */ export const currentSpanFromFiber = (fiber: Fiber.RuntimeFiber): Option.Option => { - const span = fiber.getFiberRef(currentContext).unsafeMap.get(internalTracer.spanTag) as Tracer.ParentSpan | undefined + const span = fiber.getFiberRef(currentContext).unsafeMap.get(internalTracer.spanTag.key) as + | Tracer.ParentSpan + | undefined return span !== undefined && span._tag === "Span" ? Option.some(span) : Option.none() } diff --git a/packages/effect/src/internal/defaultServices/console.ts b/packages/effect/src/internal/defaultServices/console.ts index 1fe9bcdc0e..4bf842611a 100644 --- a/packages/effect/src/internal/defaultServices/console.ts +++ b/packages/effect/src/internal/defaultServices/console.ts @@ -6,7 +6,9 @@ import * as core from "../core.js" export const TypeId: Console.TypeId = Symbol.for("effect/Console") as Console.TypeId /** @internal */ -export const consoleTag: Context.Tag = Context.Tag(TypeId) +export const consoleTag: Context.Tag = Context.GenericTag( + "effect/Console" +) /** @internal */ export const defaultConsole: Console.Console = { diff --git a/packages/effect/src/internal/differ/contextPatch.ts b/packages/effect/src/internal/differ/contextPatch.ts index 5633f49542..90b5736645 100644 --- a/packages/effect/src/internal/differ/contextPatch.ts +++ b/packages/effect/src/internal/differ/contextPatch.ts @@ -1,5 +1,5 @@ import * as Chunk from "../../Chunk.js" -import type { Context, Tag } from "../../Context.js" +import type { Context } from "../../Context.js" import type { Differ } from "../../Differ.js" import * as Equal from "../../Equal.js" import * as Dual from "../../Function.js" @@ -63,7 +63,7 @@ const makeAndThen = ( /** @internal */ export interface AddService extends Differ.Context.Patch { readonly _tag: "AddService" - readonly tag: Tag + readonly key: string readonly service: T } @@ -72,37 +72,37 @@ const AddServiceProto = Object.assign(Object.create(PatchProto), { }) const makeAddService = ( - tag: Tag, + key: string, service: T ): Differ.Context.Patch => { const o = Object.create(AddServiceProto) - o.tag = tag + o.key = key o.service = service return o } /** @internal */ -export interface RemoveService extends Differ.Context.Patch> { +export interface RemoveService extends Differ.Context.Patch> { readonly _tag: "RemoveService" - readonly tag: Tag + readonly key: string } const RemoveServiceProto = Object.assign(Object.create(PatchProto), { _tag: "RemoveService" }) -const makeRemoveService = ( - tag: Tag +const makeRemoveService = ( + key: string ): Differ.Context.Patch> => { const o = Object.create(RemoveServiceProto) - o.tag = tag + o.key = key return o } /** @internal */ export interface UpdateService extends Differ.Context.Patch { readonly _tag: "UpdateService" - readonly tag: Tag + readonly key: string update(service: T): T } @@ -111,11 +111,11 @@ const UpdateServiceProto = Object.assign(Object.create(PatchProto), { }) const makeUpdateService = ( - tag: Tag, + key: string, update: (service: T) => T ): Differ.Context.Patch => { const o = Object.create(UpdateServiceProto) - o.tag = tag + o.key = key o.update = update return o } @@ -124,7 +124,7 @@ type Instruction = | Empty | AndThen | AddService - | RemoveService + | RemoveService | UpdateService /** @internal */ @@ -184,7 +184,7 @@ export const patch = Dual.dual< let patches: Chunk.Chunk> = Chunk.of( self as Differ.Context.Patch ) - const updatedContext: Map, unknown> = new Map(context.unsafeMap) + const updatedContext: Map = new Map(context.unsafeMap) while (Chunk.isNonEmpty(patches)) { const head: Instruction = Chunk.headNonEmpty(patches) as Instruction const tail = Chunk.tailNonEmpty(patches) @@ -194,7 +194,7 @@ export const patch = Dual.dual< break } case "AddService": { - updatedContext.set(head.tag, head.service) + updatedContext.set(head.key, head.service) patches = tail break } @@ -203,12 +203,12 @@ export const patch = Dual.dual< break } case "RemoveService": { - updatedContext.delete(head.tag) + updatedContext.delete(head.key) patches = tail break } case "UpdateService": { - updatedContext.set(head.tag, head.update(updatedContext.get(head.tag))) + updatedContext.set(head.key, head.update(updatedContext.get(head.key))) wasServiceUpdated = true patches = tail break diff --git a/packages/effect/src/internal/fiberRuntime.ts b/packages/effect/src/internal/fiberRuntime.ts index 96528732ae..6c433f75c0 100644 --- a/packages/effect/src/internal/fiberRuntime.ts +++ b/packages/effect/src/internal/fiberRuntime.ts @@ -2936,7 +2936,7 @@ export const releaseMapReleaseAll = ( // circular with Scope /** @internal */ -export const scopeTag = Context.Tag(core.ScopeTypeId) +export const scopeTag = Context.GenericTag("effect/Scope") /* @internal */ export const scope: Effect.Effect = scopeTag diff --git a/packages/effect/src/internal/layer.ts b/packages/effect/src/internal/layer.ts index f2aa416ecf..66c14cdabb 100644 --- a/packages/effect/src/internal/layer.ts +++ b/packages/effect/src/internal/layer.ts @@ -783,7 +783,7 @@ export const retry = dual< ) => Layer.Layer >(2, (self, schedule) => suspend(() => { - const stateTag = Context.Tag<{ state: unknown }>() + const stateTag = Context.GenericTag<{ state: unknown }>("effect/Layer/retry/{ state: unknown }") return pipe( succeed(stateTag, { state: schedule.initial }), flatMap((env: Context.Context<{ state: unknown }>) => @@ -1079,7 +1079,7 @@ export const zipWith = dual< export const unwrapEffect = ( self: Effect.Effect> ): Layer.Layer => { - const tag = Context.Tag>() + const tag = Context.GenericTag>("effect/Layer/unwrapEffect/Layer.Layer") return flatMap(fromEffect(tag, self), (context) => Context.get(context, tag)) } @@ -1087,7 +1087,7 @@ export const unwrapEffect = ( export const unwrapScoped = ( self: Effect.Effect> ): Layer.Layer, E | E1, A> => { - const tag = Context.Tag>() + const tag = Context.GenericTag>("effect/Layer/unwrapScoped/Layer.Layer") return flatMap(scoped(tag, self), (context) => Context.get(context, tag)) } diff --git a/packages/effect/src/internal/random.ts b/packages/effect/src/internal/random.ts index 1eb59332be..d4c4649717 100644 --- a/packages/effect/src/internal/random.ts +++ b/packages/effect/src/internal/random.ts @@ -15,7 +15,7 @@ export const RandomTypeId: Random.RandomTypeId = Symbol.for( ) as Random.RandomTypeId /** @internal */ -export const randomTag: Context.Tag = Context.Tag(RandomTypeId) +export const randomTag: Context.Tag = Context.GenericTag("effect/Random") /** @internal */ class RandomImpl implements Random.Random { readonly [RandomTypeId]: Random.RandomTypeId = RandomTypeId diff --git a/packages/effect/src/internal/reloadable.ts b/packages/effect/src/internal/reloadable.ts index 3afa66e1de..48c083d1cc 100644 --- a/packages/effect/src/internal/reloadable.ts +++ b/packages/effect/src/internal/reloadable.ts @@ -1,7 +1,6 @@ import * as Context from "../Context.js" import type * as Effect from "../Effect.js" import { pipe } from "../Function.js" -import { globalValue } from "../GlobalValue.js" import type * as Layer from "../Layer.js" import type * as Reloadable from "../Reloadable.js" import type * as Schedule from "../Schedule.js" @@ -120,25 +119,14 @@ export const manual = , In, E>( ) ) -/** @internal */ -const tagMap = globalValue( - Symbol.for("effect/Reloadable/tagMap"), - () => new WeakMap, Context.Tag>([]) -) - /** @internal */ export const reloadableTag = >( tag: T ): Context.Tag>, Reloadable.Reloadable>> => { - if (tagMap.has(tag)) { - return tagMap.get(tag)! - } - const newTag = Context.Tag< + return Context.GenericTag< Reloadable.Reloadable>, Reloadable.Reloadable> - >() - tagMap.set(tag, newTag) - return newTag + >(`effect/Reloadable<${tag.key}>`) } /** @internal */ diff --git a/packages/effect/src/internal/stm/tRandom.ts b/packages/effect/src/internal/stm/tRandom.ts index d847924eb3..0021e40b2d 100644 --- a/packages/effect/src/internal/stm/tRandom.ts +++ b/packages/effect/src/internal/stm/tRandom.ts @@ -83,7 +83,7 @@ const shuffleWith = ( } /** @internal */ -export const Tag = Context.Tag() +export const Tag = Context.GenericTag("effect/TRandom") class TRandomImpl implements TRandom.TRandom { readonly [TRandomTypeId]: TRandom.TRandomTypeId = TRandomTypeId diff --git a/packages/effect/src/internal/tracer.ts b/packages/effect/src/internal/tracer.ts index 2e6c6c6037..6f0865645e 100644 --- a/packages/effect/src/internal/tracer.ts +++ b/packages/effect/src/internal/tracer.ts @@ -18,14 +18,10 @@ export const make = (options: Omit): Tracer. }) /** @internal */ -export const tracerTag = Context.Tag( - Symbol.for("effect/Tracer") -) +export const tracerTag = Context.GenericTag("effect/Tracer") /** @internal */ -export const spanTag = Context.Tag( - Symbol.for("effect/ParentSpan") -) +export const spanTag = Context.GenericTag("effect/ParentSpan") const ids = globalValue("effect/Tracer/SpanId.ids", () => MutableRef.make(0)) diff --git a/packages/effect/test/Channel/environment.test.ts b/packages/effect/test/Channel/environment.test.ts index f53fd6567a..cd89731173 100644 --- a/packages/effect/test/Channel/environment.test.ts +++ b/packages/effect/test/Channel/environment.test.ts @@ -18,7 +18,7 @@ export interface NumberService extends Equal.Equal { readonly n: number } -export const NumberService = Context.Tag() +export const NumberService = Context.GenericTag("NumberService") export class NumberServiceImpl implements NumberService { readonly [NumberServiceTypeId]: NumberServiceTypeId = NumberServiceTypeId diff --git a/packages/effect/test/Channel/foreign.test.ts b/packages/effect/test/Channel/foreign.test.ts index fe36dbc72f..c54a2facc3 100644 --- a/packages/effect/test/Channel/foreign.test.ts +++ b/packages/effect/test/Channel/foreign.test.ts @@ -12,7 +12,7 @@ import { assert, describe } from "vitest" describe("Channel.Foreign", () => { it.effect("Tag", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $(tag, Channel.run, Effect.provideService(tag, 10)) assert.deepEqual(result, 10) })) diff --git a/packages/effect/test/Context.test.ts b/packages/effect/test/Context.test.ts index ab0aa37fdb..3a50e86c4b 100644 --- a/packages/effect/test/Context.test.ts +++ b/packages/effect/test/Context.test.ts @@ -7,23 +7,32 @@ import { assert, describe, expect, it } from "vitest" interface A { a: number } -const A = Context.Tag() +const A = Context.GenericTag("A") interface B { b: number } -const B = Context.Tag() +const B = Context.GenericTag("B") interface C { c: number } -const C = Context.Tag("C") +const C = Context.GenericTag("C") + +class D extends Context.Tag("D")() {} describe("Context", () => { it("Tag.toJson()", () => { const json: any = A.toJSON() expect(json["_id"]).toEqual("Tag") - expect(json["identifier"]).toEqual(undefined) + expect(json["key"]).toEqual("A") + expect(typeof json["stack"]).toEqual("string") + }) + + it("TagClass.toJson()", () => { + const json: any = D.toJSON() + expect(json["_id"]).toEqual("Tag") + expect(json["key"]).toEqual("D") expect(typeof json["stack"]).toEqual("string") }) @@ -33,12 +42,6 @@ describe("Context", () => { expect(json["services"]).toEqual([]) }) - it("global tag", () => { - const a = Context.Tag("effect-test/Context/Tag") - const b = Context.Tag("effect-test/Context/Tag") - expect(a).toBe(b) - }) - it("aliased tags", () => { interface Foo { readonly _tag: "Foo" @@ -49,7 +52,7 @@ describe("Context", () => { interface FooBar { readonly FooBar: unique symbol } - const Service = Context.Tag() + const Service = Context.GenericTag("FooBar") const context = Context.make(Service, { _tag: "Foo" }) expect(Context.get(context, Service)).toStrictEqual({ _tag: "Foo" }) }) @@ -57,7 +60,8 @@ describe("Context", () => { it("adds and retrieve services", () => { const Services = pipe( Context.make(A, { a: 0 }), - Context.add(B, { b: 1 }) + Context.add(B, { b: 1 }), + Context.add(D, { d: 2 }) ) expect(Context.get(Services, A)).toEqual({ a: 0 }) @@ -67,6 +71,11 @@ describe("Context", () => { Context.getOption(B) )).toEqual(O.some({ b: 1 })) + expect(pipe( + Services, + Context.get(D) + )).toEqual({ d: 2 }) + expect(pipe( Services, Context.getOption(C) @@ -190,9 +199,9 @@ describe("Context", () => { assert.deepNestedPropertyVal(result, "first._tag", "AndThen") assert.deepNestedPropertyVal(result, "first.first._tag", "Empty") assert.deepNestedPropertyVal(result, "first.second._tag", "UpdateService") - assert.deepNestedPropertyVal(result, "first.second.tag", B) + assert.deepNestedPropertyVal(result, "first.second.key", B.key) assert.deepNestedPropertyVal(result, "second._tag", "RemoveService") - assert.deepNestedPropertyVal(result, "second.tag", C) + assert.deepNestedPropertyVal(result, "second.key", C.key) }) it("error messages", () => { @@ -217,6 +226,14 @@ describe("Context", () => { new RegExp(/Error: Service not found: C \(defined at (.*)Context.test.ts:20:19\)/) ) } + try { + Context.get(Context.empty(), D as never) + } catch (e) { + assert.match( + String(e), + new RegExp(/Error: Service not found: D \(defined at (.*)Context.test.ts:22:32\)/) + ) + } } }) @@ -236,7 +253,7 @@ describe("Context", () => { }) it("isTag", () => { - expect(Context.isTag(Context.Tag())).toEqual(true) + expect(Context.isTag(Context.GenericTag("Demo"))).toEqual(true) expect(Context.isContext(null)).toEqual(false) }) }) diff --git a/packages/effect/test/Effect/environment.test.ts b/packages/effect/test/Effect/environment.test.ts index 8cd5a15ac3..697866f707 100644 --- a/packages/effect/test/Effect/environment.test.ts +++ b/packages/effect/test/Effect/environment.test.ts @@ -8,15 +8,29 @@ interface NumberService { readonly n: number } -const NumberService = Context.Tag() +const NumberService = Context.GenericTag("NumberService") interface StringService { readonly s: string } -const StringService = Context.Tag() +const StringService = Context.GenericTag("StringService") + +class NumberRepo extends Context.Tag("NumberRepo") +}>() { + static numbers = Effect.serviceConstants(NumberRepo).numbers +} describe("Effect", () => { + it.effect("class tag", () => + Effect.gen(function*($) { + yield* $( + Effect.flatMap(NumberRepo.numbers, (_) => Effect.log(`Numbers: ${_}`)).pipe( + Effect.provideService(NumberRepo, { numbers: [0, 1, 2] }) + ) + ) + })) it.effect("environment - provide is modular", () => pipe( Effect.gen(function*($) { @@ -86,7 +100,7 @@ describe("Effect", () => { interface Service { foo: (x: string, y: number) => Effect.Effect } - const Service = Context.Tag() + const Service = Context.GenericTag("Service") const { foo } = Effect.serviceFunctions(Service) return pipe( Effect.gen(function*(_) { @@ -105,7 +119,7 @@ describe("Effect", () => { interface Service { baz: Effect.Effect } - const Service = Context.Tag() + const Service = Context.GenericTag("Service") const { baz } = Effect.serviceConstants(Service) return pipe( Effect.gen(function*(_) { @@ -125,7 +139,7 @@ describe("Effect", () => { foo: (x: string, y: number) => Effect.Effect baz: Effect.Effect } - const Service = Context.Tag() + const Service = Context.GenericTag("Service") const { constants, functions } = Effect.serviceMembers(Service) return pipe( Effect.gen(function*(_) { diff --git a/packages/effect/test/Effect/foreign.test.ts b/packages/effect/test/Effect/foreign.test.ts index be3037c673..e8b3763e10 100644 --- a/packages/effect/test/Effect/foreign.test.ts +++ b/packages/effect/test/Effect/foreign.test.ts @@ -23,7 +23,7 @@ describe("Foreign", () => { })) it.effect("Tag", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $(tag, Effect.provideService(tag, 10)) assert.deepEqual(result, 10) })) diff --git a/packages/effect/test/Effect/provide-runtime.test.ts b/packages/effect/test/Effect/provide-runtime.test.ts index bb6f00ce74..8ec4ec91b1 100644 --- a/packages/effect/test/Effect/provide-runtime.test.ts +++ b/packages/effect/test/Effect/provide-runtime.test.ts @@ -12,7 +12,7 @@ import { assert, describe } from "vitest" interface A { readonly value: number } -const A = Context.Tag() +const A = Context.GenericTag("A") const LiveA = Layer.succeed(A, { value: 1 }) const ref = FiberRef.unsafeMake(0) const LiveEnv = Layer.mergeAll( @@ -29,7 +29,7 @@ describe("Effect", () => { interface SomeService { readonly _: unique symbol } - const SomeService = Context.Tag() + const SomeService = Context.GenericTag("SomeService") return Effect.gen(function*(_) { const rt = yield* _(Layer.succeedContext(Context.empty()), Layer.toRuntime) const pre = yield* _(Effect.context()) diff --git a/packages/effect/test/Effect/query-nested.test.ts b/packages/effect/test/Effect/query-nested.test.ts index a2d7a48e9b..99847fc98e 100644 --- a/packages/effect/test/Effect/query-nested.test.ts +++ b/packages/effect/test/Effect/query-nested.test.ts @@ -11,11 +11,11 @@ import { describe, expect } from "vitest" interface Counter { readonly _: unique symbol } -const Counter = Context.Tag() +const Counter = Context.GenericTag("counter") interface Requests { readonly _: unique symbol } -const Requests = Context.Tag() +const Requests = Context.GenericTag("requests") interface Parent { readonly id: number diff --git a/packages/effect/test/Effect/query.test.ts b/packages/effect/test/Effect/query.test.ts index a624fbb84a..b36d232b65 100644 --- a/packages/effect/test/Effect/query.test.ts +++ b/packages/effect/test/Effect/query.test.ts @@ -18,11 +18,11 @@ import { describe, expect } from "vitest" interface Counter { readonly _: unique symbol } -const Counter = Context.Tag() +const Counter = Context.GenericTag("counter") interface Requests { readonly _: unique symbol } -const Requests = Context.Tag() +const Requests = Context.GenericTag("requests") export const userIds: ReadonlyArray = ReadonlyArray.range(1, 26) diff --git a/packages/effect/test/Effect/scope-ref.test.ts b/packages/effect/test/Effect/scope-ref.test.ts index e9b8086a2b..1bf1905476 100644 --- a/packages/effect/test/Effect/scope-ref.test.ts +++ b/packages/effect/test/Effect/scope-ref.test.ts @@ -1,5 +1,5 @@ import * as it from "effect-test/utils/extend" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import * as FiberRef from "effect/FiberRef" import * as Layer from "effect/Layer" @@ -8,7 +8,7 @@ import * as Logger from "effect/Logger" import { assert, describe } from "vitest" const ref = FiberRef.unsafeMake(List.empty()) -const env = Tag<"context", number>() +const env = GenericTag<"context", number>("context") const withValue = (value: string) => Effect.locallyWith(ref, List.prepend(value)) diff --git a/packages/effect/test/Layer.test.ts b/packages/effect/test/Layer.test.ts index 98732663fb..135306bd6d 100644 --- a/packages/effect/test/Layer.test.ts +++ b/packages/effect/test/Layer.test.ts @@ -24,7 +24,7 @@ export const release3 = "Releasing Module 3" describe("Layer", () => { it.effect("layers can be acquired in parallel", () => Effect.gen(function*($) { - const BoolTag = Context.Tag() + const BoolTag = Context.GenericTag("boolean") const deferred = yield* $(Deferred.make()) const layer1 = Layer.effectContext(Effect.never) const layer2 = Layer.scopedContext( @@ -43,7 +43,7 @@ describe("Layer", () => { })) it.effect("preserves identity of acquired resources", () => Effect.gen(function*($) { - const ChunkTag = Context.Tag>>() + const ChunkTag = Context.GenericTag>>("Ref.Ref>") const testRef = yield* $(Ref.make>(Chunk.empty())) const layer = Layer.scoped( ChunkTag, @@ -107,21 +107,21 @@ describe("Layer", () => { class Config { constructor(readonly value: number) {} } - const ConfigTag = Context.Tag() + const ConfigTag = Context.GenericTag("Config") class A { constructor(readonly value: number) {} } - const ATag = Context.Tag() + const ATag = Context.GenericTag("A") const aLayer = Layer.function(ConfigTag, ATag, (config) => new A(config.value)) class B { constructor(readonly value: number) {} } - const BTag = Context.Tag() + const BTag = Context.GenericTag("B") const bLayer = Layer.function(ATag, BTag, (_: A) => new B(_.value)) class C { constructor(readonly value: number) {} } - const CTag = Context.Tag() + const CTag = Context.GenericTag("C") const cLayer = Layer.function(ATag, CTag, (_: A) => new C(_.value)) const fedB = bLayer.pipe( Layer.provideMerge(aLayer), @@ -161,12 +161,12 @@ describe("Layer", () => { interface Bar { readonly bar: string } - const BarTag = Context.Tag() + const BarTag = Context.GenericTag("Bar") interface Baz { readonly baz: string } - const BazTag = Context.Tag() - const ScopedTag = Context.Tag() + const BazTag = Context.GenericTag("Baz") + const ScopedTag = Context.GenericTag("void") const sleep = Effect.sleep(Duration.millis(100)) const layer1 = Layer.fail("foo") const layer2 = Layer.succeed(BarTag, { bar: "bar" }) @@ -311,12 +311,12 @@ describe("Layer", () => { readonly name: string readonly value: number } - const ServiceATag = Context.Tag() + const ServiceATag = Context.GenericTag("ServiceA") interface ServiceB { readonly name: string } - const ServiceBTag = Context.Tag() - const StringTag = Context.Tag() + const ServiceBTag = Context.GenericTag("ServiceB") + const StringTag = Context.GenericTag("string") const layer1 = Layer.succeed(ServiceATag, { name: "name", value: 1 }) const layer2 = Layer.function(StringTag, ServiceBTag, (name) => ({ name })) const live = layer2.pipe( @@ -347,7 +347,7 @@ describe("Layer", () => { it.scoped("fiberRef changes are memoized", () => Effect.gen(function*($) { const fiberRef = yield* $(FiberRef.make(false)) - const tag = Context.Tag() + const tag = Context.GenericTag("boolean") const layer1 = Layer.scopedDiscard(Effect.locallyScoped(fiberRef, true)) const layer2 = Layer.effect(tag, FiberRef.get(fiberRef)) const layer3 = layer2.pipe( @@ -359,8 +359,8 @@ describe("Layer", () => { })) it.effect("provides a partial environment to an effect", () => Effect.gen(function*($) { - const NumberTag = Context.Tag() - const StringTag = Context.Tag() + const NumberTag = Context.GenericTag("number") + const StringTag = Context.GenericTag("string") const needsNumberAndString = Effect.all([NumberTag, StringTag]) const providesNumber = Layer.succeed(NumberTag, 10) const providesString = Layer.succeed(StringTag, "hi") @@ -371,8 +371,8 @@ describe("Layer", () => { })) it.effect("to provides a partial environment to another layer", () => Effect.gen(function*($) { - const StringTag = Context.Tag() - const NumberRefTag = Context.Tag>() + const StringTag = Context.GenericTag("string") + const NumberRefTag = Context.GenericTag>("Ref.Ref") interface FooService { readonly ref: Ref.Ref readonly string: string @@ -385,7 +385,7 @@ describe("Layer", () => { ] > } - const FooTag = Context.Tag() + const FooTag = Context.GenericTag("FooService") const fooBuilder = Layer.context>().pipe( Layer.map((context) => { const s = Context.get(context, StringTag) @@ -407,8 +407,8 @@ describe("Layer", () => { })) it.effect("andTo provides a partial environment to another layer", () => Effect.gen(function*($) { - const StringTag = Context.Tag() - const NumberRefTag = Context.Tag>() + const StringTag = Context.GenericTag("string") + const NumberRefTag = Context.GenericTag>("Ref.Ref") interface FooService { readonly ref: Ref.Ref readonly string: string @@ -421,7 +421,7 @@ describe("Layer", () => { ] > } - const FooTag = Context.Tag() + const FooTag = Context.GenericTag("FooService") const fooBuilder = Layer.context>().pipe( Layer.map((context) => { const s = Context.get(context, StringTag) @@ -453,11 +453,11 @@ describe("Layer", () => { interface NumberService { readonly value: number } - const NumberTag = Context.Tag() + const NumberTag = Context.GenericTag("NumberService") interface ToStringService { readonly value: string } - const ToStringTag = Context.Tag() + const ToStringTag = Context.GenericTag("ToStringService") const layer = Layer.function(NumberTag, ToStringTag, (numberService) => ({ value: numberService.value.toString() })) @@ -480,8 +480,8 @@ describe("Layer", () => { } interface AgeService extends Pick { } - const PersonTag = Context.Tag() - const AgeTag = Context.Tag() + const PersonTag = Context.GenericTag("PersonService") + const AgeTag = Context.GenericTag("AgeService") const personLayer = Layer.succeed(PersonTag, { name: "User", age: 42 }) const ageLayer = personLayer.pipe(Layer.project(PersonTag, AgeTag, (_) => ({ age: _.age }))) const { age } = yield* $(AgeTag, Effect.provide(ageLayer)) @@ -614,7 +614,7 @@ describe("Layer", () => { interface BarService { readonly bar: string } - const BarTag = Context.Tag() + const BarTag = Context.GenericTag("BarService") const ref: Ref.Ref = yield* $(Ref.make("foo")) const layer = Layer.succeed(BarTag, { bar: "bar" }).pipe( Layer.tap((context) => Ref.set(ref, context.pipe(Context.get(BarTag)).bar)) @@ -628,7 +628,7 @@ describe("Layer", () => { interface BarService { readonly bar: string } - const BarTag = Context.Tag() + const BarTag = Context.GenericTag("BarService") const fiberRef = FiberRef.unsafeMake(0) const layer = Layer.locally(fiberRef, 100)( Layer.effect( @@ -648,7 +648,7 @@ describe("Layer", () => { interface BarService { readonly bar: string } - const BarTag = Context.Tag() + const BarTag = Context.GenericTag("BarService") const fiberRef = FiberRef.unsafeMake(0) const layer = Layer.locallyWith(fiberRef, (n) => n + 1)( Layer.effect( @@ -715,7 +715,7 @@ export class Service1 { return Effect.succeed(1) } } -export const Service1Tag = Context.Tag() +export const Service1Tag = Context.GenericTag("Service1") export const makeLayer1 = (ref: Ref.Ref>): Layer.Layer => { return Layer.scoped( Service1Tag, @@ -730,7 +730,7 @@ export class Service2 { return Effect.succeed(2) } } -export const Service2Tag = Context.Tag() +export const Service2Tag = Context.GenericTag("Service2") export const makeLayer2 = (ref: Ref.Ref>): Layer.Layer => { return Layer.scoped( Service2Tag, @@ -745,7 +745,7 @@ export class Service3 { return Effect.succeed(3) } } -export const Service3Tag = Context.Tag() +export const Service3Tag = Context.GenericTag("Service3") export const makeLayer3 = (ref: Ref.Ref>): Layer.Layer => { return Layer.scoped( Service3Tag, diff --git a/packages/effect/test/Reloadable.test.ts b/packages/effect/test/Reloadable.test.ts index fe5456a82e..6c763a9ee0 100644 --- a/packages/effect/test/Reloadable.test.ts +++ b/packages/effect/test/Reloadable.test.ts @@ -18,7 +18,7 @@ const DummyService: DummyService = { [DummyServiceTypeId]: DummyServiceTypeId } -const Tag = Context.Tag() +const Tag = Context.GenericTag("DummyService") describe("Reloadable", () => { it.effect("initialization", () => diff --git a/packages/effect/test/STM.test.ts b/packages/effect/test/STM.test.ts index a5e69c7d04..aa470f959d 100644 --- a/packages/effect/test/STM.test.ts +++ b/packages/effect/test/STM.test.ts @@ -20,7 +20,7 @@ interface STMEnv { readonly ref: TRef.TRef } -const STMEnv = Context.Tag() +const STMEnv = Context.GenericTag("STMEnv") const makeSTMEnv = (n: number): Effect.Effect => pipe( diff --git a/packages/effect/test/Sink/environment.test.ts b/packages/effect/test/Sink/environment.test.ts index 17f4bac1c6..251bdb25f2 100644 --- a/packages/effect/test/Sink/environment.test.ts +++ b/packages/effect/test/Sink/environment.test.ts @@ -9,7 +9,7 @@ import { assert, describe } from "vitest" describe("Sink", () => { it.effect("contextWithSink", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("string") const sink = pipe( Sink.contextWithSink((env: Context.Context) => Sink.succeed(pipe(env, Context.get(tag)))), Sink.provideContext(pipe(Context.empty(), Context.add(tag, "use this"))) diff --git a/packages/effect/test/Sink/foreign.test.ts b/packages/effect/test/Sink/foreign.test.ts index 0a7ade3d20..1295712ad9 100644 --- a/packages/effect/test/Sink/foreign.test.ts +++ b/packages/effect/test/Sink/foreign.test.ts @@ -15,7 +15,7 @@ const runSink = (sink: Sink.Sink) => Stream. describe("Channel.Foreign", () => { it.effect("Tag", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $(tag, runSink, Effect.provideService(tag, 10)) assert.deepEqual(result, 10) })) diff --git a/packages/effect/test/Stream/environment.test.ts b/packages/effect/test/Stream/environment.test.ts index a2495b6006..3691919cce 100644 --- a/packages/effect/test/Stream/environment.test.ts +++ b/packages/effect/test/Stream/environment.test.ts @@ -14,7 +14,7 @@ interface StringService { readonly string: string } -const StringService = Context.Tag() +const StringService = Context.GenericTag("string") describe("Stream", () => { it.effect("context", () => diff --git a/packages/effect/test/Stream/foreign.test.ts b/packages/effect/test/Stream/foreign.test.ts index efebdd4b24..4c2e8c2b42 100644 --- a/packages/effect/test/Stream/foreign.test.ts +++ b/packages/effect/test/Stream/foreign.test.ts @@ -14,7 +14,7 @@ import { assert, describe } from "vitest" describe("Stream.Foreign", () => { it.effect("Tag", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( tag, Stream.runCollect, @@ -38,7 +38,7 @@ describe("Stream.Foreign", () => { it.effect("Either.right", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( Either.right(10), @@ -51,7 +51,7 @@ describe("Stream.Foreign", () => { it.effect("Either.left", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( Either.left(10), Stream.runCollect, @@ -63,7 +63,7 @@ describe("Stream.Foreign", () => { it.effect("Option.some", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( Option.some(10), Stream.runCollect, @@ -75,7 +75,7 @@ describe("Stream.Foreign", () => { it.effect("Option.none", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( Option.none(), Stream.runCollect, @@ -87,7 +87,7 @@ describe("Stream.Foreign", () => { it.effect("Effect.fail", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( Effect.fail("ok"), Stream.runCollect, @@ -99,7 +99,7 @@ describe("Stream.Foreign", () => { it.effect("Effect.succeed", () => Effect.gen(function*($) { - const tag = Context.Tag() + const tag = Context.GenericTag("number") const result = yield* $( Effect.succeed("ok"), Stream.runCollect, diff --git a/packages/experimental/src/DevTools/Client.ts b/packages/experimental/src/DevTools/Client.ts index 9e3c9356fd..df0b0a592c 100644 --- a/packages/experimental/src/DevTools/Client.ts +++ b/packages/experimental/src/DevTools/Client.ts @@ -36,7 +36,7 @@ export interface Client { * @since 1.0.0 * @category tags */ -export const Client = Context.Tag("@effect/experimental/DevTools/Client") +export const Client = Context.GenericTag("@effect/experimental/DevTools/Client") /** * @since 1.0.0 diff --git a/packages/experimental/src/DevTools/Server.ts b/packages/experimental/src/DevTools/Server.ts index 69eb3a746a..03f7b309cc 100644 --- a/packages/experimental/src/DevTools/Server.ts +++ b/packages/experimental/src/DevTools/Server.ts @@ -41,7 +41,7 @@ export interface Server { * @since 1.0.0 * @category tags */ -export const Server = Context.Tag("@effect/experimental/DevTools/Server") +export const Server = Context.GenericTag("@effect/experimental/DevTools/Server") /** * @since 1.0.0 diff --git a/packages/experimental/src/Persistence.ts b/packages/experimental/src/Persistence.ts index 087d02b1c4..dc8d646d6a 100644 --- a/packages/experimental/src/Persistence.ts +++ b/packages/experimental/src/Persistence.ts @@ -74,8 +74,10 @@ export interface BackingPersistenceStore { * @since 1.0.0 * @category tags */ -export const BackingPersistence: Context.Tag = Context.Tag( - BackingPersistenceTypeId +export const BackingPersistence: Context.Tag = Context.GenericTag< + BackingPersistence +>( + "@effect/experimental/BackingPersistence" ) /** @@ -137,8 +139,10 @@ export declare namespace ResultPersistence { * @since 1.0.0 * @category tags */ -export const ResultPersistence: Context.Tag = Context.Tag( - ResultPersistenceTypeId +export const ResultPersistence: Context.Tag = Context.GenericTag< + ResultPersistence +>( + "@effect/experimental/ResultPersistence" ) /** diff --git a/packages/experimental/src/Socket.ts b/packages/experimental/src/Socket.ts index cef1da8a32..eb2f094315 100644 --- a/packages/experimental/src/Socket.ts +++ b/packages/experimental/src/Socket.ts @@ -31,7 +31,7 @@ export type SocketTypeId = typeof SocketTypeId * @since 1.0.0 * @category tags */ -export const Socket: Context.Tag = Context.Tag( +export const Socket: Context.Tag = Context.GenericTag( "@effect/experimental/Socket" ) @@ -165,7 +165,7 @@ export interface WebSocket { * @since 1.0.0 * @category tags */ -export const WebSocket: Context.Tag = Context.Tag( +export const WebSocket: Context.Tag = Context.GenericTag( "@effect/experimental/Socket/WebSocket" ) diff --git a/packages/experimental/src/Socket/Node.ts b/packages/experimental/src/Socket/Node.ts index 10c218e462..30451b6d77 100644 --- a/packages/experimental/src/Socket/Node.ts +++ b/packages/experimental/src/Socket/Node.ts @@ -30,7 +30,7 @@ export interface NetSocket { * @since 1.0.0 * @category tags */ -export const NetSocket: Context.Tag = Context.Tag( +export const NetSocket: Context.Tag = Context.GenericTag( "@effect/experimental/Socket/Node/NetSocket" ) diff --git a/packages/experimental/src/SocketServer.ts b/packages/experimental/src/SocketServer.ts index b557c94b55..25dd31274f 100644 --- a/packages/experimental/src/SocketServer.ts +++ b/packages/experimental/src/SocketServer.ts @@ -22,7 +22,7 @@ export type SocketServerTypeId = typeof SocketServerTypeId * @since 1.0.0 * @category tags */ -export const SocketServer: Context.Tag = Context.Tag( +export const SocketServer: Context.Tag = Context.GenericTag( "@effect/experimental/SocketServer" ) diff --git a/packages/experimental/src/SocketServer/Node.ts b/packages/experimental/src/SocketServer/Node.ts index 17d4a769b3..c404f3c17b 100644 --- a/packages/experimental/src/SocketServer/Node.ts +++ b/packages/experimental/src/SocketServer/Node.ts @@ -31,7 +31,7 @@ export interface IncomingMessage { * @since 1.0.0 * @category tags */ -export const IncomingMessage = Context.Tag( +export const IncomingMessage = Context.GenericTag( "@effect/experimental/SocketServer/Node/IncomingMessage" ) diff --git a/packages/opentelemetry/src/Resource.ts b/packages/opentelemetry/src/Resource.ts index 8f7bd1a516..1ea190bf6e 100644 --- a/packages/opentelemetry/src/Resource.ts +++ b/packages/opentelemetry/src/Resource.ts @@ -3,7 +3,7 @@ */ import * as Resources from "@opentelemetry/resources" import { SemanticResourceAttributes, TelemetrySdkLanguageValues } from "@opentelemetry/semantic-conventions" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Layer from "effect/Layer" /** @@ -18,7 +18,7 @@ export interface Resource { * @since 1.0.0 * @category tag */ -export const Resource = Tag("@effect/opentelemetry/Resource") +export const Resource = GenericTag("@effect/opentelemetry/Resource") /** * @since 1.0.0 diff --git a/packages/opentelemetry/src/internal/tracer.ts b/packages/opentelemetry/src/internal/tracer.ts index 511f40e8e4..6ca75d09ed 100644 --- a/packages/opentelemetry/src/internal/tracer.ts +++ b/packages/opentelemetry/src/internal/tracer.ts @@ -104,10 +104,10 @@ export class OtelSpan implements EffectTracer.Span { } /** @internal */ -export const TracerProvider = Context.Tag("@effect/opentelemetry/Tracer/TracerProvider") +export const TracerProvider = Context.GenericTag("@effect/opentelemetry/Tracer/TracerProvider") /** @internal */ -export const Tracer = Context.Tag("@effect/opentelemetry/Tracer/Tracer") +export const Tracer = Context.GenericTag("@effect/opentelemetry/Tracer/Tracer") /** @internal */ export const make = Effect.map(Tracer, (tracer) => @@ -124,7 +124,7 @@ export const make = Effect.map(Tracer, (tracer) => ) }, context(execution, fiber) { - const currentSpan = fiber.getFiberRef(FiberRef.currentContext).unsafeMap.get(EffectTracer.ParentSpan) as + const currentSpan = fiber.getFiberRef(FiberRef.currentContext).unsafeMap.get(EffectTracer.ParentSpan.key) as | EffectTracer.ParentSpan | undefined @@ -140,10 +140,10 @@ export const make = Effect.map(Tracer, (tracer) => })) /** @internal */ -export const traceFlagsTag = Context.Tag("@effect/opentelemetry/traceFlags") +export const traceFlagsTag = Context.GenericTag("@effect/opentelemetry/traceFlags") /** @internal */ -export const traceStateTag = Context.Tag("@effect/opentelemetry/traceState") +export const traceStateTag = Context.GenericTag("@effect/opentelemetry/traceState") /** @internal */ export const makeExternalSpan = (options: { diff --git a/packages/opentelemetry/src/tsconfig.json b/packages/opentelemetry/src/tsconfig.json deleted file mode 100644 index 8980ff177f..0000000000 --- a/packages/opentelemetry/src/tsconfig.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "compilerOptions": { - "moduleDetection": "force", - "downlevelIteration": true, - "resolveJsonModule": true, - "esModuleInterop": true, - "skipLibCheck": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "preserveSymlinks": true, - "moduleResolution": "NodeNext", - "lib": [ - "ES2021", - "DOM", - "DOM.Iterable" - ], - "sourceMap": true, - "strict": true, - "noImplicitReturns": false, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true, - "noEmitOnError": false, - "allowJs": false, - "checkJs": false, - "forceConsistentCasingInFileNames": true, - "stripInternal": true, - "noImplicitAny": true, - "noImplicitThis": true, - "noUncheckedIndexedAccess": false, - "strictNullChecks": true, - "target": "ES2021", - "module": "NodeNext", - "incremental": true, - "removeComments": false, - "paths": { - "@effect/opentelemetry": [ - "./index.ts" - ], - "@effect/opentelemetry/*": [ - "./*.ts" - ] - } - }, - "include": [ - "**/*" - ] -} diff --git a/packages/platform-browser/src/internal/clipboard.ts b/packages/platform-browser/src/internal/clipboard.ts index 6ddca623ef..bef7c49e94 100644 --- a/packages/platform-browser/src/internal/clipboard.ts +++ b/packages/platform-browser/src/internal/clipboard.ts @@ -1,11 +1,11 @@ import * as PlatformError from "@effect/platform/Error" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" import type * as Clipboard from "../Clipboard.js" /** @internal */ -export const tag = Tag("@effect/platform-browser/Clipboard") +export const tag = GenericTag("@effect/platform-browser/Clipboard") /** @internal */ export const make = ( diff --git a/packages/platform-browser/test/fixtures/serializedWorker.ts b/packages/platform-browser/test/fixtures/serializedWorker.ts index 0ff1fe0b18..fbbe2a1e27 100644 --- a/packages/platform-browser/test/fixtures/serializedWorker.ts +++ b/packages/platform-browser/test/fixtures/serializedWorker.ts @@ -5,7 +5,7 @@ import { Person, User, WorkerMessage } from "./schema.js" interface Name { readonly _: unique symbol } -const Name = Context.Tag() +const Name = Context.GenericTag("Name") const WorkerLive = Runner.layerSerialized(WorkerMessage, { GetPersonById: (req) => diff --git a/packages/platform-bun/examples/http-client.ts b/packages/platform-bun/examples/http-client.ts index eed549dc5e..09a7731f70 100644 --- a/packages/platform-bun/examples/http-client.ts +++ b/packages/platform-bun/examples/http-client.ts @@ -19,7 +19,7 @@ interface TodoService { _: TodoWithoutId ) => Effect.Effect } -const TodoService = Context.Tag() +const TodoService = Context.GenericTag("@effect/platform-bun/examples/TodoService") const makeTodoService = Effect.gen(function*(_) { const defaultClient = yield* _(Http.client.Client) diff --git a/packages/platform-bun/examples/worker.ts b/packages/platform-bun/examples/worker.ts index 5cafc9fad1..60428470d3 100644 --- a/packages/platform-bun/examples/worker.ts +++ b/packages/platform-bun/examples/worker.ts @@ -6,7 +6,7 @@ import * as OS from "node:os" interface MyWorkerPool { readonly _: unique symbol } -const Pool = Context.Tag>("@app/MyWorkerPool") +const Pool = Context.GenericTag>("@app/MyWorkerPool") const PoolLive = BunWorker.makePoolLayer(Pool, { spawn: () => new globalThis.Worker("./examples/worker/range.ts"), minSize: 0, diff --git a/packages/platform-node-shared/tsconfig.build.json b/packages/platform-node-shared/tsconfig.build.json index 972fb14a53..37a515c3b6 100644 --- a/packages/platform-node-shared/tsconfig.build.json +++ b/packages/platform-node-shared/tsconfig.build.json @@ -1,14 +1,23 @@ { "extends": "./tsconfig.src.json", "references": [ - { "path": "../platform" }, - { "path": "../effect" }, - { "path": "../schema" } + { + "path": "../platform" + }, + { + "path": "../effect" + }, + { + "path": "../schema" + } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", "outDir": "build/esm", "declarationDir": "build/dts", - "stripInternal": true + "stripInternal": true, + "types": [ + "node" + ] } } diff --git a/packages/platform-node/examples/http-client.ts b/packages/platform-node/examples/http-client.ts index 1ef54670a7..00318a3cb8 100644 --- a/packages/platform-node/examples/http-client.ts +++ b/packages/platform-node/examples/http-client.ts @@ -21,7 +21,7 @@ interface TodoService { _: TodoWithoutId ) => Effect.Effect } -const TodoService = Context.Tag() +const TodoService = Context.GenericTag("@effect/platform-node/examples/TodoService") const makeTodoService = Effect.gen(function*(_) { const defaultClient = yield* _(Http.client.Client) diff --git a/packages/platform-node/examples/worker.ts b/packages/platform-node/examples/worker.ts index 2286584076..de4d39573d 100644 --- a/packages/platform-node/examples/worker.ts +++ b/packages/platform-node/examples/worker.ts @@ -6,7 +6,7 @@ import * as WT from "node:worker_threads" interface MyWorkerPool { readonly _: unique symbol } -const Pool = Context.Tag>("@app/MyWorkerPool") +const Pool = Context.GenericTag>("@app/MyWorkerPool") const PoolLive = NodeWorker.makePoolLayer(Pool, { spawn: () => new WT.Worker("./examples/worker/range.ts"), minSize: 0, diff --git a/packages/platform-node/src/internal/http/client.ts b/packages/platform-node/src/internal/http/client.ts index 2ace7ab1e9..ba2e943dbb 100644 --- a/packages/platform-node/src/internal/http/client.ts +++ b/packages/platform-node/src/internal/http/client.ts @@ -24,7 +24,7 @@ export const HttpAgentTypeId: NodeClient.HttpAgentTypeId = Symbol.for( ) as NodeClient.HttpAgentTypeId /** @internal */ -export const HttpAgent = Context.Tag(HttpAgentTypeId) +export const HttpAgent = Context.GenericTag("@effect/platform-node/Http/NodeClient/HttpAgent") /** @internal */ export const makeAgent = (options?: Https.AgentOptions): Effect.Effect => diff --git a/packages/platform-node/test/Http/NodeClient.test.ts b/packages/platform-node/test/Http/NodeClient.test.ts index 3debcb158b..9f58460973 100644 --- a/packages/platform-node/test/Http/NodeClient.test.ts +++ b/packages/platform-node/test/Http/NodeClient.test.ts @@ -33,7 +33,7 @@ const makeJsonPlaceholder = Effect.gen(function*(_) { } as const }) interface JsonPlaceholder extends Effect.Effect.Success {} -const JsonPlaceholder = Context.Tag() +const JsonPlaceholder = Context.GenericTag("test/JsonPlaceholder") const JsonPlaceholderLive = Layer.provide( Layer.effect(JsonPlaceholder, makeJsonPlaceholder), NodeClient.layer diff --git a/packages/platform/src/KeyValueStore.ts b/packages/platform/src/KeyValueStore.ts index 186158ba27..b0b4189243 100644 --- a/packages/platform/src/KeyValueStore.ts +++ b/packages/platform/src/KeyValueStore.ts @@ -200,7 +200,7 @@ export interface SchemaStore { */ export const layerSchema: ( schema: Schema.Schema, - tagIdentifier?: unknown + tagIdentifier: string ) => { readonly tag: Context.Tag, SchemaStore> readonly layer: Layer.Layer> diff --git a/packages/platform/src/internal/commandExecutor.ts b/packages/platform/src/internal/commandExecutor.ts index d526471220..1b71ba50cf 100644 --- a/packages/platform/src/internal/commandExecutor.ts +++ b/packages/platform/src/internal/commandExecutor.ts @@ -1,6 +1,6 @@ import * as Brand from "effect/Brand" import * as Chunk from "effect/Chunk" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Sink from "effect/Sink" @@ -19,7 +19,7 @@ export const ExitCode = Brand.nominal<_CommandExecutor.ExitCode>() export const ProcessId = Brand.nominal<_CommandExecutor.Process.Id>() /** @internal */ -export const CommandExecutor = Tag<_CommandExecutor.CommandExecutor>("@effect/platform/CommandExecutor") +export const CommandExecutor = GenericTag<_CommandExecutor.CommandExecutor>("@effect/platform/CommandExecutor") /** @internal */ export const makeExecutor = (start: _CommandExecutor.CommandExecutor["start"]): _CommandExecutor.CommandExecutor => { diff --git a/packages/platform/src/internal/fileSystem.ts b/packages/platform/src/internal/fileSystem.ts index 5fd0659860..5071547b81 100644 --- a/packages/platform/src/internal/fileSystem.ts +++ b/packages/platform/src/internal/fileSystem.ts @@ -1,6 +1,6 @@ import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import { identity, pipe } from "effect/Function" import * as Option from "effect/Option" @@ -10,7 +10,7 @@ import * as Error from "../Error.js" import type { File, FileSystem, Size as Size_, SizeInput, StreamOptions } from "../FileSystem.js" /** @internal */ -export const tag = Tag("@effect/platform/FileSystem") +export const tag = GenericTag("@effect/platform/FileSystem") /** @internal */ export const Size = (bytes: SizeInput) => typeof bytes === "bigint" ? bytes as Size_ : BigInt(bytes) as Size_ diff --git a/packages/platform/src/internal/http/client.ts b/packages/platform/src/internal/http/client.ts index 16bbe12da5..9faf097179 100644 --- a/packages/platform/src/internal/http/client.ts +++ b/packages/platform/src/internal/http/client.ts @@ -26,7 +26,7 @@ export const TypeId: Client.TypeId = Symbol.for( ) as Client.TypeId /** @internal */ -export const tag = Context.Tag(TypeId) +export const tag = Context.GenericTag("@effect/platform/Http/Client") const clientProto = { [TypeId]: TypeId, @@ -76,8 +76,8 @@ export const makeDefault = ( ): Client.Client.Default => make(Effect.flatMap(f), addB3Headers) /** @internal */ -export const Fetch = Context.Tag( - Symbol.for("@effect/platform/Http/Client/Fetch") +export const Fetch = Context.GenericTag( + "@effect/platform/Http/Client/Fetch" ) /** @internal */ diff --git a/packages/platform/src/internal/http/etag.ts b/packages/platform/src/internal/http/etag.ts index 05cf54503f..87ed9dbb88 100644 --- a/packages/platform/src/internal/http/etag.ts +++ b/packages/platform/src/internal/http/etag.ts @@ -7,7 +7,7 @@ export const GeneratorTypeId: Etag.GeneratorTypeId = Symbol.for( ) as Etag.GeneratorTypeId /** @internal */ -export const tag = Context.Tag(GeneratorTypeId) +export const tag = Context.GenericTag("@effect/platform/Http/Etag/Generator") /** @internal */ export const toString = (self: Etag.Etag): string => { diff --git a/packages/platform/src/internal/http/platform.ts b/packages/platform/src/internal/http/platform.ts index 8e1e183caa..2058cffb1f 100644 --- a/packages/platform/src/internal/http/platform.ts +++ b/packages/platform/src/internal/http/platform.ts @@ -12,7 +12,7 @@ import type * as ServerResponse from "../../Http/ServerResponse.js" export const TypeId: Platform.TypeId = Symbol.for("@effect/platform/Http/Platform") as Platform.TypeId /** @internal */ -export const tag = Context.Tag(TypeId) +export const tag = Context.GenericTag("@effect/platform/Http/Platform") /** @internal */ export const make = (impl: { diff --git a/packages/platform/src/internal/http/router.ts b/packages/platform/src/internal/http/router.ts index d063e47e7a..378552f042 100644 --- a/packages/platform/src/internal/http/router.ts +++ b/packages/platform/src/internal/http/router.ts @@ -27,7 +27,7 @@ export const RouteContextTypeId: Router.RouteContextTypeId = Symbol.for( ) as Router.RouteContextTypeId /** @internal */ -export const RouteContext = Context.Tag("@effect/platform/Http/Router/RouteContext") +export const RouteContext = Context.GenericTag("@effect/platform/Http/Router/RouteContext") /** @internal */ export const params = Effect.map(RouteContext, (_) => _.params) diff --git a/packages/platform/src/internal/http/server.ts b/packages/platform/src/internal/http/server.ts index 6ddbc143ee..5ea98655d0 100644 --- a/packages/platform/src/internal/http/server.ts +++ b/packages/platform/src/internal/http/server.ts @@ -12,7 +12,7 @@ import type * as ServerRequest from "../../Http/ServerRequest.js" export const TypeId: Server.TypeId = Symbol.for("@effect/platform/Http/Server") as Server.TypeId /** @internal */ -export const serverTag = Context.Tag(TypeId) +export const serverTag = Context.GenericTag("@effect/platform/Http/Server") const serverProto = { [TypeId]: TypeId diff --git a/packages/platform/src/internal/http/serverRequest.ts b/packages/platform/src/internal/http/serverRequest.ts index be87c164e3..0d2bd1d85d 100644 --- a/packages/platform/src/internal/http/serverRequest.ts +++ b/packages/platform/src/internal/http/serverRequest.ts @@ -19,7 +19,7 @@ import type * as Path from "../../Path.js" export const TypeId: ServerRequest.TypeId = Symbol.for("@effect/platform/Http/ServerRequest") as ServerRequest.TypeId /** @internal */ -export const serverRequestTag = Context.Tag(TypeId) +export const serverRequestTag = Context.GenericTag("@effect/platform/Http/ServerRequest") /** @internal */ export const multipartPersisted = Effect.flatMap(serverRequestTag, (request) => request.multipart) diff --git a/packages/platform/src/internal/keyValueStore.ts b/packages/platform/src/internal/keyValueStore.ts index dc411b45ec..dbba27c3eb 100644 --- a/packages/platform/src/internal/keyValueStore.ts +++ b/packages/platform/src/internal/keyValueStore.ts @@ -14,7 +14,7 @@ export const TypeId: KeyValueStore.TypeId = Symbol.for( ) as KeyValueStore.TypeId /** @internal */ -export const keyValueStoreTag = Context.Tag(TypeId) +export const keyValueStoreTag = Context.GenericTag("@effect/platform/KeyValueStore") /** @internal */ export const make: ( @@ -168,9 +168,9 @@ export const layerFileSystem = (directory: string) => /** @internal */ export const layerSchema = ( schema: Schema.Schema, - tagIdentifier?: unknown + tagIdentifier: string ) => { - const tag = Context.Tag>(tagIdentifier) + const tag = Context.GenericTag>(tagIdentifier) const layer = Layer.effect(tag, Effect.map(keyValueStoreTag, (store) => store.forSchema(schema))) return { tag, layer } as const } diff --git a/packages/platform/src/internal/path.ts b/packages/platform/src/internal/path.ts index 899e799114..3934f8d22e 100644 --- a/packages/platform/src/internal/path.ts +++ b/packages/platform/src/internal/path.ts @@ -1,4 +1,4 @@ -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import { identity } from "effect/Function" import * as Layer from "effect/Layer" @@ -7,7 +7,7 @@ import { BadArgument } from "../Error.js" import type { Path as _Path } from "../Path.js" /** @internal */ -export const Path = Tag<_Path>("@effect/platform/Path") +export const Path = GenericTag<_Path>("@effect/platform/Path") /** @internal */ export const layer = Layer.succeed( diff --git a/packages/platform/src/internal/terminal.ts b/packages/platform/src/internal/terminal.ts index 2b542e02c4..b0e3f22767 100644 --- a/packages/platform/src/internal/terminal.ts +++ b/packages/platform/src/internal/terminal.ts @@ -1,5 +1,5 @@ -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import type * as Terminal from "../Terminal.js" /** @internal */ -export const tag = Tag("@effect/platform/Terminal") +export const tag = GenericTag("@effect/platform/Terminal") diff --git a/packages/platform/src/internal/worker.ts b/packages/platform/src/internal/worker.ts index 0ced6690f1..5f519fadd0 100644 --- a/packages/platform/src/internal/worker.ts +++ b/packages/platform/src/internal/worker.ts @@ -39,8 +39,8 @@ export const PlatformWorkerTypeId: Worker.PlatformWorkerTypeId = Symbol.for( ) as Worker.PlatformWorkerTypeId /** @internal */ -export const PlatformWorker = Context.Tag( - PlatformWorkerTypeId +export const PlatformWorker = Context.GenericTag( + "@effect/platform/Worker/PlatformWorker" ) /** @internal */ @@ -49,8 +49,8 @@ export const WorkerManagerTypeId: Worker.WorkerManagerTypeId = Symbol.for( ) as Worker.WorkerManagerTypeId /** @internal */ -export const WorkerManager = Context.Tag( - WorkerManagerTypeId +export const WorkerManager = Context.GenericTag( + "@effect/platform/Worker/WorkerManager" ) /** @internal */ diff --git a/packages/platform/src/internal/workerRunner.ts b/packages/platform/src/internal/workerRunner.ts index 8aa2f24f35..75c92942d4 100644 --- a/packages/platform/src/internal/workerRunner.ts +++ b/packages/platform/src/internal/workerRunner.ts @@ -25,8 +25,8 @@ export const PlatformRunnerTypeId: WorkerRunner.PlatformRunnerTypeId = Symbol.fo ) as WorkerRunner.PlatformRunnerTypeId /** @internal */ -export const PlatformRunner = Context.Tag( - PlatformRunnerTypeId +export const PlatformRunner = Context.GenericTag( + "@effect/platform/Runner/PlatformRunner" ) /** @internal */ diff --git a/packages/platform/test/HttpClient.test.ts b/packages/platform/test/HttpClient.test.ts index 06580ec880..784134ed3d 100644 --- a/packages/platform/test/HttpClient.test.ts +++ b/packages/platform/test/HttpClient.test.ts @@ -36,7 +36,7 @@ const makeJsonPlaceholder = Effect.gen(function*(_) { } as const }) interface JsonPlaceholder extends Effect.Effect.Success {} -const JsonPlaceholder = Context.Tag() +const JsonPlaceholder = Context.GenericTag("test/JsonPlaceholder") const JsonPlaceholderLive = Layer.effect(JsonPlaceholder, makeJsonPlaceholder) .pipe(Layer.provide(Http.client.layer)) diff --git a/packages/platform/test/KeyValueStore.test.ts b/packages/platform/test/KeyValueStore.test.ts index 60bc09c91a..aa6dd7acd5 100644 --- a/packages/platform/test/KeyValueStore.test.ts +++ b/packages/platform/test/KeyValueStore.test.ts @@ -114,7 +114,7 @@ class User extends Schema.Class()({ name: Schema.string, age: Schema.number }) {} -const UserStore = KeyValueStore.layerSchema(User) +const UserStore = KeyValueStore.layerSchema(User, "UserStore") const runUserStore = (effect: Effect.Effect, E, A>) => Effect.runPromise(Effect.provide(effect, UserStore.layer.pipe(Layer.provide(KeyValueStore.layerMemory)))) diff --git a/packages/rpc-http-node/src/Server.ts b/packages/rpc-http-node/src/Server.ts index e6a8f6ed6d..6466cef434 100644 --- a/packages/rpc-http-node/src/Server.ts +++ b/packages/rpc-http-node/src/Server.ts @@ -14,7 +14,7 @@ import type { Readable } from "node:stream" * @category tags * @since 1.0.0 */ -export const IncomingMessage = Context.Tag("@effect/rpc-http-node/IncomingMessage") +export const IncomingMessage = Context.GenericTag("@effect/rpc-http-node/IncomingMessage") /** * @category models diff --git a/packages/rpc-nextjs/src/Server.ts b/packages/rpc-nextjs/src/Server.ts index bc5a98dfbf..471008fd93 100644 --- a/packages/rpc-nextjs/src/Server.ts +++ b/packages/rpc-nextjs/src/Server.ts @@ -12,7 +12,7 @@ import type { NextApiRequest, NextApiResponse } from "next" * @category tags * @since 1.0.0 */ -export const ApiRequest = Context.Tag("@effect/rpc-nextjs/ApiRequest") +export const ApiRequest = Context.GenericTag("@effect/rpc-nextjs/ApiRequest") /** * @category models diff --git a/packages/rpc-workers/src/internal/resolver.ts b/packages/rpc-workers/src/internal/resolver.ts index e806697218..3ce675db97 100644 --- a/packages/rpc-workers/src/internal/resolver.ts +++ b/packages/rpc-workers/src/internal/resolver.ts @@ -1,7 +1,7 @@ import * as Worker from "@effect/platform/Worker" import { RpcTransportError } from "@effect/rpc/Error" import * as Resolver from "@effect/rpc/Resolver" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" import type { Scope } from "effect/Scope" @@ -9,7 +9,7 @@ import type * as WWResolver from "../Resolver.js" import * as schema from "../Schema.js" /** @internal */ -export const RpcWorkerPool = Tag() +export const RpcWorkerPool = GenericTag("@effect/rpc-workers/RpcWorkerPool") /** @internal */ export const makePool = ( diff --git a/packages/rpc-workers/test/e2e/schema.ts b/packages/rpc-workers/test/e2e/schema.ts index 81f4ccb4fd..33352c331d 100644 --- a/packages/rpc-workers/test/e2e/schema.ts +++ b/packages/rpc-workers/test/e2e/schema.ts @@ -1,6 +1,6 @@ import * as Schema from "@effect/rpc-workers/Schema" import * as S from "@effect/schema/Schema" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" export const schema = Schema.make({ currentDate: { @@ -23,7 +23,7 @@ export interface Name { readonly name: string } -export const Name = Tag() +export const Name = GenericTag("Name") export const schemaWithSetup = Schema.make({ __setup: { diff --git a/packages/rpc/test/Client.test.ts b/packages/rpc/test/Client.test.ts index 6282baf48b..cae434106e 100644 --- a/packages/rpc/test/Client.test.ts +++ b/packages/rpc/test/Client.test.ts @@ -7,7 +7,7 @@ import * as Server from "@effect/rpc/Server" import { typeEquals } from "@effect/rpc/test/utils" import * as S from "@effect/schema/Schema" import { Cause } from "effect" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" @@ -30,7 +30,7 @@ const makeCounter = () => { } as const } interface Counter extends ReturnType {} -const Counter = Tag() +const Counter = GenericTag("Counter") const posts = RS.withServiceError( RS.make({ diff --git a/packages/rpc/test/Router.test.ts b/packages/rpc/test/Router.test.ts index e49395a043..0cffc2cecf 100644 --- a/packages/rpc/test/Router.test.ts +++ b/packages/rpc/test/Router.test.ts @@ -2,7 +2,7 @@ import * as _ from "@effect/rpc/Router" import * as RS from "@effect/rpc/Schema" import { typeEquals } from "@effect/rpc/test/utils" import * as S from "@effect/schema/Schema" -import { Tag } from "effect/Context" +import { GenericTag } from "effect/Context" import * as Effect from "effect/Effect" import * as Either from "effect/Either" import { describe, expect, it } from "vitest" @@ -15,7 +15,7 @@ const makeCounter = () => { } } interface Counter extends ReturnType {} -const Counter = Tag() +const Counter = GenericTag("Counter") const SomeError_ = S.struct({ _tag: S.literal("SomeError"), diff --git a/packages/schema/README.md b/packages/schema/README.md index 60145dddea..503500751a 100644 --- a/packages/schema/README.md +++ b/packages/schema/README.md @@ -2434,7 +2434,7 @@ import * as Context from "effect/Context"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; -const Fetch = Context.Tag<"Fetch", typeof fetch>(); +const Fetch = Context.GenericTag<"Fetch", typeof fetch>(); const api = (url: string): Effect.Effect<"Fetch", Error, unknown> => Fetch.pipe( diff --git a/packages/schema/dtslint/Context.ts b/packages/schema/dtslint/Context.ts index 9d3a48a92d..e53a4a920e 100644 --- a/packages/schema/dtslint/Context.ts +++ b/packages/schema/dtslint/Context.ts @@ -7,10 +7,10 @@ declare const aContext: Schema.Schema declare const bContext: Schema.Schema declare const cContext: Schema.Schema -const Taga = Context.Tag<"a", string>() -const Tagb = Context.Tag<"b", number>() -const Tag1 = Context.Tag<"Tag1", string>() -const Tag2 = Context.Tag<"Tag2", number>() +const Taga = Context.GenericTag<"a", string>("a") +const Tagb = Context.GenericTag<"b", number>("b") +const Tag1 = Context.GenericTag<"Tag1", string>("Tag1") +const Tag2 = Context.GenericTag<"Tag2", number>("Tag2") // --------------------------------------------- // declare diff --git a/packages/schema/test/Schema/Class.test.ts b/packages/schema/test/Schema/Class.test.ts index b0484197a8..23656c3fed 100644 --- a/packages/schema/test/Schema/Class.test.ts +++ b/packages/schema/test/Schema/Class.test.ts @@ -20,7 +20,7 @@ class Person extends S.Class()({ } } -const Name = Context.Tag<"Name", string>() +const Name = Context.GenericTag<"Name", string>("Name") const NameString = S.string.pipe( S.nonEmpty(), S.transformOrFail( @@ -36,7 +36,7 @@ const NameString = S.string.pipe( ) ) -const Id = Context.Tag<"Id", number>() +const Id = Context.GenericTag<"Id", number>("Name") const IdNumber = S.number.pipe( S.transformOrFail( S.number, diff --git a/packages/schema/test/util.ts b/packages/schema/test/util.ts index 9557fff101..3b49b0c300 100644 --- a/packages/schema/test/util.ts +++ b/packages/schema/test/util.ts @@ -287,7 +287,7 @@ export const AsyncDeclaration = S.declare( export const AsyncString = effectify(S.string).pipe(S.identifier("AsyncString")) -const Name = Context.Tag<"Name", string>() +const Name = Context.GenericTag<"Name", string>("Name") export const DependencyString = S.transformOrFail( S.string,