@adviser/cement 0.3.1 → 0.3.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.
Files changed (138) hide show
  1. package/base-sys-abstraction-CR_Z-Ceg.d.ts +84 -0
  2. package/base-sys-abstraction-DWtPI7Kg.d.cts +84 -0
  3. package/cf/index.cjs +936 -0
  4. package/cf/index.cjs.map +1 -0
  5. package/cf/index.d.cts +27 -0
  6. package/cf/index.d.ts +27 -0
  7. package/cf/index.js +12 -0
  8. package/cf/index.js.map +1 -0
  9. package/{chunk-3RHIVQAA.js → chunk-A7OPSHUV.js} +6 -94
  10. package/chunk-A7OPSHUV.js.map +1 -0
  11. package/chunk-HFP74WLI.js +96 -0
  12. package/chunk-HFP74WLI.js.map +1 -0
  13. package/chunk-P6LDM7PY.js +1189 -0
  14. package/chunk-P6LDM7PY.js.map +1 -0
  15. package/chunk-PRCFKZR7.js +1742 -0
  16. package/chunk-PRCFKZR7.js.map +1 -0
  17. package/deno/index.cjs +947 -0
  18. package/deno/index.cjs.map +1 -0
  19. package/deno/index.d.cts +59 -0
  20. package/deno/index.d.ts +59 -0
  21. package/deno/index.js +16 -0
  22. package/deno/index.js.map +1 -0
  23. package/index-BfZxTAe_.d.cts +318 -0
  24. package/index-CfSl8Gmj.d.ts +318 -0
  25. package/index.cjs +400 -143
  26. package/index.cjs.map +1 -1
  27. package/index.d.cts +7 -317
  28. package/index.d.ts +7 -317
  29. package/index.js +34 -1729
  30. package/index.js.map +1 -1
  31. package/node/index.cjs +272 -217
  32. package/node/index.cjs.map +1 -1
  33. package/node/index.d.cts +16 -21
  34. package/node/index.d.ts +16 -21
  35. package/node/index.js +8 -352
  36. package/node/index.js.map +1 -1
  37. package/package.json +18 -11
  38. package/src/cf/cf-sys-abstraction.ts +86 -0
  39. package/src/cf/index.ts +1 -0
  40. package/src/{node → deno}/deno-file-service.ts +2 -2
  41. package/src/{node → deno}/deno-sys-abstraction.ts +64 -7
  42. package/src/deno/index.ts +2 -0
  43. package/src/index.ts +1 -2
  44. package/src/jsr.json +1 -1
  45. package/src/logger-impl.ts +2 -2
  46. package/src/logger.ts +10 -3
  47. package/src/node/index.ts +0 -1
  48. package/src/node/node-sys-abstraction.ts +45 -1
  49. package/src/runtime.ts +13 -3
  50. package/src/sys-env.ts +19 -113
  51. package/src/test/index.ts +2 -0
  52. package/src/web/web-sys-abstraction.ts +42 -2
  53. package/sys-abstraction-GNnBj2sz.d.cts +102 -0
  54. package/sys-abstraction-GNnBj2sz.d.ts +102 -0
  55. package/test/index.cjs +2688 -0
  56. package/test/index.cjs.map +1 -0
  57. package/test/index.d.cts +3 -0
  58. package/test/index.d.ts +3 -0
  59. package/test/index.js +14 -0
  60. package/test/index.js.map +1 -0
  61. package/ts/base-sys-abstraction.test.js +8 -2
  62. package/ts/base-sys-abstraction.test.js.map +1 -1
  63. package/ts/cf/cf-sys-abstraction.d.ts +25 -0
  64. package/ts/cf/cf-sys-abstraction.d.ts.map +1 -0
  65. package/ts/cf/cf-sys-abstraction.js +80 -0
  66. package/ts/cf/cf-sys-abstraction.js.map +1 -0
  67. package/ts/cf/index.d.ts +2 -0
  68. package/ts/cf/index.d.ts.map +1 -0
  69. package/ts/cf/index.js +2 -0
  70. package/ts/cf/index.js.map +1 -0
  71. package/ts/crypto.test.js +1 -1
  72. package/ts/crypto.test.js.map +1 -1
  73. package/ts/{node → deno}/deno-file-service.d.ts.map +1 -1
  74. package/ts/{node → deno}/deno-file-service.js +1 -1
  75. package/ts/{node → deno}/deno-file-service.js.map +1 -1
  76. package/ts/deno/deno-sys-abstraction.d.ts +43 -0
  77. package/ts/deno/deno-sys-abstraction.d.ts.map +1 -0
  78. package/ts/{node → deno}/deno-sys-abstraction.js +46 -2
  79. package/ts/deno/deno-sys-abstraction.js.map +1 -0
  80. package/ts/deno/index.d.ts +3 -0
  81. package/ts/deno/index.d.ts.map +1 -0
  82. package/ts/deno/index.js +3 -0
  83. package/ts/deno/index.js.map +1 -0
  84. package/ts/index.d.ts +1 -2
  85. package/ts/index.d.ts.map +1 -1
  86. package/ts/index.js +1 -2
  87. package/ts/index.js.map +1 -1
  88. package/ts/logger-impl.js +2 -2
  89. package/ts/logger-impl.js.map +1 -1
  90. package/ts/logger.d.ts.map +1 -1
  91. package/ts/logger.js +9 -3
  92. package/ts/logger.js.map +1 -1
  93. package/ts/logger.test.js +9 -9
  94. package/ts/logger.test.js.map +1 -1
  95. package/ts/node/index.d.ts +0 -1
  96. package/ts/node/index.d.ts.map +1 -1
  97. package/ts/node/index.js +0 -1
  98. package/ts/node/index.js.map +1 -1
  99. package/ts/node/node-sys-abstraction.d.ts +14 -1
  100. package/ts/node/node-sys-abstraction.d.ts.map +1 -1
  101. package/ts/node/node-sys-abstraction.js +43 -0
  102. package/ts/node/node-sys-abstraction.js.map +1 -1
  103. package/ts/runtime.d.ts +1 -0
  104. package/ts/runtime.d.ts.map +1 -1
  105. package/ts/runtime.js +10 -3
  106. package/ts/runtime.js.map +1 -1
  107. package/ts/sys-env.d.ts +0 -11
  108. package/ts/sys-env.d.ts.map +1 -1
  109. package/ts/sys-env.js +19 -104
  110. package/ts/sys-env.js.map +1 -1
  111. package/ts/sys-env.test.js +16 -3
  112. package/ts/sys-env.test.js.map +1 -1
  113. package/ts/test/index.d.ts +3 -0
  114. package/ts/test/index.d.ts.map +1 -0
  115. package/ts/test/index.js +3 -0
  116. package/ts/test/index.js.map +1 -0
  117. package/ts/test/test-exit-handler.js +1 -1
  118. package/ts/web/web-sys-abstraction.d.ts +27 -0
  119. package/ts/web/web-sys-abstraction.d.ts.map +1 -1
  120. package/ts/web/web-sys-abstraction.js +35 -1
  121. package/ts/web/web-sys-abstraction.js.map +1 -1
  122. package/utils/index.js +6 -4
  123. package/web/index.cjs +396 -67
  124. package/web/index.cjs.map +1 -1
  125. package/web/index.d.cts +28 -2
  126. package/web/index.d.ts +28 -2
  127. package/web/index.js +5 -2
  128. package/base-sys-abstraction-BPFyK8XL.d.ts +0 -195
  129. package/base-sys-abstraction-KYXfUGd6.d.cts +0 -195
  130. package/chunk-3RHIVQAA.js.map +0 -1
  131. package/chunk-PSPOGR2I.js +0 -627
  132. package/chunk-PSPOGR2I.js.map +0 -1
  133. package/chunk-STUPETPE.js +0 -87
  134. package/chunk-STUPETPE.js.map +0 -1
  135. package/ts/node/deno-sys-abstraction.d.ts +0 -22
  136. package/ts/node/deno-sys-abstraction.d.ts.map +0 -1
  137. package/ts/node/deno-sys-abstraction.js.map +0 -1
  138. /package/ts/{node → deno}/deno-file-service.d.ts +0 -0
