@adviser/cement 0.0.0-jsr-t1 → 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ import { runtimeFn } from "@adviser/cement";
2
+ import { MockFileService } from "@adviser/cement/node";
3
+
4
+ describe("MockFileService", () => {
5
+ if (runtimeFn().isNodeIsh || runtimeFn().isDeno) {
6
+ let MFS: MockFileService;
7
+ beforeAll(async () => {
8
+ const { MockFileService } = await import("./mock-file-service.js");
9
+ MFS = new MockFileService();
10
+ });
11
+ it("writeFileString", async () => {
12
+ const f = MFS;
13
+ const absFname = f.abs("test");
14
+ await f.writeFileString("test", "hello");
15
+ expect(f.files).toEqual({
16
+ [absFname]: {
17
+ content: "hello",
18
+ name: absFname,
19
+ },
20
+ test: {
21
+ name: absFname,
22
+ content: "hello",
23
+ },
24
+ });
25
+ });
26
+ } else {
27
+ it.skip("nothing in browser", () => {
28
+ expect(1).toEqual(1);
29
+ });
30
+ }
31
+ });
@@ -0,0 +1,100 @@
1
+ import type { ExecException, exec } from "node:child_process";
2
+ import { runtimeFn } from "@adviser/cement";
3
+
4
+ function exitHandler(errCode: number, larg: string, done: () => void) {
5
+ return (err: ExecException | null, stdout: string | Buffer, stderr: string | Buffer): void => {
6
+ if (err) {
7
+ expect(err.code).toBe(errCode);
8
+ }
9
+ if (stdout) {
10
+ const res = stdout
11
+ .toString()
12
+ .split("\n")
13
+ .filter((line) => line.trim())
14
+ .map((line) => {
15
+ const out = JSON.parse(line);
16
+ return out;
17
+ })
18
+ .map((obj) => {
19
+ delete obj.pid;
20
+ return obj;
21
+ });
22
+ expect(res).toEqual([
23
+ {
24
+ larg: larg,
25
+ },
26
+ {
27
+ larg: larg,
28
+ msg: "Called OnExit 1",
29
+ },
30
+ {
31
+ larg: larg,
32
+ msg: "Called OnExit 2",
33
+ },
34
+ ]);
35
+ done();
36
+ }
37
+ if (stderr) {
38
+ expect(stderr).toEqual({});
39
+ }
40
+ };
41
+ }
42
+
43
+ describe("node_sys", () => {
44
+ if (runtimeFn().isNodeIsh || runtimeFn().isDeno) {
45
+ let fnExec: typeof exec;
46
+ let execHandler = "tsx src/test/test-exit-handler.ts";
47
+ beforeAll(async () => {
48
+ const { exec } = await import("node:child_process");
49
+ fnExec = exec;
50
+ if (runtimeFn().isDeno) {
51
+ execHandler = "deno run --allow-net --allow-read --allow-run --unstable-sloppy-imports src/test/test-exit-handler.ts";
52
+ // // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ // const gs = globalThis as any;
54
+ // fnExec = (async (cmd: string, cb: (err: ExecException | null, stdout: string | Buffer, stderr: string | Buffer) => void) => {
55
+ // const c = new gs.Deno.Command(cmd.split(" ")[0], {
56
+ // args: cmd.split(" ").slice(1),
57
+ // stdout: "piped",
58
+ // stderr: "piped",
59
+ // });
60
+ // const result = await c.output();
61
+ // const td = new TextDecoder();
62
+ // cb(result, td.decode(result.stdout), td.decode(result.stderr));
63
+ // }) as unknown as typeof exec;
64
+ }
65
+ });
66
+ it("just-exit", () => {
67
+ return new Promise<void>((done) => {
68
+ fnExec(`${execHandler} exit24`, exitHandler(24, "exit24", done));
69
+ });
70
+ });
71
+
72
+ it("throw", () => {
73
+ return new Promise<void>((done) => {
74
+ fnExec(`${execHandler} throw`, exitHandler(19, "throw", done));
75
+ });
76
+ });
77
+
78
+ it("via sigint", () => {
79
+ return new Promise<void>((done) => {
80
+ fnExec(`${execHandler} sigint`, exitHandler(2, "sigint", done));
81
+ });
82
+ });
83
+
84
+ it("via sigterm", () => {
85
+ return new Promise<void>((done) => {
86
+ fnExec(`${execHandler} sigterm`, exitHandler(9, "sigterm", done));
87
+ });
88
+ });
89
+
90
+ it("via sigquit", () => {
91
+ return new Promise<void>((done) => {
92
+ fnExec(`${execHandler} sigquit`, exitHandler(3, "sigquit", done));
93
+ });
94
+ });
95
+ } else {
96
+ it.skip("nothing in browser", () => {
97
+ expect(true).toBe(true);
98
+ });
99
+ }
100
+ });
@@ -0,0 +1,42 @@
1
+ import { wrapRefcounted } from "./refcounted.js";
2
+
3
+ class RealInstance {
4
+ x: number;
5
+ isOpen = true;
6
+ constructor(x: number) {
7
+ this.x = x;
8
+ }
9
+ wurst(): number {
10
+ return this.x++;
11
+ }
12
+ close(): void {
13
+ if (!this.isOpen) {
14
+ throw new Error("already closed");
15
+ }
16
+ this.isOpen = false;
17
+ }
18
+ }
19
+
20
+ it("simple", () => {
21
+ const obj = wrapRefcounted(new RealInstance(42), "close");
22
+ expect(obj.wurst()).toBe(42);
23
+ obj.close();
24
+ expect(() => obj.close()).toThrowError("already closed");
25
+ });
26
+
27
+ it("nested", () => {
28
+ const ri = new RealInstance(42);
29
+ const obj1 = wrapRefcounted(ri, "close");
30
+ const obj2 = wrapRefcounted(ri, "close");
31
+ expect(obj1).toBe(obj2);
32
+ expect(obj1.wurst()).toBe(42);
33
+ expect(obj2.wurst()).toBe(43);
34
+ obj2.close();
35
+ expect(obj2.isOpen).toBe(true);
36
+ expect(obj2.wurst()).toBe(44);
37
+ expect(obj1.wurst()).toBe(45);
38
+ obj1.close();
39
+ expect(obj1.wurst()).toBe(46);
40
+ expect(obj2.isOpen).toBe(false);
41
+ expect(() => obj2.close()).toThrowError("already closed");
42
+ });
@@ -0,0 +1,23 @@
1
+ type Refcounted<T, M extends string> = T & {
2
+ __refcounted: number;
3
+ __unrefcounted: () => void;
4
+ } & Record<M, () => void>;
5
+
6
+ export function wrapRefcounted<T, M extends string>(t: T, method: M): T {
7
+ const my = t as Refcounted<T, M>;
8
+ my.__refcounted = (my.__refcounted || 0) + 1;
9
+ if (my.__refcounted === 1) {
10
+ my.__unrefcounted = my[method];
11
+ const mRec = my as Record<string, () => void>;
12
+ mRec[method] = function (this: Refcounted<T, M>): void {
13
+ this.__refcounted--;
14
+ if (this.__refcounted === 0) {
15
+ this.__unrefcounted();
16
+ }
17
+ if (this.__refcounted < 0) {
18
+ throw new Error("already closed");
19
+ }
20
+ };
21
+ }
22
+ return t;
23
+ }
@@ -0,0 +1,67 @@
1
+ import { LogWriteStream, MockLogger } from "@adviser/cement";
2
+
3
+ describe("logger", () => {
4
+ it("with logcollector", async () => {
5
+ const l = MockLogger();
6
+ l.logger.Debug().Str("bla1", "blub1").Msg("hello1");
7
+ l.logger.Info().Str("bla2", "blub2").Msg("hello2");
8
+ await l.logger.Flush();
9
+ expect(l.logCollector.Logs()).toEqual([
10
+ { level: "debug", bla1: "blub1", msg: "hello1", module: "MockLogger" },
11
+ { level: "info", bla2: "blub2", msg: "hello2", module: "MockLogger" },
12
+ ]);
13
+ });
14
+
15
+ it("with logcollector disableDebug", async () => {
16
+ const l = MockLogger({
17
+ disableDebug: true,
18
+ });
19
+ l.logger.Debug().Str("bla1", "blub1").Msg("hello1");
20
+ l.logger.Info().Str("bla2", "blub2").Msg("hello2");
21
+ await l.logger.Flush();
22
+ expect(l.logCollector.Logs()).toEqual([{ level: "info", bla2: "blub2", msg: "hello2", module: "MockLogger" }]);
23
+ });
24
+
25
+ it("with logcollector moduleName", async () => {
26
+ const l = MockLogger({
27
+ moduleName: "test",
28
+ });
29
+ l.logger.Debug().Str("bla1", "blub1").Msg("hello1");
30
+ l.logger.Info().Str("bla2", "blub2").Msg("hello2");
31
+ await l.logger.Flush();
32
+ expect(l.logCollector.Logs()).toEqual([
33
+ { level: "debug", bla1: "blub1", msg: "hello1", module: "test" },
34
+ { level: "info", bla2: "blub2", msg: "hello2", module: "test" },
35
+ ]);
36
+ });
37
+
38
+ it("with logcollector [moduleName]", async () => {
39
+ const l = MockLogger({
40
+ moduleName: ["test", "wurst"],
41
+ });
42
+ l.logger.Debug().Str("bla1", "blub1").Msg("hello1");
43
+ l.logger.With().Module("wurst").Logger().Debug().Str("bla2", "blub2").Msg("hello2");
44
+ await l.logger.Flush();
45
+ expect(l.logCollector.Logs()).toEqual([
46
+ { level: "debug", bla1: "blub1", msg: "hello1", module: "test" },
47
+ { level: "debug", bla2: "blub2", msg: "hello2", module: "wurst" },
48
+ ]);
49
+ });
50
+
51
+ it("tee in logcolletor", async () => {
52
+ const lc2Buffer: Uint8Array[] = [];
53
+ const lc2 = new LogWriteStream(lc2Buffer);
54
+ const l = MockLogger({
55
+ pass: lc2,
56
+ });
57
+ l.logger.Error().Msg("should been shown in console");
58
+ await l.logger.Flush();
59
+ expect(l.logCollector.Logs()).toEqual([{ level: "error", msg: "should been shown in console", module: "MockLogger" }]);
60
+ expect(lc2Buffer.length).toBe(1);
61
+ expect(JSON.parse(new TextDecoder().decode(lc2Buffer[0]))).toEqual({
62
+ level: "error",
63
+ msg: "should been shown in console",
64
+ module: "MockLogger",
65
+ });
66
+ });
67
+ });
@@ -0,0 +1,92 @@
1
+ import { utils } from "@adviser/cement";
2
+ import { receiveFromStream, sendToStream, streamingTestState } from "./stream-test-helper.js";
3
+
4
+ it("rechunk empty", async () => {
5
+ const chunks = await utils.rebufferArray([], 10);
6
+ expect(chunks.length).toEqual(0);
7
+ });
8
+
9
+ it("rechunk 0 size", async () => {
10
+ const chunks = await utils.rebufferArray([new Uint8Array(0)], 10);
11
+ expect(chunks.length).toEqual(0);
12
+ });
13
+
14
+ it("rechunk smaller 10", async () => {
15
+ const chunks = await utils.rebufferArray([new Uint8Array(3)], 10);
16
+ expect(chunks.length).toEqual(1);
17
+ expect(chunks[0].length).toEqual(3);
18
+ });
19
+
20
+ it("rechunk smaller 10 pack smaller chunks", async () => {
21
+ const chunks = await utils.rebufferArray(
22
+ Array(7)
23
+ .fill(0)
24
+ .map((_, i) => {
25
+ const o = new Uint8Array(3);
26
+ for (let j = 0; j < o.length; j++) {
27
+ o[j] = i * o.length + j;
28
+ }
29
+ return o;
30
+ }),
31
+ 10,
32
+ );
33
+ expect(chunks.length).toEqual(3);
34
+ expect(chunks[0].length).toEqual(10);
35
+ expect(Array.from(chunks[0]).map((i) => i)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
36
+ expect(chunks[1].length).toEqual(10);
37
+ expect(Array.from(chunks[1]).map((i) => i)).toEqual([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]);
38
+ expect(chunks[2].length).toEqual(1);
39
+ expect(Array.from(chunks[2]).map((i) => i)).toEqual([20]);
40
+ });
41
+
42
+ it("rechunk smaller 10 pack bigger chunks", async () => {
43
+ const chunks = await utils.rebufferArray(
44
+ Array(3)
45
+ .fill(0)
46
+ .map((_, i) => {
47
+ const o = new Uint8Array(11);
48
+ for (let j = 0; j < o.length; j++) {
49
+ o[j] = i * o.length + j;
50
+ }
51
+ return o;
52
+ }),
53
+ 10,
54
+ );
55
+ expect(chunks.length).toEqual(4);
56
+ expect(chunks[0].length).toEqual(10);
57
+ expect(Array.from(chunks[0]).map((i) => i)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
58
+ expect(chunks[1].length).toEqual(10);
59
+ expect(Array.from(chunks[1]).map((i) => i)).toEqual([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]);
60
+ expect(chunks[2].length).toEqual(10);
61
+ expect(Array.from(chunks[2]).map((i) => i)).toEqual([20, 21, 22, 23, 24, 25, 26, 27, 28, 29]);
62
+ expect(chunks[3].length).toEqual(3);
63
+ expect(Array.from(chunks[3]).map((i) => i)).toEqual([30, 31, 32]);
64
+ });
65
+
66
+ describe("test streaming through rebuffer", () => {
67
+ const state: streamingTestState = {
68
+ sendChunks: 10000,
69
+ sendChunkSize: 3,
70
+ fillCalls: 0,
71
+ CollectorFn: vitest.fn(),
72
+ };
73
+ const reBufferSize = 11;
74
+
75
+ it("does rebuffer respect backpressure", async () => {
76
+ const ts = new TransformStream<Uint8Array, Uint8Array>(undefined, undefined, { highWaterMark: 2 });
77
+ const reb = utils.rebuffer(ts.readable, reBufferSize);
78
+ await Promise.all([receiveFromStream(reb, state), sendToStream(ts.writable, state)]);
79
+
80
+ expect(state.CollectorFn).toBeCalledTimes(~~((state.sendChunkSize * state.sendChunks) / reBufferSize) + 1 + 1 /*done*/);
81
+ expect(state.CollectorFn.mock.calls.slice(-1)[0][0].done).toBeTruthy();
82
+ let lastfillCalls = 0;
83
+ for (let i = 0; i < state.CollectorFn.mock.calls.length - 1 /*done*/; i++) {
84
+ const { fillCalls, reBufferCalls, value } = state.CollectorFn.mock.calls[i][0];
85
+ expect(value?.[0]).toBe(~~((reBufferSize * i) / state.sendChunkSize) % 256);
86
+ expect(fillCalls * state.sendChunkSize).toBeGreaterThanOrEqual(
87
+ (fillCalls - lastfillCalls) * state.sendChunkSize + reBufferCalls * reBufferSize,
88
+ );
89
+ lastfillCalls = fillCalls;
90
+ }
91
+ });
92
+ });
@@ -0,0 +1,106 @@
1
+ import { utils } from "@adviser/cement";
2
+ import { receiveFromStream, sendToStream, streamingTestState } from "./stream-test-helper.js";
3
+
4
+ it("array2stream", async () => {
5
+ const as = utils.array2stream([1, 2, 3]);
6
+ let i = 0;
7
+ const reader = as.getReader();
8
+ while (true) {
9
+ const { done, value } = await reader.read();
10
+ if (done) {
11
+ break;
12
+ }
13
+ expect(1 + i++).toBe(value);
14
+ }
15
+ });
16
+
17
+ it("stream2array", async () => {
18
+ const as = await utils.stream2array(
19
+ new ReadableStream({
20
+ start(controller): void {
21
+ controller.enqueue(1);
22
+ controller.enqueue(2);
23
+ controller.enqueue(3);
24
+ controller.close();
25
+ },
26
+ }),
27
+ );
28
+ expect(as).toEqual([1, 2, 3]);
29
+ });
30
+
31
+ it("devnull", async () => {
32
+ const cnt = await utils.devnull(
33
+ utils.streamMap(utils.array2stream([1, 2, 3]), {
34
+ Map: (i, idx) => (idx + 1) * 10 + i + 1,
35
+ }),
36
+ );
37
+ expect(cnt).toBe(3);
38
+ });
39
+
40
+ it("stream_map", async () => {
41
+ const closeFn = vitest.fn();
42
+ const s = await utils.stream2array(
43
+ utils.streamMap(utils.array2stream([1, 2, 3]), {
44
+ Map: (i, idx) => (idx + 1) * 10 + i + 1,
45
+ Close: closeFn,
46
+ }),
47
+ );
48
+ expect(closeFn).toBeCalledTimes(1);
49
+ expect(s).toEqual([12, 23, 34]);
50
+ });
51
+
52
+ it("stream_map async", async () => {
53
+ const closeFn = vitest.fn();
54
+ const s = await utils.stream2array(
55
+ utils.streamMap(utils.array2stream([1, 2, 3]), {
56
+ Map: (i, idx) => Promise.resolve((idx + 1) * 10 + i + 1),
57
+ Close: closeFn,
58
+ }),
59
+ );
60
+ expect(closeFn).toBeCalledTimes(1);
61
+ expect(s).toEqual([12, 23, 34]);
62
+ });
63
+
64
+ it("map types", async () => {
65
+ const oo = await utils.stream2array(
66
+ utils.streamMap(utils.array2stream([1, 2, 3]), {
67
+ Map: (chunk, idx) => {
68
+ return "[" + chunk + "/" + idx + "]";
69
+ },
70
+ }),
71
+ );
72
+ expect(oo).toEqual(["[1/0]", "[2/1]", "[3/2]"]);
73
+ });
74
+
75
+ describe("test streaming through streamMap", () => {
76
+ const state: streamingTestState = {
77
+ sendChunks: 10000,
78
+ sendChunkSize: 3,
79
+ fillCalls: 0,
80
+ CollectorFn: vitest.fn(),
81
+ };
82
+ it("does streamMap respect backpressure", async () => {
83
+ const ts = new TransformStream<Uint8Array, Uint8Array>(undefined, undefined, { highWaterMark: 2 });
84
+ const reb = utils.streamMap(ts.readable, {
85
+ Map: (chunk) => {
86
+ for (let i = 0; i < chunk.length; i++) {
87
+ chunk[i] = (chunk[i] + 1) % 256;
88
+ }
89
+ return chunk;
90
+ },
91
+ });
92
+ await Promise.all([receiveFromStream(reb, state), sendToStream(ts.writable, state)]);
93
+
94
+ expect(state.CollectorFn).toBeCalledTimes(state.sendChunks + 1 /*done*/);
95
+ expect(state.CollectorFn.mock.calls.slice(-1)[0][0].done).toBeTruthy();
96
+ let lastfillCalls = 0;
97
+ for (let i = 0; i < state.CollectorFn.mock.calls.length - 1 /*done*/; i++) {
98
+ const { fillCalls, reBufferCalls, value } = state.CollectorFn.mock.calls[i][0];
99
+ expect(value?.[0]).toBe((i + 1) % 256);
100
+ expect(fillCalls * state.sendChunkSize).toBeGreaterThanOrEqual(
101
+ (fillCalls - lastfillCalls) * state.sendChunkSize + reBufferCalls * state.sendChunkSize,
102
+ );
103
+ lastfillCalls = fillCalls;
104
+ }
105
+ });
106
+ });
@@ -0,0 +1,39 @@
1
+ import { stream2string } from "./stream2string.js";
2
+
3
+ it("stream2string", async () => {
4
+ expect(
5
+ await stream2string(
6
+ new ReadableStream({
7
+ start(controller): void {
8
+ const encoder = new TextEncoder();
9
+ controller.enqueue(encoder.encode("Hello"));
10
+ controller.enqueue(encoder.encode(" "));
11
+ controller.enqueue(encoder.encode("World"));
12
+ controller.enqueue(encoder.encode("!"));
13
+ controller.close();
14
+ },
15
+ }),
16
+ ),
17
+ ).toBe("Hello World!");
18
+ });
19
+
20
+ it("stream2string maxSize", async () => {
21
+ const instr = "Hello World!";
22
+ for (let i = 0; i < instr.length; i++) {
23
+ expect(
24
+ await stream2string(
25
+ new ReadableStream({
26
+ start(controller): void {
27
+ const encoder = new TextEncoder();
28
+ controller.enqueue(encoder.encode("Hello"));
29
+ controller.enqueue(encoder.encode(" "));
30
+ controller.enqueue(encoder.encode("World"));
31
+ controller.enqueue(encoder.encode("!"));
32
+ controller.close();
33
+ },
34
+ }),
35
+ i,
36
+ ),
37
+ ).toBe(instr.slice(0, i));
38
+ }
39
+ });
@@ -0,0 +1,6 @@
1
+ import { utils } from "@adviser/cement";
2
+
3
+ it("string2stream", async () => {
4
+ const inStr = utils.string2stream("Hello World!");
5
+ expect(await utils.stream2string(inStr)).toBe("Hello World!");
6
+ });
package/ts/index.d.ts CHANGED
@@ -19,5 +19,6 @@ export * from "./crypto.js";
19
19
  export * from "./base-sys-abstraction.js";
20
20
  export * from "./bin2text.js";
21
21
  export * from "./version.js";
22
+ export * from "./refcounted.js";
22
23
  export * as utils from "./utils/index.js";
23
24
  //# sourceMappingURL=index.d.ts.map
package/ts/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC"}
package/ts/index.js CHANGED
@@ -19,5 +19,6 @@ export * from "./crypto.js";
19
19
  export * from "./base-sys-abstraction.js";
20
20
  export * from "./bin2text.js";
21
21
  export * from "./version.js";
22
+ export * from "./refcounted.js";
22
23
  export * as utils from "./utils/index.js";
23
24
  //# sourceMappingURL=index.js.map
package/ts/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC"}
@@ -42,15 +42,11 @@ describe("node_sys", () => {
42
42
  let fnExec;
43
43
  let execHandler = "tsx src/test/test-exit-handler.ts";
44
44
  beforeAll(async () => {
45
+ const { exec } = await import("node:child_process");
46
+ fnExec = exec;
45
47
  if (runtimeFn().isDeno) {
46
- const { exec } = await import("child_process");
47
- fnExec = exec;
48
48
  execHandler = "deno run --allow-net --allow-read --allow-run --unstable-sloppy-imports src/test/test-exit-handler.ts";
49
49
  }
50
- else {
51
- const { exec } = await import("child_process");
52
- fnExec = exec;
53
- }
54
50
  });
55
51
  it("just-exit", () => {
56
52
  return new Promise((done) => {
@@ -1 +1 @@
1
- {"version":3,"file":"node-sys-abstraction.test.js","sourceRoot":"","sources":["../../../src/node/node-sys-abstraction.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node-sys-abstraction.test.js","sourceRoot":"","sources":["../../../src/node/node-sys-abstraction.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function wrapRefcounted<T, M extends string>(t: T, method: M): T;
2
+ //# sourceMappingURL=refcounted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refcounted.d.ts","sourceRoot":"","sources":["../../src/refcounted.ts"],"names":[],"mappings":"AAKA,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAiBtE"}
@@ -0,0 +1,19 @@
1
+ export function wrapRefcounted(t, method) {
2
+ const my = t;
3
+ my.__refcounted = (my.__refcounted || 0) + 1;
4
+ if (my.__refcounted === 1) {
5
+ my.__unrefcounted = my[method];
6
+ const mRec = my;
7
+ mRec[method] = function () {
8
+ this.__refcounted--;
9
+ if (this.__refcounted === 0) {
10
+ this.__unrefcounted();
11
+ }
12
+ if (this.__refcounted < 0) {
13
+ throw new Error("already closed");
14
+ }
15
+ };
16
+ }
17
+ return t;
18
+ }
19
+ //# sourceMappingURL=refcounted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refcounted.js","sourceRoot":"","sources":["../../src/refcounted.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,cAAc,CAAsB,CAAI,EAAE,MAAS;IACjE,MAAM,EAAE,GAAG,CAAqB,CAAC;IACjC,EAAE,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,EAAE,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;QAC1B,EAAE,CAAC,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,EAAgC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,GAAG;YACb,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,CAAC;YACD,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=refcounted.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refcounted.test.d.ts","sourceRoot":"","sources":["../../src/refcounted.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,39 @@
1
+ import { wrapRefcounted } from "./refcounted.js";
2
+ class RealInstance {
3
+ constructor(x) {
4
+ this.isOpen = true;
5
+ this.x = x;
6
+ }
7
+ wurst() {
8
+ return this.x++;
9
+ }
10
+ close() {
11
+ if (!this.isOpen) {
12
+ throw new Error("already closed");
13
+ }
14
+ this.isOpen = false;
15
+ }
16
+ }
17
+ it("simple", () => {
18
+ const obj = wrapRefcounted(new RealInstance(42), "close");
19
+ expect(obj.wurst()).toBe(42);
20
+ obj.close();
21
+ expect(() => obj.close()).toThrowError("already closed");
22
+ });
23
+ it("nested", () => {
24
+ const ri = new RealInstance(42);
25
+ const obj1 = wrapRefcounted(ri, "close");
26
+ const obj2 = wrapRefcounted(ri, "close");
27
+ expect(obj1).toBe(obj2);
28
+ expect(obj1.wurst()).toBe(42);
29
+ expect(obj2.wurst()).toBe(43);
30
+ obj2.close();
31
+ expect(obj2.isOpen).toBe(true);
32
+ expect(obj2.wurst()).toBe(44);
33
+ expect(obj1.wurst()).toBe(45);
34
+ obj1.close();
35
+ expect(obj1.wurst()).toBe(46);
36
+ expect(obj2.isOpen).toBe(false);
37
+ expect(() => obj2.close()).toThrowError("already closed");
38
+ });
39
+ //# sourceMappingURL=refcounted.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refcounted.test.js","sourceRoot":"","sources":["../../src/refcounted.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,YAAY;IAGhB,YAAY,CAAS;QADrB,WAAM,GAAG,IAAI,CAAC;QAEZ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IACD,KAAK;QACH,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;IAClB,CAAC;IACD,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;CACF;AAED,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IAChB,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7B,GAAG,CAAC,KAAK,EAAE,CAAC;IACZ,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IAChB,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,EAAE,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;AAC5D,CAAC,CAAC,CAAC"}
File without changes
File without changes