@effect-app/infra 2.0.1 → 2.1.0

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.
Files changed (124) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/_cjs/api/internal/RequestContextMiddleware.cjs +2 -3
  3. package/_cjs/api/internal/RequestContextMiddleware.cjs.map +1 -1
  4. package/_cjs/api/internal/events.cjs +2 -2
  5. package/_cjs/api/internal/events.cjs.map +1 -1
  6. package/_cjs/api/setupRequest.cjs +1 -1
  7. package/_cjs/api/setupRequest.cjs.map +1 -1
  8. package/_cjs/fileUtil.cjs +48 -0
  9. package/_cjs/fileUtil.cjs.map +1 -0
  10. package/_cjs/logger/shared.cjs +2 -2
  11. package/_cjs/logger/shared.cjs.map +1 -1
  12. package/_cjs/services/CUPS.cjs +118 -0
  13. package/_cjs/services/CUPS.cjs.map +1 -0
  14. package/_cjs/services/QueueMaker/SQLQueue.cjs +1 -1
  15. package/_cjs/services/QueueMaker/SQLQueue.cjs.map +1 -1
  16. package/_cjs/services/QueueMaker/memQueue.cjs +1 -1
  17. package/_cjs/services/QueueMaker/memQueue.cjs.map +1 -1
  18. package/_cjs/services/QueueMaker/sbqueue.cjs +1 -1
  19. package/_cjs/services/QueueMaker/sbqueue.cjs.map +1 -1
  20. package/_cjs/services/Store/Cosmos.cjs +1 -1
  21. package/_cjs/services/Store/Cosmos.cjs.map +1 -1
  22. package/_cjs/services/Store/Disk.cjs +1 -1
  23. package/_cjs/services/adapters/SQL/Model.cjs +500 -0
  24. package/_cjs/services/adapters/SQL/Model.cjs.map +1 -0
  25. package/_cjs/services/adapters/SQL.cjs +11 -0
  26. package/_cjs/services/adapters/SQL.cjs.map +1 -0
  27. package/_cjs/services/adapters/ServiceBus.cjs +76 -0
  28. package/_cjs/services/adapters/ServiceBus.cjs.map +1 -0
  29. package/_cjs/services/adapters/cosmos-client.cjs +18 -0
  30. package/_cjs/services/adapters/cosmos-client.cjs.map +1 -0
  31. package/_cjs/services/adapters/index.cjs +6 -0
  32. package/_cjs/services/adapters/index.cjs.map +1 -0
  33. package/_cjs/services/adapters/logger.cjs +9 -0
  34. package/_cjs/services/adapters/logger.cjs.map +1 -0
  35. package/_cjs/services/adapters/memQueue.cjs +31 -0
  36. package/_cjs/services/adapters/memQueue.cjs.map +1 -0
  37. package/_cjs/services/adapters/mongo-client.cjs +20 -0
  38. package/_cjs/services/adapters/mongo-client.cjs.map +1 -0
  39. package/_cjs/services/adapters/redis-client.cjs +83 -0
  40. package/_cjs/services/adapters/redis-client.cjs.map +1 -0
  41. package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
  42. package/dist/api/internal/RequestContextMiddleware.js +3 -4
  43. package/dist/api/internal/events.d.ts.map +1 -1
  44. package/dist/api/internal/events.js +3 -3
  45. package/dist/api/setupRequest.d.ts +1 -2
  46. package/dist/api/setupRequest.d.ts.map +1 -1
  47. package/dist/api/setupRequest.js +3 -3
  48. package/dist/fileUtil.d.ts +23 -0
  49. package/dist/fileUtil.d.ts.map +1 -0
  50. package/dist/fileUtil.js +41 -0
  51. package/dist/logger/shared.d.ts.map +1 -1
  52. package/dist/logger/shared.js +2 -2
  53. package/dist/services/CUPS.d.ts +26 -0
  54. package/dist/services/CUPS.d.ts.map +1 -0
  55. package/dist/services/CUPS.js +111 -0
  56. package/dist/services/QueueMaker/SQLQueue.d.ts.map +1 -1
  57. package/dist/services/QueueMaker/SQLQueue.js +2 -2
  58. package/dist/services/QueueMaker/memQueue.d.ts +1 -1
  59. package/dist/services/QueueMaker/memQueue.d.ts.map +1 -1
  60. package/dist/services/QueueMaker/memQueue.js +2 -2
  61. package/dist/services/QueueMaker/sbqueue.d.ts +3 -3
  62. package/dist/services/QueueMaker/sbqueue.d.ts.map +1 -1
  63. package/dist/services/QueueMaker/sbqueue.js +2 -2
  64. package/dist/services/Store/Cosmos.d.ts.map +1 -1
  65. package/dist/services/Store/Cosmos.js +2 -2
  66. package/dist/services/Store/Disk.js +2 -2
  67. package/dist/services/adapters/SQL/Model.d.ts +538 -0
  68. package/dist/services/adapters/SQL/Model.d.ts.map +1 -0
  69. package/dist/services/adapters/SQL/Model.js +508 -0
  70. package/dist/services/adapters/SQL.d.ts +2 -0
  71. package/dist/services/adapters/SQL.d.ts.map +1 -0
  72. package/dist/services/adapters/SQL.js +2 -0
  73. package/dist/services/adapters/ServiceBus.d.ts +50 -0
  74. package/dist/services/adapters/ServiceBus.d.ts.map +1 -0
  75. package/dist/services/adapters/ServiceBus.js +73 -0
  76. package/dist/services/adapters/cosmos-client.d.ts +10 -0
  77. package/dist/services/adapters/cosmos-client.d.ts.map +1 -0
  78. package/dist/services/adapters/cosmos-client.js +8 -0
  79. package/dist/services/adapters/index.d.ts +2 -0
  80. package/dist/services/adapters/index.d.ts.map +1 -0
  81. package/dist/services/adapters/index.js +2 -0
  82. package/dist/services/adapters/logger.d.ts +8 -0
  83. package/dist/services/adapters/logger.d.ts.map +1 -0
  84. package/dist/services/adapters/logger.js +3 -0
  85. package/dist/services/adapters/memQueue.d.ts +34 -0
  86. package/dist/services/adapters/memQueue.d.ts.map +1 -0
  87. package/dist/services/adapters/memQueue.js +24 -0
  88. package/dist/services/adapters/mongo-client.d.ts +10 -0
  89. package/dist/services/adapters/mongo-client.d.ts.map +1 -0
  90. package/dist/services/adapters/mongo-client.js +12 -0
  91. package/dist/services/adapters/redis-client.d.ts +29 -0
  92. package/dist/services/adapters/redis-client.d.ts.map +1 -0
  93. package/dist/services/adapters/redis-client.js +93 -0
  94. package/package.json +128 -12
  95. package/src/api/internal/RequestContextMiddleware.ts +2 -3
  96. package/src/api/internal/events.ts +2 -2
  97. package/src/api/setupRequest.ts +2 -3
  98. package/src/fileUtil.ts +85 -0
  99. package/src/logger/shared.ts +2 -3
  100. package/src/services/CUPS.ts +151 -0
  101. package/src/services/QueueMaker/SQLQueue.ts +1 -1
  102. package/src/services/QueueMaker/memQueue.ts +1 -1
  103. package/src/services/QueueMaker/sbqueue.ts +7 -7
  104. package/src/services/Store/Cosmos.ts +1 -1
  105. package/src/services/Store/Disk.ts +1 -1
  106. package/src/services/adapters/SQL/Model.ts +939 -0
  107. package/src/services/adapters/SQL.ts +1 -0
  108. package/src/services/adapters/ServiceBus.ts +140 -0
  109. package/src/services/adapters/cosmos-client.ts +16 -0
  110. package/src/services/adapters/index.ts +0 -0
  111. package/src/services/adapters/logger.ts +3 -0
  112. package/src/services/adapters/memQueue.ts +26 -0
  113. package/src/services/adapters/mongo-client.ts +23 -0
  114. package/src/services/adapters/redis-client.ts +123 -0
  115. package/tsconfig.src.json +0 -3
  116. package/src/services/Store/Redis.ts.bak +0 -88
  117. package/src/services/simpledb/cosmosdb.ts.bak +0 -149
  118. package/src/services/simpledb/diskdb.ts.bak +0 -165
  119. package/src/services/simpledb/index.ts.bak +0 -6
  120. package/src/services/simpledb/memdb.ts.bak +0 -78
  121. package/src/services/simpledb/mongodb.ts.bak +0 -107
  122. package/src/services/simpledb/redisdb.ts.bak +0 -202
  123. package/src/services/simpledb/shared.ts.bak +0 -117
  124. package/src/services/simpledb/simpledb.ts.bak +0 -121
