@effect-app/vue 2.77.2 → 2.77.3

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.
@@ -1120,590 +1120,585 @@ export const CommanderStatic = {
1120
1120
  })
1121
1121
  }
1122
1122
 
1123
- // @effect-diagnostics-next-line missingEffectServiceDependency:off
1124
- export class Commander extends Effect.Service<Commander>()("Commander", {
1125
- dependencies: [WithToast.Default, Confirm.Default],
1126
- effect: Effect.gen(function*() {
1127
- const { intl } = yield* I18n
1123
+ const makeBaseInfo = <const Id extends string, const I18nKey extends string = Id>(
1124
+ id: Id,
1125
+ options?: Pick<FnOptionsInternal<I18nKey>, "i18nCustomKey">
1126
+ ) => {
1127
+ if (!id) throw new Error("must specify an id")
1128
+ const i18nKey: I18nKey = options?.i18nCustomKey ?? id as unknown as I18nKey
1129
+
1130
+ const namespace = `action.${i18nKey}` as const
1131
+
1132
+ const context = {
1133
+ id,
1134
+ i18nKey,
1135
+ namespace,
1136
+ namespaced: <const K extends string>(k: K) => `${namespace}.${k}` as const
1137
+ }
1128
1138
 
1129
- const makeBaseInfo = <const Id extends string, const I18nKey extends string = Id>(
1130
- id: Id,
1131
- options?: Pick<FnOptionsInternal<I18nKey>, "i18nCustomKey">
1132
- ) => {
1133
- if (!id) throw new Error("must specify an id")
1134
- const i18nKey: I18nKey = options?.i18nCustomKey ?? id as unknown as I18nKey
1139
+ return context
1140
+ }
1135
1141
 
1136
- const namespace = `action.${i18nKey}` as const
1142
+ const getStateValues = <const I18nKey extends string, State extends IntlRecord | undefined>(
1143
+ options?: FnOptions<I18nKey, State>
1144
+ ): ComputedRef<State> => {
1145
+ const state_ = options?.state
1146
+ const state = !state_ ? computed(() => undefined as State) : typeof state_ === "function"
1147
+ ? computed(state_)
1148
+ : state_
1149
+ return state
1150
+ }
1137
1151
 
1138
- const context = {
1139
- id,
1140
- i18nKey,
1141
- namespace,
1142
- namespaced: <const K extends string>(k: K) => `${namespace}.${k}` as const
1143
- }
1152
+ // class preserves JSDoc throughout..
1153
+ export class CommanderImpl<RT> {
1154
+ private runFork: <A, E>(
1155
+ effect: Effect.Effect<A, E, RT>,
1156
+ options?: Runtime.RunForkOptions | undefined
1157
+ ) => RuntimeFiber<A, E>
1144
1158
 
1145
- return context
1146
- }
1159
+ constructor(private readonly rt: Runtime.Runtime<RT>, private readonly intl: I18n) {
1160
+ this.runFork = Runtime.runFork(this.rt)
1161
+ }
1147
1162
 
1148
- const makeContext = <const Id extends string, const I18nKey extends string = Id>(
1149
- id: Id,
1150
- options?: FnOptionsInternal<I18nKey>
1151
- ) => {
1152
- if (!id) throw new Error("must specify an id")
1153
- const i18nKey: I18nKey = options?.i18nCustomKey ?? id as unknown as I18nKey
1154
-
1155
- const namespace = `action.${i18nKey}` as const
1156
-
1157
- // must remain stable through out single call
1158
- const action = intl.formatMessage({
1159
- id: namespace,
1160
- defaultMessage: id
1161
- }, options?.state)
1162
- const context = CommandContext.of({
1163
- ...makeBaseInfo(id, options),
1164
- action,
1165
- state: options?.state
1166
- })
1167
-
1168
- return context
1169
- }
1163
+ readonly makeContext = <const Id extends string, const I18nKey extends string = Id>(
1164
+ id: Id,
1165
+ options?: FnOptionsInternal<I18nKey>
1166
+ ) => {
1167
+ if (!id) throw new Error("must specify an id")
1168
+ const i18nKey: I18nKey = options?.i18nCustomKey ?? id as unknown as I18nKey
1169
+
1170
+ const namespace = `action.${i18nKey}` as const
1171
+
1172
+ // must remain stable through out single call
1173
+ const action = this.intl.formatMessage({
1174
+ id: namespace,
1175
+ defaultMessage: id
1176
+ }, options?.state)
1177
+ const context = CommandContext.of({
1178
+ ...makeBaseInfo(id, options),
1179
+ action,
1180
+ state: options?.state
1181
+ })
1170
1182
 
1171
- const getStateValues = <const I18nKey extends string, State extends IntlRecord | undefined>(
1172
- options?: FnOptions<I18nKey, State>
1173
- ): ComputedRef<State> => {
1174
- const state_ = options?.state
1175
- const state = !state_ ? computed(() => undefined as State) : typeof state_ === "function"
1176
- ? computed(state_)
1177
- : state_
1178
- return state
1179
- }
1183
+ return context
1184
+ }
1180
1185
 
1181
- const makeCommand = <RT>(runtime: Runtime.Runtime<RT>) => {
1182
- const runFork = Runtime.runFork(runtime)
1183
- return <const Id extends string, const State extends IntlRecord | undefined, const I18nKey extends string = Id>(
1184
- id_: Id | { id: Id },
1185
- options?: FnOptions<I18nKey, State>,
1186
- errorDef?: Error
1186
+ readonly makeCommand = <
1187
+ const Id extends string,
1188
+ const State extends IntlRecord | undefined,
1189
+ const I18nKey extends string = Id
1190
+ >(
1191
+ id_: Id | { id: Id },
1192
+ options?: FnOptions<I18nKey, State>,
1193
+ errorDef?: Error
1194
+ ) => {
1195
+ const id = typeof id_ === "string" ? id_ : id_.id
1196
+ const state = getStateValues(options)
1197
+
1198
+ return Object.assign(
1199
+ <Args extends ReadonlyArray<unknown>, A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`>(
1200
+ handler: (...args: Args) => Effect.Effect<A, E, R>
1187
1201
  ) => {
1188
- const id = typeof id_ === "string" ? id_ : id_.id
1189
- const state = getStateValues(options)
1190
-
1191
- return Object.assign(
1192
- <Args extends ReadonlyArray<unknown>, A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`>(
1193
- handler: (...args: Args) => Effect.Effect<A, E, R>
1194
- ) => {
1195
- // we capture the definition stack here, so we can append it to later stack traces
1196
- const limit = Error.stackTraceLimit
1197
- Error.stackTraceLimit = 2
1198
- const localErrorDef = new Error()
1199
- Error.stackTraceLimit = limit
1200
- if (!errorDef) {
1201
- errorDef = localErrorDef
1202
- }
1202
+ // we capture the definition stack here, so we can append it to later stack traces
1203
+ const limit = Error.stackTraceLimit
1204
+ Error.stackTraceLimit = 2
1205
+ const localErrorDef = new Error()
1206
+ Error.stackTraceLimit = limit
1207
+ if (!errorDef) {
1208
+ errorDef = localErrorDef
1209
+ }
1203
1210
 
1204
- const key = `Commander.Command.${id}.state` as const
1205
- const stateTag = Context.GenericTag<typeof key, State>(key)
1206
-
1207
- const makeContext_ = () => makeContext(id, { ...options, state: state?.value })
1208
- const initialContext = makeContext_()
1209
- const action = computed(() => makeContext_().action)
1210
-
1211
- const errorReporter = <A, E, R>(self: Effect.Effect<A, E, R>) =>
1212
- self.pipe(
1213
- Effect.tapErrorCause(
1214
- Effect.fnUntraced(function*(cause) {
1215
- if (Cause.isInterruptedOnly(cause)) {
1216
- console.info(`Interrupted while trying to ${id}`)
1217
- return
1218
- }
1219
-
1220
- const fail = Cause.failureOption(cause)
1221
- if (Option.isSome(fail)) {
1222
- // if (fail.value._tag === "SuppressErrors") {
1223
- // console.info(
1224
- // `Suppressed error trying to ${action}`,
1225
- // fail.value,
1226
- // )
1227
- // return
1228
- // }
1229
- const message = `Failure trying to ${id}`
1230
- yield* reportMessage(message, {
1231
- action: id,
1232
- error: fail.value
1233
- })
1234
- return
1235
- }
1236
-
1237
- const context = yield* CommandContext
1238
- const extra = {
1239
- action: context.action,
1240
- message: `Unexpected Error trying to ${id}`
1241
- }
1242
- yield* reportRuntimeError(cause, extra)
1243
- }, Effect.uninterruptible)
1244
- )
1245
- )
1246
-
1247
- const currentState = Effect.sync(() => state.value)
1248
-
1249
- const theHandler = flow(
1250
- handler,
1251
- errorReporter,
1252
- // all must be within the Effect.fn to fit within the Span
1253
- Effect.provideServiceEffect(
1254
- stateTag,
1255
- currentState
1256
- ),
1257
- Effect.provideServiceEffect(
1258
- CommandContext,
1259
- Effect.sync(() => makeContext_())
1260
- )
1211
+ const key = `Commander.Command.${id}.state` as const
1212
+ const stateTag = Context.GenericTag<typeof key, State>(key)
1213
+
1214
+ const makeContext_ = () => this.makeContext(id, { ...options, state: state?.value })
1215
+ const initialContext = makeContext_()
1216
+ const action = computed(() => makeContext_().action)
1217
+
1218
+ const errorReporter = <A, E, R>(self: Effect.Effect<A, E, R>) =>
1219
+ self.pipe(
1220
+ Effect.tapErrorCause(
1221
+ Effect.fnUntraced(function*(cause) {
1222
+ if (Cause.isInterruptedOnly(cause)) {
1223
+ console.info(`Interrupted while trying to ${id}`)
1224
+ return
1225
+ }
1226
+
1227
+ const fail = Cause.failureOption(cause)
1228
+ if (Option.isSome(fail)) {
1229
+ // if (fail.value._tag === "SuppressErrors") {
1230
+ // console.info(
1231
+ // `Suppressed error trying to ${action}`,
1232
+ // fail.value,
1233
+ // )
1234
+ // return
1235
+ // }
1236
+ const message = `Failure trying to ${id}`
1237
+ yield* reportMessage(message, {
1238
+ action: id,
1239
+ error: fail.value
1240
+ })
1241
+ return
1242
+ }
1243
+
1244
+ const context = yield* CommandContext
1245
+ const extra = {
1246
+ action: context.action,
1247
+ message: `Unexpected Error trying to ${id}`
1248
+ }
1249
+ yield* reportRuntimeError(cause, extra)
1250
+ }, Effect.uninterruptible)
1261
1251
  )
1252
+ )
1262
1253
 
1263
- const [result, exec] = asResult(theHandler)
1254
+ const currentState = Effect.sync(() => state.value)
1255
+
1256
+ const theHandler = flow(
1257
+ handler,
1258
+ errorReporter,
1259
+ // all must be within the Effect.fn to fit within the Span
1260
+ Effect.provideServiceEffect(
1261
+ stateTag,
1262
+ currentState
1263
+ ),
1264
+ Effect.provideServiceEffect(
1265
+ CommandContext,
1266
+ Effect.sync(() => makeContext_())
1267
+ )
1268
+ )
1264
1269
 
1265
- const waiting = computed(() => result.value.waiting)
1270
+ const [result, exec] = asResult(theHandler)
1266
1271
 
1267
- const handle = Object.assign((...args: Args) => {
1268
- // we capture the call site stack here
1269
- const limit = Error.stackTraceLimit
1270
- Error.stackTraceLimit = 2
1271
- const errorCall = new Error()
1272
- Error.stackTraceLimit = limit
1272
+ const waiting = computed(() => result.value.waiting)
1273
1273
 
1274
- let cache: false | string = false
1275
- const captureStackTrace = () => {
1276
- // in case of an error, we want to append the definition stack to the call site stack,
1277
- // so we can see where the handler was defined too
1274
+ const handle = Object.assign((...args: Args) => {
1275
+ // we capture the call site stack here
1276
+ const limit = Error.stackTraceLimit
1277
+ Error.stackTraceLimit = 2
1278
+ const errorCall = new Error()
1279
+ Error.stackTraceLimit = limit
1278
1280
 
1279
- if (cache !== false) {
1280
- return cache
1281
- }
1282
- if (errorCall.stack) {
1283
- const stackDef = errorDef!.stack!.trim().split("\n")
1284
- const stackCall = errorCall.stack.trim().split("\n")
1285
- let endStackDef = stackDef.slice(2).join("\n").trim()
1286
- if (!endStackDef.includes(`(`)) {
1287
- endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1288
- }
1289
- let endStackCall = stackCall.slice(2).join("\n").trim()
1290
- if (!endStackCall.includes(`(`)) {
1291
- endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1292
- }
1293
- cache = `${endStackDef}\n${endStackCall}`
1294
- return cache
1295
- }
1281
+ let cache: false | string = false
1282
+ const captureStackTrace = () => {
1283
+ // in case of an error, we want to append the definition stack to the call site stack,
1284
+ // so we can see where the handler was defined too
1285
+
1286
+ if (cache !== false) {
1287
+ return cache
1288
+ }
1289
+ if (errorCall.stack) {
1290
+ const stackDef = errorDef!.stack!.trim().split("\n")
1291
+ const stackCall = errorCall.stack.trim().split("\n")
1292
+ let endStackDef = stackDef.slice(2).join("\n").trim()
1293
+ if (!endStackDef.includes(`(`)) {
1294
+ endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1296
1295
  }
1296
+ let endStackCall = stackCall.slice(2).join("\n").trim()
1297
+ if (!endStackCall.includes(`(`)) {
1298
+ endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1299
+ }
1300
+ cache = `${endStackDef}\n${endStackCall}`
1301
+ return cache
1302
+ }
1303
+ }
1297
1304
 
1298
- const command = currentState.pipe(Effect.flatMap((state) =>
1299
- Effect.withSpan(
1300
- exec(...args),
1301
- id,
1302
- {
1303
- captureStackTrace,
1304
- attributes: {
1305
- input: args,
1306
- state,
1307
- action: initialContext.action,
1308
- id: initialContext.id,
1309
- i18nKey: initialContext.i18nKey
1310
- }
1311
- }
1312
- )
1313
- ))
1314
-
1315
- return runFork(command)
1316
- }, { action })
1317
-
1318
- const handleEffect = Object.assign((...args: Args) => {
1319
- // we capture the call site stack here
1320
- const limit = Error.stackTraceLimit
1321
- Error.stackTraceLimit = 2
1322
- const errorCall = new Error()
1323
- Error.stackTraceLimit = limit
1324
-
1325
- let cache: false | string = false
1326
- const captureStackTrace = () => {
1327
- // in case of an error, we want to append the definition stack to the call site stack,
1328
- // so we can see where the handler was defined too
1329
-
1330
- if (cache !== false) {
1331
- return cache
1332
- }
1333
- if (errorCall.stack) {
1334
- const stackDef = errorDef!.stack!.trim().split("\n")
1335
- const stackCall = errorCall.stack.trim().split("\n")
1336
- let endStackDef = stackDef.slice(2).join("\n").trim()
1337
- if (!endStackDef.includes(`(`)) {
1338
- endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1339
- }
1340
- let endStackCall = stackCall.slice(2).join("\n").trim()
1341
- if (!endStackCall.includes(`(`)) {
1342
- endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1343
- }
1344
- cache = `${endStackDef}\n${endStackCall}`
1345
- return cache
1305
+ const command = currentState.pipe(Effect.flatMap((state) =>
1306
+ Effect.withSpan(
1307
+ exec(...args),
1308
+ id,
1309
+ {
1310
+ captureStackTrace,
1311
+ attributes: {
1312
+ input: args,
1313
+ state,
1314
+ action: initialContext.action,
1315
+ id: initialContext.id,
1316
+ i18nKey: initialContext.i18nKey
1346
1317
  }
1347
1318
  }
1319
+ )
1320
+ ))
1348
1321
 
1349
- const command = Effect.withSpan(
1350
- exec(...args),
1351
- id,
1352
- { captureStackTrace }
1353
- )
1354
-
1355
- return Effect.currentSpan.pipe(
1356
- Effect.option,
1357
- Effect.map((span) =>
1358
- runFork(Option.isSome(span) ? command.pipe(Effect.withParentSpan(span.value)) : command)
1359
- )
1360
- )
1361
- }, { action, state })
1362
-
1363
- const compose = Object.assign((...args: Args) => {
1364
- // we capture the call site stack here
1365
- const limit = Error.stackTraceLimit
1366
- Error.stackTraceLimit = 2
1367
- const errorCall = new Error()
1368
- Error.stackTraceLimit = limit
1369
-
1370
- let cache: false | string = false
1371
- const captureStackTrace = () => {
1372
- // in case of an error, we want to append the definition stack to the call site stack,
1373
- // so we can see where the handler was defined too
1374
-
1375
- if (cache !== false) {
1376
- return cache
1377
- }
1378
- if (errorCall.stack) {
1379
- const stackDef = errorDef!.stack!.trim().split("\n")
1380
- const stackCall = errorCall.stack.trim().split("\n")
1381
- let endStackDef = stackDef.slice(2).join("\n").trim()
1382
- if (!endStackDef.includes(`(`)) {
1383
- endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1384
- }
1385
- let endStackCall = stackCall.slice(2).join("\n").trim()
1386
- if (!endStackCall.includes(`(`)) {
1387
- endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1388
- }
1389
- cache = `${endStackDef}\n${endStackCall}`
1390
- return cache
1391
- }
1322
+ return this.runFork(command)
1323
+ }, { action })
1324
+
1325
+ const handleEffect = Object.assign((...args: Args) => {
1326
+ // we capture the call site stack here
1327
+ const limit = Error.stackTraceLimit
1328
+ Error.stackTraceLimit = 2
1329
+ const errorCall = new Error()
1330
+ Error.stackTraceLimit = limit
1331
+
1332
+ let cache: false | string = false
1333
+ const captureStackTrace = () => {
1334
+ // in case of an error, we want to append the definition stack to the call site stack,
1335
+ // so we can see where the handler was defined too
1336
+
1337
+ if (cache !== false) {
1338
+ return cache
1339
+ }
1340
+ if (errorCall.stack) {
1341
+ const stackDef = errorDef!.stack!.trim().split("\n")
1342
+ const stackCall = errorCall.stack.trim().split("\n")
1343
+ let endStackDef = stackDef.slice(2).join("\n").trim()
1344
+ if (!endStackDef.includes(`(`)) {
1345
+ endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1346
+ }
1347
+ let endStackCall = stackCall.slice(2).join("\n").trim()
1348
+ if (!endStackCall.includes(`(`)) {
1349
+ endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1392
1350
  }
1351
+ cache = `${endStackDef}\n${endStackCall}`
1352
+ return cache
1353
+ }
1354
+ }
1393
1355
 
1394
- const command = Effect.withSpan(
1395
- exec(...args),
1396
- id,
1397
- { captureStackTrace }
1398
- )
1399
-
1400
- return command
1401
- }, { action })
1402
-
1403
- const compose2 = Object.assign((...args: Args) => {
1404
- // we capture the call site stack here
1405
- const limit = Error.stackTraceLimit
1406
- Error.stackTraceLimit = 2
1407
- const errorCall = new Error()
1408
- Error.stackTraceLimit = limit
1409
-
1410
- let cache: false | string = false
1411
- const captureStackTrace = () => {
1412
- // in case of an error, we want to append the definition stack to the call site stack,
1413
- // so we can see where the handler was defined too
1414
-
1415
- if (cache !== false) {
1416
- return cache
1417
- }
1418
- if (errorCall.stack) {
1419
- const stackDef = errorDef!.stack!.trim().split("\n")
1420
- const stackCall = errorCall.stack.trim().split("\n")
1421
- let endStackDef = stackDef.slice(2).join("\n").trim()
1422
- if (!endStackDef.includes(`(`)) {
1423
- endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1424
- }
1425
- let endStackCall = stackCall.slice(2).join("\n").trim()
1426
- if (!endStackCall.includes(`(`)) {
1427
- endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1428
- }
1429
- cache = `${endStackDef}\n${endStackCall}`
1430
- return cache
1431
- }
1356
+ const command = Effect.withSpan(
1357
+ exec(...args),
1358
+ id,
1359
+ { captureStackTrace }
1360
+ )
1361
+
1362
+ return Effect.currentSpan.pipe(
1363
+ Effect.option,
1364
+ Effect.map((span) =>
1365
+ this.runFork(Option.isSome(span) ? command.pipe(Effect.withParentSpan(span.value)) : command)
1366
+ )
1367
+ )
1368
+ }, { action, state })
1369
+
1370
+ const compose = Object.assign((...args: Args) => {
1371
+ // we capture the call site stack here
1372
+ const limit = Error.stackTraceLimit
1373
+ Error.stackTraceLimit = 2
1374
+ const errorCall = new Error()
1375
+ Error.stackTraceLimit = limit
1376
+
1377
+ let cache: false | string = false
1378
+ const captureStackTrace = () => {
1379
+ // in case of an error, we want to append the definition stack to the call site stack,
1380
+ // so we can see where the handler was defined too
1381
+
1382
+ if (cache !== false) {
1383
+ return cache
1384
+ }
1385
+ if (errorCall.stack) {
1386
+ const stackDef = errorDef!.stack!.trim().split("\n")
1387
+ const stackCall = errorCall.stack.trim().split("\n")
1388
+ let endStackDef = stackDef.slice(2).join("\n").trim()
1389
+ if (!endStackDef.includes(`(`)) {
1390
+ endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1432
1391
  }
1392
+ let endStackCall = stackCall.slice(2).join("\n").trim()
1393
+ if (!endStackCall.includes(`(`)) {
1394
+ endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1395
+ }
1396
+ cache = `${endStackDef}\n${endStackCall}`
1397
+ return cache
1398
+ }
1399
+ }
1433
1400
 
1434
- const command = Effect.withSpan(
1435
- exec(...args).pipe(Effect.flatten),
1436
- id,
1437
- { captureStackTrace }
1438
- )
1401
+ const command = Effect.withSpan(
1402
+ exec(...args),
1403
+ id,
1404
+ { captureStackTrace }
1405
+ )
1439
1406
 
1440
- return command
1441
- }, { action })
1407
+ return command
1408
+ }, { action })
1442
1409
 
1443
- return reactive({
1444
- /** static */
1445
- id,
1410
+ const compose2 = Object.assign((...args: Args) => {
1411
+ // we capture the call site stack here
1412
+ const limit = Error.stackTraceLimit
1413
+ Error.stackTraceLimit = 2
1414
+ const errorCall = new Error()
1415
+ Error.stackTraceLimit = limit
1446
1416
 
1447
- /** the base i18n key, based on id by default. static */
1448
- i18nKey: initialContext.i18nKey,
1449
- /** the `action.` namespace based on i18nKey.. static */
1450
- namespace: initialContext.namespace,
1451
-
1452
- /** easy generate namespaced 18n keys, based on namespace. static */
1453
- namespaced: initialContext.namespaced,
1454
-
1455
- /** reactive */
1456
- result,
1457
- /** reactive */
1458
- waiting,
1459
- /** reactive */
1460
- action,
1461
-
1462
- handle,
1463
-
1464
- /** experimental */
1465
- handleEffect,
1466
- /** experimental */
1467
- compose,
1468
- /** experimental */
1469
- compose2,
1470
- /** experimental */
1471
- exec
1472
- })
1473
- },
1474
- { id }
1475
- )
1476
- }
1477
- }
1417
+ let cache: false | string = false
1418
+ const captureStackTrace = () => {
1419
+ // in case of an error, we want to append the definition stack to the call site stack,
1420
+ // so we can see where the handler was defined too
1478
1421
 
1479
- return {
1480
- // /** @experimental */
1481
- // takeOver:
1482
- // <Args extends any[], A, E, R, const Id extends string>(command: Commander.CommandOut<Args, A, E, R, Id,I18nKey>) =>
1483
- // (...args: Args) => {
1484
- // // we capture the call site stack here
1485
- // const limit = Error.stackTraceLimit
1486
- // Error.stackTraceLimit = 2
1487
- // const errorCall = new Error()
1488
- // const localErrorDef = new Error()
1489
- // Error.stackTraceLimit = limit
1490
-
1491
- // // TODO
1492
- // const errorDef = localErrorDef
1493
-
1494
- // let cache: false | string = false
1495
- // const captureStackTrace = () => {
1496
- // // in case of an error, we want to append the definition stack to the call site stack,
1497
- // // so we can see where the handler was defined too
1498
-
1499
- // if (cache !== false) {
1500
- // return cache
1501
- // }
1502
- // if (errorCall.stack) {
1503
- // const stackDef = errorDef.stack!.trim().split("\n")
1504
- // const stackCall = errorCall.stack.trim().split("\n")
1505
- // let endStackDef = stackDef.slice(2).join("\n").trim()
1506
- // if (!endStackDef.includes(`(`)) {
1507
- // endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1508
- // }
1509
- // let endStackCall = stackCall.slice(2).join("\n").trim()
1510
- // if (!endStackCall.includes(`(`)) {
1511
- // endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1512
- // }
1513
- // cache = `${endStackDef}\n${endStackCall}`
1514
- // return cache
1515
- // }
1516
- // }
1517
-
1518
- // return Effect.gen(function*() {
1519
- // const ctx = yield* CommandContext
1520
- // ctx.action = command.action
1521
- // return yield* command.exec(...args).pipe(
1522
- // Effect.flatten,
1523
- // Effect.withSpan(
1524
- // command.action,
1525
- // { captureStackTrace }
1526
- // )
1527
- // )
1528
- // })
1529
- // },
1530
-
1531
- fn: <RT>(runtime: Runtime.Runtime<RT>) => {
1532
- const make = makeCommand(runtime)
1533
- /**
1534
- * Define a Command for handling user actions with built-in error reporting and state management.
1535
- *
1536
- * @param id The internal identifier for the action. Used as a tracing span and to lookup
1537
- * the user-facing name via internationalization (`action.${id}`).
1538
- * @returns A function that executes the command when called (e.g., directly in `@click` handlers).
1539
- * Built-in error reporting handles failures automatically.
1540
- *
1541
- * **Effect Context**: Effects have access to the `CommandContext` service, which provides
1542
- * the user-facing action name.
1543
- *
1544
- * **Returned Properties**:
1545
- * - `action`: User-facing action name from intl messages (useful for button labels)
1546
- * - `result`: The command result state
1547
- * - `waiting`: Boolean indicating if the command is in progress (shorthand for `result.waiting`)
1548
- * - `handle`: Function to execute the command
1549
- *
1550
- * **User Feedback**: Use the `withDefaultToast` helper for status notifications, or render
1551
- * the `result` inline for custom UI feedback.
1552
- */
1553
- const f = <
1554
- const Id extends string,
1555
- const State extends IntlRecord = IntlRecord,
1556
- const I18nKey extends string = Id
1557
- >(
1558
- id: Id | { id: Id },
1559
- options?: FnOptions<I18nKey, State>
1560
- ): Commander.Gen<RT, Id, I18nKey> & Commander.NonGen<RT, Id, I18nKey> & {
1561
- state: Context.Tag<`Commander.Command.${Id}.state`, State>
1562
- } =>
1563
- Object.assign(
1564
- (
1565
- fn: any,
1566
- ...combinators: any[]
1567
- ): any => {
1568
- // we capture the definition stack here, so we can append it to later stack traces
1569
- const limit = Error.stackTraceLimit
1570
- Error.stackTraceLimit = 2
1571
- const errorDef = new Error()
1572
- Error.stackTraceLimit = limit
1573
-
1574
- return make(id, options, errorDef)(
1575
- Effect.fnUntraced(
1576
- // fnUntraced only supports generators as first arg, so we convert to generator if needed
1577
- isGeneratorFunction(fn) ? fn : function*(...args) {
1578
- return yield* fn(...args)
1579
- },
1580
- ...combinators as [any]
1581
- ) as any
1582
- )
1583
- },
1584
- makeBaseInfo(typeof id === "string" ? id : id.id, options),
1585
- {
1586
- state: Context.GenericTag<`Commander.Command.${Id}.state`, State>(
1587
- `Commander.Command.${typeof id === "string" ? id : id.id}.state`
1588
- )
1422
+ if (cache !== false) {
1423
+ return cache
1589
1424
  }
1425
+ if (errorCall.stack) {
1426
+ const stackDef = errorDef!.stack!.trim().split("\n")
1427
+ const stackCall = errorCall.stack.trim().split("\n")
1428
+ let endStackDef = stackDef.slice(2).join("\n").trim()
1429
+ if (!endStackDef.includes(`(`)) {
1430
+ endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1431
+ }
1432
+ let endStackCall = stackCall.slice(2).join("\n").trim()
1433
+ if (!endStackCall.includes(`(`)) {
1434
+ endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1435
+ }
1436
+ cache = `${endStackDef}\n${endStackCall}`
1437
+ return cache
1438
+ }
1439
+ }
1440
+
1441
+ const command = Effect.withSpan(
1442
+ exec(...args).pipe(Effect.flatten),
1443
+ id,
1444
+ { captureStackTrace }
1590
1445
  )
1591
- return f
1446
+
1447
+ return command
1448
+ }, { action })
1449
+
1450
+ return reactive({
1451
+ /** static */
1452
+ id,
1453
+
1454
+ /** the base i18n key, based on id by default. static */
1455
+ i18nKey: initialContext.i18nKey,
1456
+ /** the `action.` namespace based on i18nKey.. static */
1457
+ namespace: initialContext.namespace,
1458
+
1459
+ /** easy generate namespaced 18n keys, based on namespace. static */
1460
+ namespaced: initialContext.namespaced,
1461
+
1462
+ /** reactive */
1463
+ result,
1464
+ /** reactive */
1465
+ waiting,
1466
+ /** reactive */
1467
+ action,
1468
+
1469
+ handle,
1470
+
1471
+ /** experimental */
1472
+ handleEffect,
1473
+ /** experimental */
1474
+ compose,
1475
+ /** experimental */
1476
+ compose2,
1477
+ /** experimental */
1478
+ exec
1479
+ })
1592
1480
  },
1481
+ { id }
1482
+ )
1483
+ }
1593
1484
 
1594
- /** @experimental */
1595
- alt2: <RT>(rt: Runtime.Runtime<RT>) => {
1596
- const cmd = makeCommand(rt)
1597
- /** @experimental */
1598
- const f: <
1599
- const Id extends string,
1600
- MutArgs extends Array<unknown>,
1601
- MutA,
1602
- MutE,
1603
- MutR,
1604
- const I18nKey extends string = Id
1605
- >(
1606
- id:
1607
- | Id
1608
- | { id: Id; mutate: (...args: MutArgs) => Effect.Effect<MutA, MutE, MutR> }
1609
- | ((...args: MutArgs) => Effect.Effect<MutA, MutE, MutR>) & { id: Id },
1610
- options?: FnOptions<I18nKey, IntlRecord>
1611
- ) =>
1612
- & Commander.CommandContextLocal<Id, I18nKey>
1613
- & (<Args extends Array<unknown>, A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`>(
1614
- handler: (
1615
- ctx: Effect.fn.Gen & Effect.fn.NonGen & Commander.CommandContextLocal<Id, I18nKey> & {
1616
- // todo: only if we passed in one
1617
- mutate: (...args: MutArgs) => Effect.Effect<MutA, MutE, MutR>
1618
- }
1619
- ) => (...args: Args) => Effect.Effect<A, E, R>
1620
- ) => Commander.CommandOut<Args, A, E, R, Id, I18nKey>) = (
1621
- _id,
1622
- options?
1623
- ) => {
1624
- const isObject = typeof _id === "object" || typeof _id === "function"
1625
- const id = isObject ? _id.id : _id
1626
- const baseInfo = makeBaseInfo(id, options)
1627
- const idCmd = cmd(id, options)
1628
- // TODO: implement proper tracing stack
1629
- return Object.assign((cb: any) =>
1630
- idCmd(cb(
1631
- Object.assign(
1632
- (fn: any, ...combinators: any[]) =>
1633
- Effect.fnUntraced(
1634
- // fnUntraced only supports generators as first arg, so we convert to generator if needed
1635
- isGeneratorFunction(fn) ? fn : function*(...args) {
1636
- return yield* fn(...args)
1637
- },
1638
- ...combinators as [any]
1639
- ),
1640
- baseInfo,
1641
- isObject
1642
- ? { mutate: "mutate" in _id ? _id.mutate : typeof _id === "function" ? _id : undefined }
1643
- : {}
1644
- )
1645
- )), baseInfo) as any
1646
- }
1647
- return f
1485
+ // /** @experimental */
1486
+ // takeOver:
1487
+ // <Args extends any[], A, E, R, const Id extends string>(command: Commander.CommandOut<Args, A, E, R, Id,I18nKey>) =>
1488
+ // (...args: Args) => {
1489
+ // // we capture the call site stack here
1490
+ // const limit = Error.stackTraceLimit
1491
+ // Error.stackTraceLimit = 2
1492
+ // const errorCall = new Error()
1493
+ // const localErrorDef = new Error()
1494
+ // Error.stackTraceLimit = limit
1495
+
1496
+ // // TODO
1497
+ // const errorDef = localErrorDef
1498
+
1499
+ // let cache: false | string = false
1500
+ // const captureStackTrace = () => {
1501
+ // // in case of an error, we want to append the definition stack to the call site stack,
1502
+ // // so we can see where the handler was defined too
1503
+
1504
+ // if (cache !== false) {
1505
+ // return cache
1506
+ // }
1507
+ // if (errorCall.stack) {
1508
+ // const stackDef = errorDef.stack!.trim().split("\n")
1509
+ // const stackCall = errorCall.stack.trim().split("\n")
1510
+ // let endStackDef = stackDef.slice(2).join("\n").trim()
1511
+ // if (!endStackDef.includes(`(`)) {
1512
+ // endStackDef = endStackDef.replace(/at (.*)/, "at ($1)")
1513
+ // }
1514
+ // let endStackCall = stackCall.slice(2).join("\n").trim()
1515
+ // if (!endStackCall.includes(`(`)) {
1516
+ // endStackCall = endStackCall.replace(/at (.*)/, "at ($1)")
1517
+ // }
1518
+ // cache = `${endStackDef}\n${endStackCall}`
1519
+ // return cache
1520
+ // }
1521
+ // }
1522
+
1523
+ // return Effect.gen(function*() {
1524
+ // const ctx = yield* CommandContext
1525
+ // ctx.action = command.action
1526
+ // return yield* command.exec(...args).pipe(
1527
+ // Effect.flatten,
1528
+ // Effect.withSpan(
1529
+ // command.action,
1530
+ // { captureStackTrace }
1531
+ // )
1532
+ // )
1533
+ // })
1534
+ // },
1535
+
1536
+ /**
1537
+ * Define a Command for handling user actions with built-in error reporting and state management.
1538
+ *
1539
+ * @param id The internal identifier for the action. Used as a tracing span and to lookup
1540
+ * the user-facing name via internationalization (`action.${id}`).
1541
+ * @returns A function that executes the command when called (e.g., directly in `@click` handlers).
1542
+ * Built-in error reporting handles failures automatically.
1543
+ *
1544
+ * **Effect Context**: Effects have access to the `CommandContext` service, which provides
1545
+ * the user-facing action name.
1546
+ *
1547
+ * **Returned Properties**:
1548
+ * - `action`: User-facing action name from intl messages (useful for button labels)
1549
+ * - `result`: The command result state
1550
+ * - `waiting`: Boolean indicating if the command is in progress (shorthand for `result.waiting`)
1551
+ * - `handle`: Function to execute the command
1552
+ *
1553
+ * **User Feedback**: Use the `withDefaultToast` helper for status notifications, or render
1554
+ * the `result` inline for custom UI feedback.
1555
+ */
1556
+ fn = <
1557
+ const Id extends string,
1558
+ const State extends IntlRecord = IntlRecord,
1559
+ const I18nKey extends string = Id
1560
+ >(
1561
+ id: Id | { id: Id },
1562
+ options?: FnOptions<I18nKey, State>
1563
+ ): Commander.Gen<RT, Id, I18nKey> & Commander.NonGen<RT, Id, I18nKey> & {
1564
+ state: Context.Tag<`Commander.Command.${Id}.state`, State>
1565
+ } =>
1566
+ Object.assign(
1567
+ (
1568
+ fn: any,
1569
+ ...combinators: any[]
1570
+ ): any => {
1571
+ // we capture the definition stack here, so we can append it to later stack traces
1572
+ const limit = Error.stackTraceLimit
1573
+ Error.stackTraceLimit = 2
1574
+ const errorDef = new Error()
1575
+ Error.stackTraceLimit = limit
1576
+
1577
+ return this.makeCommand(id, options, errorDef)(
1578
+ Effect.fnUntraced(
1579
+ // fnUntraced only supports generators as first arg, so we convert to generator if needed
1580
+ isGeneratorFunction(fn) ? fn : function*(...args) {
1581
+ return yield* fn(...args)
1582
+ },
1583
+ ...combinators as [any]
1584
+ ) as any
1585
+ )
1648
1586
  },
1587
+ makeBaseInfo(typeof id === "string" ? id : id.id, options),
1588
+ {
1589
+ state: Context.GenericTag<`Commander.Command.${Id}.state`, State>(
1590
+ `Commander.Command.${typeof id === "string" ? id : id.id}.state`
1591
+ )
1592
+ }
1593
+ )
1649
1594
 
1650
- /** @experimental */
1651
- alt: makeCommand as unknown as <RT>(
1652
- runtime: Runtime.Runtime<RT>
1653
- ) => /** @experimental */ <const Id extends string, const I18nKey extends string = Id>(
1654
- id: Id,
1655
- customI18nKey?: I18nKey
1656
- ) =>
1657
- & Commander.CommandContextLocal<Id, I18nKey>
1658
- & (<Args extends Array<unknown>, A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`>(
1659
- handler: (...args: Args) => Effect.Effect<A, E, R>
1660
- ) => Commander.CommandOut<Args, A, E, R, Id, I18nKey>),
1661
-
1662
- /** @experimental */
1663
- wrap: <RT>(runtime: Runtime.Runtime<RT>) => {
1664
- const make = makeCommand(runtime)
1665
-
1666
- /** @experimental */
1667
- const f = <
1668
- const Id extends string,
1669
- Args extends Array<unknown>,
1670
- A,
1671
- E,
1672
- R,
1673
- const State extends IntlRecord = IntlRecord,
1674
- I18nKey extends string = Id
1675
- >(
1676
- mutation:
1677
- | { mutate: (...args: Args) => Effect.Effect<A, E, R>; id: Id }
1678
- | ((...args: Args) => Effect.Effect<A, E, R>) & { id: Id },
1679
- options?: FnOptions<I18nKey, State>
1680
- ):
1681
- & Commander.CommandContextLocal<Id, I18nKey>
1682
- & Commander.GenWrap<RT, Id, I18nKey, Args, A, E, R>
1683
- & Commander.NonGenWrap<RT, Id, I18nKey, Args, A, E, R> =>
1684
- Object.assign((
1685
- ...combinators: any[]
1686
- ): any => {
1687
- // we capture the definition stack here, so we can append it to later stack traces
1688
- const limit = Error.stackTraceLimit
1689
- Error.stackTraceLimit = 2
1690
- const errorDef = new Error()
1691
- Error.stackTraceLimit = limit
1692
-
1693
- const mutate = "mutate" in mutation ? mutation.mutate : mutation
1694
-
1695
- return make(mutation.id, options, errorDef)(
1595
+ /** @experimental */
1596
+ alt2: <
1597
+ const Id extends string,
1598
+ MutArgs extends Array<unknown>,
1599
+ MutA,
1600
+ MutE,
1601
+ MutR,
1602
+ const I18nKey extends string = Id
1603
+ >(
1604
+ id:
1605
+ | Id
1606
+ | { id: Id; mutate: (...args: MutArgs) => Effect.Effect<MutA, MutE, MutR> }
1607
+ | ((...args: MutArgs) => Effect.Effect<MutA, MutE, MutR>) & { id: Id },
1608
+ options?: FnOptions<I18nKey, IntlRecord>
1609
+ ) =>
1610
+ & Commander.CommandContextLocal<Id, I18nKey>
1611
+ & (<Args extends Array<unknown>, A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`>(
1612
+ handler: (
1613
+ ctx: Effect.fn.Gen & Effect.fn.NonGen & Commander.CommandContextLocal<Id, I18nKey> & {
1614
+ // todo: only if we passed in one
1615
+ mutate: (...args: MutArgs) => Effect.Effect<MutA, MutE, MutR>
1616
+ }
1617
+ ) => (...args: Args) => Effect.Effect<A, E, R>
1618
+ ) => Commander.CommandOut<Args, A, E, R, Id, I18nKey>) = (
1619
+ _id,
1620
+ options?
1621
+ ) => {
1622
+ const isObject = typeof _id === "object" || typeof _id === "function"
1623
+ const id = isObject ? _id.id : _id
1624
+ const baseInfo = makeBaseInfo(id, options)
1625
+ const idCmd = this.makeCommand(id, options)
1626
+ // TODO: implement proper tracing stack
1627
+ return Object.assign((cb: any) =>
1628
+ idCmd(cb(
1629
+ Object.assign(
1630
+ (fn: any, ...combinators: any[]) =>
1696
1631
  Effect.fnUntraced(
1697
1632
  // fnUntraced only supports generators as first arg, so we convert to generator if needed
1698
- isGeneratorFunction(mutate) ? mutate : function*(...args: Args) {
1699
- return yield* mutate(...args)
1633
+ isGeneratorFunction(fn) ? fn : function*(...args) {
1634
+ return yield* fn(...args)
1700
1635
  },
1701
1636
  ...combinators as [any]
1702
- ) as any
1703
- )
1704
- }, makeBaseInfo(mutation.id, options))
1705
- return f
1706
- }
1637
+ ),
1638
+ baseInfo,
1639
+ isObject
1640
+ ? { mutate: "mutate" in _id ? _id.mutate : typeof _id === "function" ? _id : undefined }
1641
+ : {}
1642
+ )
1643
+ )), baseInfo) as any
1707
1644
  }
1645
+
1646
+ /** @experimental */
1647
+ alt = this.makeCommand as unknown as <const Id extends string, const I18nKey extends string = Id>(
1648
+ id: Id,
1649
+ customI18nKey?: I18nKey
1650
+ ) =>
1651
+ & Commander.CommandContextLocal<Id, I18nKey>
1652
+ & (<Args extends Array<unknown>, A, E, R extends RT | CommandContext | `Commander.Command.${Id}.state`>(
1653
+ handler: (...args: Args) => Effect.Effect<A, E, R>
1654
+ ) => Commander.CommandOut<Args, A, E, R, Id, I18nKey>)
1655
+
1656
+ /** @experimental */
1657
+ wrap = <
1658
+ const Id extends string,
1659
+ Args extends Array<unknown>,
1660
+ A,
1661
+ E,
1662
+ R,
1663
+ const State extends IntlRecord = IntlRecord,
1664
+ I18nKey extends string = Id
1665
+ >(
1666
+ mutation:
1667
+ | { mutate: (...args: Args) => Effect.Effect<A, E, R>; id: Id }
1668
+ | ((...args: Args) => Effect.Effect<A, E, R>) & { id: Id },
1669
+ options?: FnOptions<I18nKey, State>
1670
+ ):
1671
+ & Commander.CommandContextLocal<Id, I18nKey>
1672
+ & Commander.GenWrap<RT, Id, I18nKey, Args, A, E, R>
1673
+ & Commander.NonGenWrap<RT, Id, I18nKey, Args, A, E, R> =>
1674
+ Object.assign((
1675
+ ...combinators: any[]
1676
+ ): any => {
1677
+ // we capture the definition stack here, so we can append it to later stack traces
1678
+ const limit = Error.stackTraceLimit
1679
+ Error.stackTraceLimit = 2
1680
+ const errorDef = new Error()
1681
+ Error.stackTraceLimit = limit
1682
+
1683
+ const mutate = "mutate" in mutation ? mutation.mutate : mutation
1684
+
1685
+ return this.makeCommand(mutation.id, options, errorDef)(
1686
+ Effect.fnUntraced(
1687
+ // fnUntraced only supports generators as first arg, so we convert to generator if needed
1688
+ isGeneratorFunction(mutate) ? mutate : function*(...args: Args) {
1689
+ return yield* mutate(...args)
1690
+ },
1691
+ ...combinators as [any]
1692
+ ) as any
1693
+ )
1694
+ }, makeBaseInfo(mutation.id, options))
1695
+ }
1696
+
1697
+ // @effect-diagnostics-next-line missingEffectServiceDependency:off
1698
+ export class Commander extends Effect.Service<Commander>()("Commander", {
1699
+ dependencies: [WithToast.Default, Confirm.Default],
1700
+ effect: Effect.gen(function*() {
1701
+ const i18n = yield* I18n
1702
+ return <RT>(rt: Runtime.Runtime<RT>) => new CommanderImpl(rt, i18n)
1708
1703
  })
1709
1704
  }) {}