@@ -1,21 +1,78 @@
1
- import { SysAbstraction, SystemService, VoidFunc } from "../sys-abstraction.js";
2
1
  import {
3
- BaseSysAbstraction,
4
- ExitHandler,
5
2
  ExitService,
6
- WrapperSysAbstraction,
3
+ ExitHandler,
4
+ BaseSysAbstraction,
7
5
  WrapperSysAbstractionParams,
6
+ WrapperSysAbstraction,
8
7
  } from "../base-sys-abstraction.js";
9
- import { Env, envFactory } from "../sys-env.js";
8
+ import { ResolveOnce } from "../resolve-once.js";
9
+ import { runtimeFn } from "../runtime.js";
10
+ import { SysAbstraction, SystemService, VoidFunc } from "../sys-abstraction.js";
11
+ import { Env, EnvActions, envFactory, EnvFactoryOpts } from "../sys-env.js";
10
12
  import { Utf8EnDecoderSingleton } from "../txt-en-decoder.js";
11
- import * as process from "node:process";
13
+ // import * as process from "node:process";
12
14
  import { DenoFileService } from "./deno-file-service.js";
13
15
 
14
16
  const Deno = (globalThis as unknown as { Deno: unknown }).Deno as {
15
17
  addSignalListener(sig: string, hdl: () => void): void;
16
18
  exit(code?: number): void;
19
+ args: string[];
17
20
  };