@@ -0,0 +1,85 @@
1
+ import crypto from "crypto"
2
+ import { Effect } from "effect-app"
3
+ import type { Abortable } from "events"
4
+ import type { Mode, ObjectEncodingOptions, OpenMode } from "fs"
5
+ import fs from "fs/promises"
6
+ import os from "os"
7
+ import path from "path"
8
+ import type internal from "stream"
9
+
10
+ export function readFile(fileName: string) {
11
+ return Effect.tryPromise(() => fs.readFile(fileName))
12
+ }
13
+
14
+ export function createReadableStream(fileName: string) {
15
+ return Effect.map(openFile(fileName), (file) => file.createReadStream())
16
+ }
17
+
18
+ export function openFile(fileName: string) {
19
+ return Effect.acquireRelease(Effect.tryPromise(() => fs.open(fileName)), (f) => Effect.promise(() => f.close()))
20
+ }
21
+
22
+ export function tempFile(
23
+ folder: string
24
+ ) {
25
+ return (prefix: string) => (data: Data, options?: FileOptions) => tempFile_(folder, prefix, data, options)
26
+ }
27
+
28
+ type Data =
29
+ | string
30
+ | NodeJS.ArrayBufferView
31
+ | Iterable<string | NodeJS.ArrayBufferView>
32
+ | AsyncIterable<string | NodeJS.ArrayBufferView>
33
+ | internal.Stream
34
+
35
+ export type FileOptions =
36
+ | (ObjectEncodingOptions & {
37
+ mode?: Mode | undefined
38
+ flag?: OpenMode | undefined
39
+ } & Abortable)
40
+ | BufferEncoding
41
+ | null
42
+ export function tempFile_(
43
+ folder: string,
44
+ prefix: string,
45
+ data: Data,
46
+ options?: FileOptions
47
+ ) {
48
+ return Effect.flatMap(
49
+ Effect
50
+ .sync(() => path.join(os.tmpdir(), folder, `${prefix}-` + crypto.randomUUID())),
51
+ (fp) =>
52
+ Effect.acquireRelease(
53
+ Effect
54
+ .map(
55
+ Effect
56
+ .tryPromise(() => fs.writeFile(fp, data, options)),
57
+ (_) => fp
58
+ ),
59
+ (p) => Effect.promise(() => fs.unlink(p))
60
+ )
61
+ )
62
+ }
63
+
64
+ /**
65
+ * Safe write file to .tmp and then rename
66
+ */
67
+ export function writeTextFile(fileName: string, content: string) {
68
+ const tmp = fileName + ".tmp"
69
+ return Effect
70
+ .andThen(
71
+ Effect
72
+ .tryPromise(() => fs.writeFile(tmp, content, "utf-8")),
73
+ Effect.tryPromise(() => fs.rename(tmp, fileName))
74
+ )
75
+ .pipe(Effect.orDie)
76
+ }
77
+
78
+ export function fileExists(fileName: string) {
79
+ return Effect.orDie(Effect
80
+ .tryPromise(() => fs.stat(fileName).then((_) => _.isFile())))
81
+ }
82
+
83
+ export function readTextFile(fileName: string) {
84
+ return Effect.tryPromise(() => fs.readFile(fileName, "utf-8"))
85
+ }
@@ -10,9 +10,8 @@ export function getRequestContextFromFiberRefs(fiberRefs: FiberRefs.FiberRefs) {
10
10
  const locale = FiberRefs.getOrDefault(fiberRefs, LocaleRef)
11
11
  const namespace = FiberRefs.getOrDefault(fiberRefs, storeId)
12
12
  return new RequestContext({
13
- span: Option.getOrElse(
14
- span,
15
- () => ({ spanId: "bogus", sampled: true, traceId: "bogus" })
13
+ span: Option.map(span, Tracer.externalSpan).pipe(
14
+ Option.getOrElse(() => ({ spanId: "bogus", sampled: true, traceId: "bogus" }))
16
15
  ),
17
16
  name: NonEmptyString255("_"),
18
17
  locale,
@@ -0,0 +1,151 @@
1
+ import type { FileOptions } from "@effect-app/infra/fileUtil"
2
+ import { tempFile } from "@effect-app/infra/fileUtil"
3
+ import cp from "child_process"
4
+ import { Config, Effect, Layer, Predicate } from "effect-app"
5
+ import { NonEmptyString255 } from "effect-app/Schema"
6
+ import { pretty } from "effect-app/utils"
7
+ import fs from "fs"
8
+ import os from "os"
9
+ import path from "path"
10
+ import util from "util"
11
+ import { InfraLogger } from "../logger.js"
12
+
13
+ export const PrinterId = NonEmptyString255
14
+ export type PrinterId = NonEmptyString255
15
+
16
+ const exec_ = util.promisify(cp.exec)
17
+ const exec = (command: string) =>
18
+ Effect.andThen(
19
+ InfraLogger.logDebug(`Executing: ${command}`),
20
+ Effect.tap(
21
+ Effect
22
+ .tryPromise(() => exec_(command)),
23
+ (r) => (InfraLogger.logDebug(`Executed`).pipe(Effect.annotateLogs("result", pretty(r))))
24
+ )
25
+ )
26
+
27
+ type PrinterConfig = { url?: URL | undefined; id: string }
28
+
29
+ function printFile(printer: PrinterConfig | undefined, options: string[]) {
30
+ return (filePath: string) => printFile_(filePath, printer, options)
31
+ }
32
+
33
+ function printFile_(filePath: string, printer: PrinterConfig | undefined, options: string[]) {
34
+ return exec(["lp", ...buildPrintArgs(filePath, printer, options)].join(" "))
35
+ }
36
+
37
+ function* buildPrintArgs(filePath: string, printer: PrinterConfig | undefined, options: string[]) {
38
+ if (printer) {
39
+ if (printer.url) {
40
+ yield `-h ${printer.url.host}`
41
+ if (printer.url.username) {
42
+ yield `-U ${printer.url.username}`
43
+ }
44
+ }
45
+ yield `-d "${printer.id}"`
46
+ for (const o of options) {
47
+ yield `-o ${o}`
48
+ }
49
+ }
50
+ yield `"${filePath}"`
51
+ }
52
+
53
+ export const prepareTempDir = Effect.sync(() => {
54
+ // TODO
55
+ try {
56
+ fs.mkdirSync(path.join(os.tmpdir(), "effect-ts-app"))
57
+ } catch (err) {
58
+ if (`${err}`.includes("EEXIST")) {
59
+ return
60
+ }
61
+ throw err
62
+ }
63
+ })
64
+
65
+ const makeTempFile = tempFile("effect-ts-app")
66
+ export const makePrintJobTempFile = makeTempFile("print-job")
67
+ export const makePrintJobTempFileArrayBuffer = (buffer: ArrayBuffer, options?: FileOptions) =>
68
+ makePrintJobTempFile(Buffer.from(buffer), options)
69
+
70
+ function printBuffer(printer: PrinterConfig, options: string[]) {
71
+ return (buffer: ArrayBuffer) =>
72
+ makePrintJobTempFileArrayBuffer(buffer)
73
+ .pipe(
74
+ Effect.flatMap(printFile(printer, options)),
75
+ Effect.scoped
76
+ )
77
+ }
78
+
79
+ function getAvailablePrinters(host?: string) {
80
+ return Effect.gen(function*() {
81
+ const { stdout } = yield* exec(["lpstat", ...buildListArgs({ host }), "-s"].join(" "))
82
+ return [...stdout.matchAll(/device for (\w+):/g)]
83
+ .map((_) => _[1])
84
+ .filter(Predicate.isNotNullable)
85
+ .map((_) => NonEmptyString255(_))
86
+ })
87
+ }
88
+
89
+ function* buildListArgs(config?: { host?: string | undefined }) {
90
+ if (config?.host) {
91
+ yield `-h ${config.host}`
92
+ }
93
+ }
94
+
95
+ export class CUPS extends Effect.Service<CUPS>()("effect-app/CUPS", {
96
+ effect: Effect.gen(function*() {
97
+ const cupsServer = yield* Config.string("cupsServer").pipe(
98
+ Config.mapAttempt((_) => new URL(_)),
99
+ Config.withDefault(undefined)
100
+ )
101
+ function print(buffer: ArrayBuffer, printerId: PrinterId, ...options: string[]) {
102
+ const _print = printBuffer({
103
+ id: printerId,
104
+ url: cupsServer
105
+ }, options)
106
+ return _print(buffer)
107
+ }
108
+ return {
109
+ print,
110
+ printFile: (filePath: string, printerId: PrinterId, ...options: string[]) =>
111
+ printFile({
112
+ id: printerId,
113
+ url: cupsServer
114
+ }, options)(filePath),
115
+ getAvailablePrinters: getAvailablePrinters(cupsServer?.host)
116
+ }
117
+ })
118
+ }) {
119
+ static readonly Fake = Layer.effect(
120
+ this,
121
+ Effect.sync(() => {
122
+ return this.make({
123
+ print: (buffer, printerId, ...options) =>
124
+ InfraLogger
125
+ .logInfo("Printing to fake printer")
126
+ .pipe(
127
+ Effect.zipRight(Effect.sync(() => ({ stdout: "fake", stderr: "" }))),
128
+ Effect
129
+ .annotateLogs({
130
+ printerId,
131
+ "options": pretty(options),
132
+ "bufferSize": buffer.byteLength.toString()
133
+ })
134
+ ),
135
+ printFile: (filePath, printerId, ...options) =>
136
+ InfraLogger
137
+ .logInfo("Printing to fake printer")
138
+ .pipe(
139
+ Effect.zipRight(Effect.sync(() => ({ stdout: "fake", stderr: "" }))),
140
+ Effect
141
+ .annotateLogs({
142
+ printerId,
143
+ filePath,
144
+ "options": pretty(options)
145
+ })
146
+ ),
147
+ getAvailablePrinters: Effect.sync(() => [])
148
+ })
149
+ })
150
+ )
151
+ }
@@ -1,4 +1,3 @@
1
- import { Model } from "@effect-app/infra-adapters/SQL"
2
1
  import { getRequestContext, setupRequestContext } from "@effect-app/infra/api/setupRequest"
3
2
  import { reportNonInterruptedFailure } from "@effect-app/infra/services/QueueMaker/errors"
4
3
  import type { QueueBase } from "@effect-app/infra/services/QueueMaker/service"
@@ -10,6 +9,7 @@ import { Effect, Fiber, Option, S, Tracer } from "effect-app"
10
9
  import type { NonEmptyString255 } from "effect-app/Schema"
11
10
  import { pretty } from "effect-app/utils"
12
11
  import { InfraLogger } from "../../logger.js"
12
+ import { Model } from "../adapters/SQL.js"
13
13
 
14
14
  export const QueueId = S.Number.pipe(S.brand("QueueId"))
15
15
  export type QueueId = typeof QueueId.Type
@@ -1,9 +1,9 @@
1
- import { MemQueue } from "@effect-app/infra-adapters/memQueue"
2
1
  import { Tracer } from "effect"
3
2
  import { Effect, Fiber, flow, S } from "effect-app"
4
3
  import { pretty } from "effect-app/utils"
5
4
  import { getRequestContext, setupRequestContext } from "../../api/setupRequest.js"
6
5
  import { InfraLogger } from "../../logger.js"
6
+ import { MemQueue } from "../adapters/memQueue.js"
7
7
  import { reportNonInterruptedFailure } from "./errors.js"
8
8
  import { type QueueBase, QueueMeta } from "./service.js"
9
9
 
@@ -1,17 +1,17 @@
1
1
  import type {} from "@azure/service-bus"
2
- import {
3
- LiveSender,
4
- LiveServiceBusClient,
5
- Sender,
6
- ServiceBusReceiverFactory,
7
- subscribe
8
- } from "@effect-app/infra-adapters/ServiceBus"
9
2
  import { Tracer } from "effect"
10
3
  import { Cause, Effect, flow, Layer, S } from "effect-app"
11
4
  import type { StringId } from "effect-app/Schema"
12
5
  import { pretty } from "effect-app/utils"
13
6
  import { getRequestContext, setupRequestContext } from "../../api/setupRequest.js"
14
7
  import { InfraLogger } from "../../logger.js"
8
+ import {
9
+ LiveSender,
10
+ LiveServiceBusClient,
11
+ Sender,
12
+ ServiceBusReceiverFactory,
13
+ subscribe
14
+ } from "../adapters/ServiceBus.js"
15
15
  import { reportNonInterruptedFailure, reportNonInterruptedFailureCause, reportQueueError } from "./errors.js"
16
16
  import { type QueueBase, QueueMeta } from "./service.js"
17
17
 
@@ -1,12 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- import { CosmosClient, CosmosClientLayer } from "@effect-app/infra-adapters/cosmos-client"
4
3
  import { Array, Chunk, Duration, Effect, Layer, Option, pipe, Secret, Struct } from "effect-app"
5
4
  import type { NonEmptyReadonlyArray } from "effect-app"
6
5
  import { toNonEmptyArray } from "effect-app/Array"
7
6
  import { dropUndefinedT } from "effect-app/utils"
8
7
  import { OptimisticConcurrencyException } from "../../errors.js"
9
8
  import { InfraLogger } from "../../logger.js"
9
+ import { CosmosClient, CosmosClientLayer } from "../adapters/cosmos-client.js"
10
10
  import { buildWhereCosmosQuery3, logQuery } from "./Cosmos/query.js"
11
11
  import { StoreMaker } from "./service.js"
12
12
  import type { FilterArgs, PersistenceModelType, StorageConfig, Store, StoreConfig } from "./service.js"
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import * as fu from "@effect-app/infra-adapters/fileUtil"
2
+ import * as fu from "../../fileUtil.js"
3
3
 
4
4
  import fs from "fs"
5
5