18
21
 
22
+ interface DenoEnv {
23
+ get: (key: string) => string | undefined;
24
+ toObject: () => Record<string, string>;
25
+ set: (key: string, value: string) => void;
26
+ has: (key: string) => boolean;
27
+ delete: (key: string) => void;
28
+ }
29
+
30
+ const once = new ResolveOnce<DenoEnvActions>();
31
+ export class DenoEnvActions implements EnvActions {
32
+ readonly #deno = globalThis as unknown as {
33
+ Deno: {
34
+ env: DenoEnv;
35
+ };
36
+ };
37
+
38
+ static new(opts: Partial<EnvFactoryOpts>): EnvActions {
39
+ return once.once(() => new DenoEnvActions(opts));
40
+ }
41
+
42
+ get _env(): DenoEnv {
43
+ return this.#deno.Deno.env;
44
+ }
45
+
46
+ readonly opts: Partial<EnvFactoryOpts>;
47
+ private constructor(opts: Partial<EnvFactoryOpts>) {
48
+ this.opts = opts;
49
+ }
50
+
51
+ register(env: Env): Env {
52
+ for (const key of env.keys()) {
53
+ this._env.set(key, env.get(key) || "");
54
+ }
55
+ return env;
56
+ }
57
+ active(): boolean {
58
+ return runtimeFn().isDeno;
59
+ }
60
+ keys(): string[] {
61
+ return Object.keys(this._env.toObject());
62
+ }
63
+ get(key: string): string | undefined {
64
+ return this._env.get(key);
65
+ }
66
+ set(key: string, value?: string): void {
67
+ if (value) {
68
+ this._env.set(key, value);
69
+ }
70
+ }
71
+ delete(key: string): void {
72
+ this._env.delete(key);
73
+ }
74
+ }
75
+
19
76
  export class DenoExitServiceImpl implements ExitService {
20
77
  constructor() {
21
78
  globalThis.addEventListener("unhandledrejection", (e) => {
@@ -101,7 +158,7 @@ export class DenoSystemService implements SystemService {
101
158
  }
102
159
 
103
160
  Args(): string[] {
104
- return process.argv;
161
+ return Deno.args;
105
162
  }
106
163
 
107
164
  OnExit(hdl: VoidFunc): VoidFunc {
@@ -0,0 +1,2 @@
1
+ export * from "./deno-sys-abstraction.js";
2
+ export * from "./deno-file-service.js";
package/src/index.ts CHANGED
@@ -4,8 +4,7 @@ export * from "./logger.js";
4
4
  export * from "./sys-abstraction.js";
5
5
  export * from "./sys-env.js";
6
6
  export * from "./time.js";
7
- export * from "./test/log-write-stream.js";
8
- export * from "./test/mock-logger.js";
7
+ export * from "./test/index.js";
9
8
  export * from "./txt-en-decoder.js";
10
9
  export * from "./log-level-impl.js";
11
10
  export * from "./result.js";
package/src/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adviser/cement",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "exports": {
5
5
  ".": "./index.ts",
6
6
  "./web": "./web/index.ts",
@@ -146,7 +146,7 @@ export class LoggerImpl implements Logger {
146
146
  if (rt.isBrowser) {
147
147
  stream = new ConsoleWriterStream();
148
148
  } else {
149
- if (rt.isNodeIsh || rt.isReactNative || rt.isDeno) {
149
+ if (rt.isNodeIsh || rt.isReactNative || rt.isDeno || rt.isCFWorker) {
150
150
  stream = this._sys.Stdout();
151
151
  } else {
152
152
  throw new Error("No output defined for runtime");
@@ -267,7 +267,7 @@ export class LoggerImpl implements Logger {
267
267
  }
268
268
  if (this.levelHandler.isStackExposed) {
269
269
  this._attributes["stack"] = logValue(
270
- err.stack?.split("\n").map((s) => s.trim()),
270
+ err.stack?.split(/[\r\n]+/).map((s) => s.trim()),
271
271
  toLogValueCtx(this.levelHandler),
272
272
  );
273
273
  }
package/src/logger.ts CHANGED
@@ -81,11 +81,18 @@ function logValueInternal(val: LogValueArg, ctx: LogValueStateInternal): LogValu
81
81
  }
82
82
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
83
83
  } catch (e) {
84
- if (val.match(/[\n\r]/)) {
85
- const lines = val.trimEnd().split(/[\n\r]/);
86
- return new LogValue(() => lines);
84
+ try {
85
+ const url = new URL(val);
86
+ return new LogValue(() => url.toString());
87
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
88
+ } catch (e) {
89
+ // ignore
87
90
  }
88
91
  }
92
+ if (val.match(/[\n\r]/)) {
93
+ const lines = val.split(/[\n\r]+/).map((v) => v.trim());
94
+ return new LogValue(() => lines);
95
+ }
89
96
  return new LogValue(() => val.toString());
90
97
  }
91
98
  case "number":
package/src/node/index.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export * from "./node-file-service.js";
2
2
  export * from "./node-sys-abstraction.js";
3
- export * from "./deno-sys-abstraction.js";
4
3
  export * from "./mock-file-service.js";
@@ -7,9 +7,53 @@ import {
7
7
  WrapperSysAbstractionParams,
8
8
  } from "../base-sys-abstraction.js";
9
9
  import { NodeFileService } from "./node-file-service.js";
10
- import { Env, envFactory } from "../sys-env.js";
10
+ import { Env, EnvActions, envFactory, EnvFactoryOpts } from "../sys-env.js";
11
11
  import { Utf8EnDecoderSingleton } from "../txt-en-decoder.js";
12
12
  import process from "node:process";
13
+ import { runtimeFn } from "../runtime.js";
14
+ import { ResolveOnce } from "../resolve-once.js";
15
+
16
+ const once = new ResolveOnce<NodeEnvActions>();
17
+ export class NodeEnvActions implements EnvActions {
18
+ readonly #node = globalThis as unknown as { process: { env: Record<string, string> } };
19
+
20
+ static new(opts: Partial<EnvFactoryOpts>): EnvActions {
21
+ return once.once(() => new NodeEnvActions(opts));
22
+ }
23
+
24
+ readonly opts: Partial<EnvFactoryOpts>;
25
+ private constructor(opts: Partial<EnvFactoryOpts>) {
26
+ this.opts = opts;
27
+ }
28
+
29
+ register(env: Env): Env {
30
+ for (const key of env.keys()) {
31
+ this._env[key] = env.get(key) || "";
32
+ }
33
+ return env;
34
+ }
35
+
36
+ active(): boolean {
37
+ return runtimeFn().isNodeIsh;
38
+ // typeof this.#node === "object" && typeof this.#node.process === "object" && typeof this.#node.process.env === "object";
39
+ }
40
+ readonly _env: Record<string, string> = this.active() ? this.#node.process.env : {};
41
+ keys(): string[] {
42
+ return Object.keys(this._env);
43
+ }
44
+ get(key: string): string | undefined {
45
+ return this._env[key];
46
+ }
47
+ set(key: string, value?: string): void {
48
+ if (value) {
49
+ this._env[key] = value;
50
+ }
51
+ }
52
+ delete(key: string): void {
53
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
54
+ delete this._env[key];
55
+ }
56
+ }
13
57
 
14
58
  export class NodeExitServiceImpl implements ExitService {
15
59
  constructor() {
package/src/runtime.ts CHANGED
@@ -3,6 +3,7 @@ export interface Runtime {
3
3
  isBrowser: boolean;
4
4
  isDeno: boolean;
5
5
  isReactNative: boolean;
6
+ isCFWorker: boolean;
6
7
  }
7
8
 
8
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -17,20 +18,29 @@ function isSet(value: string, ref: any = globalThis): boolean {
17
18
  return false;
18
19
  }
19
20
 
21
+ // caches.default or WebSocketPair
22
+
20
23
  export function runtimeFn(): Runtime {
21
24
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
25
  const gt: any = globalThis;
23
- const isReactNative =
26
+ let isReactNative =
24
27
  isSet("navigator.product") && typeof gt["navigator"] === "object" && gt["navigator"]["product"] === "ReactNative";
25
28
  let isNodeIsh = false;
26
29
  if (!isSet("Deno")) {
27
30
  isNodeIsh = isSet("process.versions.node") && !isReactNative;
28
31
  }
29
- const isDeno = isSet("Deno");
32
+ let isDeno = isSet("Deno");
33
+ const isCFWorker = isSet("caches.default") && isSet("WebSocketPair");
34
+ if (isCFWorker) {
35
+ isDeno = false;
36
+ isNodeIsh = false;
37
+ isReactNative = false;
38
+ }
30
39
  return {
31
40
  isNodeIsh,
32
- isBrowser: !(isNodeIsh || isDeno) && !isReactNative,
41
+ isBrowser: !(isNodeIsh || isDeno || isCFWorker || isReactNative),
33
42
  isDeno,
34
43
  isReactNative,
44
+ isCFWorker,
35
45
  };
36
46
  }
package/src/sys-env.ts CHANGED
@@ -1,4 +1,8 @@
1
- import { ResolveOnce } from "./resolve-once.js";
1
+ import { DenoEnvActions } from "./deno/deno-sys-abstraction.js";
2
+ import { NodeEnvActions } from "./node/node-sys-abstraction.js";
3
+ import { BrowserEnvActions } from "./web/web-sys-abstraction.js";
4
+ import { CFEnvActions } from "./cf/cf-sys-abstraction.js";
5
+ import { KeyedResolvOnce } from "./resolve-once.js";
2
6
 
3
7
  export interface EnvMap {
4
8
  get(key: string): string | undefined;
@@ -11,106 +15,6 @@ export interface EnvActions extends EnvMap {
11
15
  register(env: Env): Env;
12
16
  }
13
17
 
14
- class NodeEnvActions implements EnvActions {
15
- readonly #node = globalThis as unknown as { process: { env: Record<string, string> } };
16
-
17
- // eslint-disable-next-line @typescript-eslint/no-useless-constructor, @typescript-eslint/no-unused-vars
18
- constructor(opts: Partial<EnvFactoryOpts>) {
19
- // do nothing
20
- }
21
-
22
- register(env: Env): Env {
23
- return env;
24
- }
25
-
26
- active(): boolean {
27
- return typeof this.#node === "object" && typeof this.#node.process === "object" && typeof this.#node.process.env === "object";
28
- }
29
- readonly _env = this.active() ? this.#node.process.env : {};
30
- keys(): string[] {
31
- return Object.keys(this._env);
32
- }
33
- get(key: string): string | undefined {
34
- return this._env[key];
35
- }
36
- set(key: string, value?: string): void {
37
- if (value) {
38
- this._env[key] = value;
39
- }
40
- }
41
- delete(key: string): void {
42
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
43
- delete this._env[key];
44
- }
45
- }
46
-
47
- class DenoEnvActions implements EnvActions {
48
- readonly #deno = globalThis as unknown as { Deno: { env: Map<string, string> } };
49
-
50
- get _env(): Map<string, string> {
51
- return this.#deno.Deno.env;
52
- }
53
-
54
- // eslint-disable-next-line @typescript-eslint/no-useless-constructor, @typescript-eslint/no-unused-vars
55
- constructor(opts: Partial<EnvFactoryOpts>) {
56
- // do nothing
57
- }
58
-
59
- register(env: Env): Env {
60
- return env;
61
- }
62
- active(): boolean {
63
- return typeof this.#deno === "object" && typeof this.#deno.Deno === "object" && typeof this.#deno.Deno.env === "object";
64
- }
65
- keys(): string[] {
66
- return Array.from(this._env.keys());
67
- }
68
- get(key: string): string | undefined {
69
- return this._env.get(key);
70
- }
71
- set(key: string, value?: string): void {
72
- if (value) {
73
- this._env.set(key, value);
74
- }
75
- }
76
- delete(key: string): void {
77
- this._env.delete(key);
78
- }
79
- }
80
-
81
- export class BrowserEnvActions implements EnvActions {
82
- readonly env: Map<string, string> = new Map<string, string>();
83
- readonly opts: Partial<EnvFactoryOpts>;
84
- constructor(opts: Partial<EnvFactoryOpts>) {
85
- this.opts = opts;
86
- }
87
-
88
- get(key: string): string | undefined {
89
- return this.env.get(key);
90
- }
91
- set(key: string, value?: string): void {
92
- if (value) {
93
- this.env.set(key, value);
94
- }
95
- }
96
- delete(key: string): void {
97
- this.env.delete(key);
98
- }
99
- keys(): string[] {
100
- return Array.from(this.env.keys());
101
- }
102
- active(): boolean {
103
- return true; // that should work on every runtime
104
- }
105
-
106
- register(env: Env): Env {
107
- const sym = Symbol.for(this.opts.symbol || "CP_ENV");
108
- const browser = globalThis as unknown as Record<symbol, Env>;
109
- browser[sym] = env;
110
- return env;
111
- }
112
- }
113
-
114
18
  export interface EnvFactoryOpts {
115
19
  readonly symbol: string; // default "CP_ENV" used by BrowserEnvActions
116
20
  readonly presetEnv: Map<string, string>;
@@ -129,16 +33,17 @@ export interface Env extends EnvMap {
129
33
  export type EnvFactoryFn = (opts: Partial<EnvFactoryOpts>) => EnvActions;
130
34
 
131
35
  const envActions: { id: string; fn: EnvFactoryFn }[] = [
132
- { id: "node", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => new NodeEnvActions(opts) },
133
- { id: "deno", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => new DenoEnvActions(opts) },
134
- { id: "browser", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => new BrowserEnvActions(opts) },
36
+ { id: "cf", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => CFEnvActions.new(opts) },
37
+ { id: "node", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => NodeEnvActions.new(opts) },
38
+ { id: "deno", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => DenoEnvActions.new(opts) },
39
+ { id: "browser", fn: (opts: Partial<EnvFactoryOpts>): EnvActions => BrowserEnvActions.new(opts) },
135
40
  ];
136
41
 
137
42
  export function registerEnvAction(fn: EnvFactoryFn): () => void {
138
43
  const id = `id-${Math.random()}`;
139
44
  envActions.unshift({ id, fn });
140
45
  // rerun envFactory
141
- _envFactory.reset();
46
+ _envFactories.unget(id);
142
47
  return () => {
143
48
  const index = envActions.findIndex((i) => i.id === id);
144
49
  if (index >= 0) {
@@ -147,15 +52,16 @@ export function registerEnvAction(fn: EnvFactoryFn): () => void {
147
52
  };
148
53
  }
149
54
 
150
- const _envFactory = new ResolveOnce<Env>();
55
+ const _envFactories = new KeyedResolvOnce<Env>();
151
56
  export function envFactory(opts: Partial<EnvFactoryOpts> = {}): Env {
152
- return _envFactory.once(() => {
153
- const found = envActions.map((facItem) => facItem.fn(opts)).find((env) => env.active());
154
- if (!found) {
155
- throw new Error("SysContainer:envFactory: no env available");
156
- }
157
- const ret = new EnvImpl(found, opts);
158
- found.register(ret);
57
+ const found = envActions.find((fi) => fi.fn(opts).active());
58
+ if (!found) {
59
+ throw new Error("SysContainer:envFactory: no env available");
60
+ }
61
+ return _envFactories.get(found.id).once(() => {
62
+ const action = found.fn(opts);
63
+ const ret = new EnvImpl(action, opts);
64
+ action.register(ret);
159
65
  return ret;
160
66
  });
161
67
  }
@@ -0,0 +1,2 @@
1
+ export * from "./log-write-stream.js";
2
+ export * from "./mock-logger.js";
@@ -1,10 +1,50 @@
1
1
  import { BaseSysAbstraction, WrapperSysAbstraction, WrapperSysAbstractionParams } from "../base-sys-abstraction.js";
2
2
  import { FileService, NamedWritableStream } from "../file-service.js";
3
+ import { ResolveOnce } from "../resolve-once.js";
3
4
  import { SysAbstraction, SystemService, VoidFunc } from "../sys-abstraction.js";
4
- import { Env, envFactory } from "../sys-env.js";
5
+ import { Env, EnvActions, envFactory, EnvFactoryOpts } from "../sys-env.js";
5
6
  import { Utf8EnDecoderSingleton } from "../txt-en-decoder.js";
6
7
 
7
- class WebFileService implements FileService {
8
+ const once = new ResolveOnce<BrowserEnvActions>();
9
+ export class BrowserEnvActions implements EnvActions {
10
+ readonly env: Map<string, string> = new Map<string, string>();
11
+ readonly opts: Partial<EnvFactoryOpts>;
12
+
13
+ static new(opts: Partial<EnvFactoryOpts>): EnvActions {
14
+ return once.once(() => new BrowserEnvActions(opts));
15
+ }
16
+
17
+ private constructor(opts: Partial<EnvFactoryOpts>) {
18
+ this.opts = opts;
19
+ }
20
+
21
+ get(key: string): string | undefined {
22
+ return this.env.get(key);
23
+ }
24
+ set(key: string, value?: string): void {
25
+ if (value) {
26
+ this.env.set(key, value);
27
+ }
28
+ }
29
+ delete(key: string): void {
30
+ this.env.delete(key);
31
+ }
32
+ keys(): string[] {
33
+ return Array.from(this.env.keys());
34
+ }
35
+ active(): boolean {
36
+ return true; // that should work on every runtime
37
+ }
38
+
39
+ register(env: Env): Env {
40
+ const sym = Symbol.for(this.opts.symbol || "CP_ENV");
41
+ const browser = globalThis as unknown as Record<symbol, Env>;
42
+ browser[sym] = env;
43
+ return env;
44
+ }
45
+ }
46
+
47
+ export class WebFileService implements FileService {
8
48
  get baseDir(): string {
9
49
  throw new Error("basedir-Method not implemented.");
10
50
  }
@@ -0,0 +1,102 @@
1
+ interface NamedWritableStream {
2
+ readonly name: string;
3
+ readonly stream: WritableStream<Uint8Array>;
4
+ }
5
+ interface FileService {
6
+ readonly baseDir: string;
7
+ create(fname: string): Promise<NamedWritableStream>;
8
+ readFileString(fname: string): Promise<string>;
9
+ writeFileString(fname: string, content: string): Promise<void>;
10
+ abs(fname: string): string;
11
+ join(...paths: string[]): string;
12
+ relative(from: string, to?: string): string;
13
+ dirname(fname: string): string;
14
+ basename(fname: string): string;
15
+ isAbsolute(fname: string): boolean;
16
+ }
17
+
18
+ interface EnvMap {
19
+ get(key: string): string | undefined;
20
+ set(key: string, value?: string): void;
21
+ delete(key: string): void;
22
+ keys(): string[];
23
+ }
24
+ interface EnvActions extends EnvMap {
25
+ active(): boolean;
26
+ register(env: Env): Env;
27
+ }
28
+ interface EnvFactoryOpts {
29
+ readonly symbol: string;
30
+ readonly presetEnv: Map<string, string>;
31
+ }
32
+ type OnSetFn = (key: string, value?: string) => void;
33
+ interface OnSetItem {
34
+ readonly filter: Set<string>;
35
+ readonly fn: OnSetFn;
36
+ }
37
+ interface Env extends EnvMap {
38
+ onSet(fn: OnSetFn, ...filter: string[]): void;
39
+ }
40
+ type EnvFactoryFn = (opts: Partial<EnvFactoryOpts>) => EnvActions;
41
+ declare function registerEnvAction(fn: EnvFactoryFn): () => void;
42
+ declare function envFactory(opts?: Partial<EnvFactoryOpts>): Env;
43
+ declare class EnvImpl implements Env {
44
+ readonly _map: EnvMap;
45
+ constructor(map: EnvMap, opts?: Partial<EnvFactoryOpts>);
46
+ _updatePresets(presetEnv?: Map<string, string>): void;
47
+ _applyOnSet(onSet: OnSetItem[], key?: string, value?: string): void;
48
+ readonly _onSet: OnSetItem[];
49
+ keys(): string[];
50
+ onSet(fn: OnSetFn, ...filter: string[]): void;
51
+ get(key: string): string | undefined;
52
+ set(key: string, value?: string): void;
53
+ delete(key: string): void;
54
+ }
55
+
56
+ declare abstract class Time {
57
+ abstract Now(add?: number): Date;
58
+ abstract Sleep(duration: Duration): Promise<void>;
59
+ TimeSince(start: Date): Duration;
60
+ }
61
+ type Duration = number;
62
+ declare enum TimeUnits {
63
+ Microsecond = 1,
64
+ Second = 1000,
65
+ Minute = 60000,
66
+ Hour = 3600000
67
+ }
68
+
69
+ declare enum TimeMode {
70
+ REAL = "real",
71
+ CONST = "const",
72
+ STEP = "step"
73
+ }
74
+ declare enum RandomMode {
75
+ CONST = "const",
76
+ STEP = "step",
77
+ RANDOM = "random"
78
+ }
79
+ declare enum IDMode {
80
+ UUID = "uuid",
81
+ CONST = "const",
82
+ STEP = "step"
83
+ }
84
+ declare function String2TimeMode(s?: string): TimeMode;
85
+ type VoidFunc = () => void | Promise<void>;
86
+ interface SystemService {
87
+ Env(): Env;
88
+ Args(): string[];
89
+ OnExit(hdl: VoidFunc): VoidFunc;
90
+ Exit(code: number): void;
91
+ }
92
+ interface SysAbstraction {
93
+ Time(): Time;
94
+ Stdout(): WritableStream<Uint8Array>;
95
+ Stderr(): WritableStream<Uint8Array>;
96
+ NextId(): string;
97
+ Random0ToValue(value: number): number;
98
+ System(): SystemService;
99
+ FileSystem(): FileService;
100
+ }
101
+
102
+ export { type Duration as D, type EnvActions as E, type FileService as F, IDMode as I, type NamedWritableStream as N, type OnSetItem as O, RandomMode as R, type SystemService as S, Time as T, type VoidFunc as V, EnvImpl as a, type EnvFactoryOpts as b, type Env as c, type SysAbstraction as d, TimeMode as e, String2TimeMode as f, type EnvMap as g, type EnvFactoryFn as h, envFactory as i, TimeUnits as j, registerEnvAction as r };
@@ -0,0 +1,102 @@
1
+ interface NamedWritableStream {
2
+ readonly name: string;
3
+ readonly stream: WritableStream<Uint8Array>;
4
+ }
5
+ interface FileService {
6
+ readonly baseDir: string;
7
+ create(fname: string): Promise<NamedWritableStream>;
8
+ readFileString(fname: string): Promise<string>;
9
+ writeFileString(fname: string, content: string): Promise<void>;
10
+ abs(fname: string): string;
11
+ join(...paths: string[]): string;
12
+ relative(from: string, to?: string): string;
13
+ dirname(fname: string): string;
14
+ basename(fname: string): string;
15
+ isAbsolute(fname: string): boolean;
16
+ }
17
+
18
+ interface EnvMap {
19
+ get(key: string): string | undefined;
20
+ set(key: string, value?: string): void;
21
+ delete(key: string): void;
22
+ keys(): string[];
23
+ }
24
+ interface EnvActions extends EnvMap {
25
+ active(): boolean;
26
+ register(env: Env): Env;
27
+ }
28
+ interface EnvFactoryOpts {
29
+ readonly symbol: string;
30
+ readonly presetEnv: Map<string, string>;
31
+ }
32
+ type OnSetFn = (key: string, value?: string) => void;
33
+ interface OnSetItem {
34
+ readonly filter: Set<string>;
35
+ readonly fn: OnSetFn;
36
+ }
37
+ interface Env extends EnvMap {
38
+ onSet(fn: OnSetFn, ...filter: string[]): void;
39
+ }
40
+ type EnvFactoryFn = (opts: Partial<EnvFactoryOpts>) => EnvActions;
41
+ declare function registerEnvAction(fn: EnvFactoryFn): () => void;
42
+ declare function envFactory(opts?: Partial<EnvFactoryOpts>): Env;
43
+ declare class EnvImpl implements Env {
44
+ readonly _map: EnvMap;
45
+ constructor(map: EnvMap, opts?: Partial<EnvFactoryOpts>);
46
+ _updatePresets(presetEnv?: Map<string, string>): void;
47
+ _applyOnSet(onSet: OnSetItem[], key?: string, value?: string): void;
48
+ readonly _onSet: OnSetItem[];
49
+ keys(): string[];
50
+ onSet(fn: OnSetFn, ...filter: string[]): void;
51
+ get(key: string): string | undefined;
52
+ set(key: string, value?: string): void;
53
+ delete(key: string): void;
54
+ }
55
+
56
+ declare abstract class Time {
57
+ abstract Now(add?: number): Date;
58
+ abstract Sleep(duration: Duration): Promise<void>;
59
+ TimeSince(start: Date): Duration;
60
+ }
61
+ type Duration = number;
62
+ declare enum TimeUnits {
63
+ Microsecond = 1,
64
+ Second = 1000,
65
+ Minute = 60000,
66
+ Hour = 3600000
67
+ }
68
+
69
+ declare enum TimeMode {
70
+ REAL = "real",
71
+ CONST = "const",
72
+ STEP = "step"
73
+ }
74
+ declare enum RandomMode {
75
+ CONST = "const",
76
+ STEP = "step",
77
+ RANDOM = "random"
78
+ }
79
+ declare enum IDMode {
80
+ UUID = "uuid",
81
+ CONST = "const",
82
+ STEP = "step"
83
+ }
84
+ declare function String2TimeMode(s?: string): TimeMode;
85
+ type VoidFunc = () => void | Promise<void>;
86
+ interface SystemService {
87
+ Env(): Env;
88
+ Args(): string[];
89
+ OnExit(hdl: VoidFunc): VoidFunc;
90
+ Exit(code: number): void;
91
+ }
92
+ interface SysAbstraction {
93
+ Time(): Time;
94
+ Stdout(): WritableStream<Uint8Array>;
95
+ Stderr(): WritableStream<Uint8Array>;
96
+ NextId(): string;
97
+ Random0ToValue(value: number): number;
98
+ System(): SystemService;
99
+ FileSystem(): FileService;
100
+ }
101
+
102
+ export { type Duration as D, type EnvActions as E, type FileService as F, IDMode as I, type NamedWritableStream as N, type OnSetItem as O, RandomMode as R, type SystemService as S, Time as T, type VoidFunc as V, EnvImpl as a, type EnvFactoryOpts as b, type Env as c, type SysAbstraction as d, TimeMode as e, String2TimeMode as f, type EnvMap as g, type EnvFactoryFn as h, envFactory as i, TimeUnits as j, registerEnvAction as r };