@optimystic/db-p2p 0.1.1 → 0.1.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 (64) hide show
  1. package/{readme.md → README.md} +7 -0
  2. package/dist/index.min.js +31 -30
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/cluster/cluster-repo.d.ts +27 -0
  5. package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
  6. package/dist/src/cluster/cluster-repo.js +139 -18
  7. package/dist/src/cluster/cluster-repo.js.map +1 -1
  8. package/dist/src/cluster/service.d.ts +13 -2
  9. package/dist/src/cluster/service.d.ts.map +1 -1
  10. package/dist/src/cluster/service.js +17 -7
  11. package/dist/src/cluster/service.js.map +1 -1
  12. package/dist/src/index.d.ts +1 -1
  13. package/dist/src/index.d.ts.map +1 -1
  14. package/dist/src/index.js +1 -1
  15. package/dist/src/index.js.map +1 -1
  16. package/dist/src/libp2p-node.d.ts +13 -2
  17. package/dist/src/libp2p-node.d.ts.map +1 -1
  18. package/dist/src/libp2p-node.js +35 -16
  19. package/dist/src/libp2p-node.js.map +1 -1
  20. package/dist/src/protocol-client.d.ts.map +1 -1
  21. package/dist/src/protocol-client.js +8 -7
  22. package/dist/src/protocol-client.js.map +1 -1
  23. package/dist/src/repo/cluster-coordinator.d.ts +7 -2
  24. package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
  25. package/dist/src/repo/cluster-coordinator.js +18 -3
  26. package/dist/src/repo/cluster-coordinator.js.map +1 -1
  27. package/dist/src/repo/coordinator-repo.d.ts +26 -3
  28. package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
  29. package/dist/src/repo/coordinator-repo.js +117 -22
  30. package/dist/src/repo/coordinator-repo.js.map +1 -1
  31. package/dist/src/repo/service.d.ts +13 -2
  32. package/dist/src/repo/service.d.ts.map +1 -1
  33. package/dist/src/repo/service.js +25 -12
  34. package/dist/src/repo/service.js.map +1 -1
  35. package/dist/src/storage/memory-storage.d.ts +15 -0
  36. package/dist/src/storage/memory-storage.d.ts.map +1 -1
  37. package/dist/src/storage/memory-storage.js +23 -4
  38. package/dist/src/storage/memory-storage.js.map +1 -1
  39. package/dist/src/storage/storage-repo.d.ts.map +1 -1
  40. package/dist/src/storage/storage-repo.js.map +1 -1
  41. package/dist/src/sync/service.d.ts.map +1 -1
  42. package/dist/src/sync/service.js +7 -2
  43. package/dist/src/sync/service.js.map +1 -1
  44. package/package.json +27 -21
  45. package/src/cluster/cluster-repo.ts +836 -711
  46. package/src/cluster/service.ts +44 -31
  47. package/src/index.ts +1 -1
  48. package/src/libp2p-key-network.ts +334 -334
  49. package/src/libp2p-node.ts +371 -339
  50. package/src/network/network-manager-service.ts +334 -334
  51. package/src/protocol-client.ts +53 -54
  52. package/src/repo/client.ts +112 -112
  53. package/src/repo/cluster-coordinator.ts +613 -592
  54. package/src/repo/coordinator-repo.ts +269 -137
  55. package/src/repo/service.ts +237 -219
  56. package/src/storage/block-storage.ts +182 -182
  57. package/src/storage/memory-storage.ts +24 -5
  58. package/src/storage/storage-repo.ts +321 -320
  59. package/src/sync/service.ts +7 -6
  60. package/dist/src/storage/file-storage.d.ts +0 -30
  61. package/dist/src/storage/file-storage.d.ts.map +0 -1
  62. package/dist/src/storage/file-storage.js +0 -127
  63. package/dist/src/storage/file-storage.js.map +0 -1
  64. package/src/storage/file-storage.ts +0 -163
@@ -132,8 +132,9 @@ export class SyncService implements Startable {
132
132
  private async readRequest(stream: Stream): Promise<SyncRequest> {
133
133
  const messages: Uint8Array[] = [];
134
134
 
135
+ // Stream is now directly AsyncIterable in libp2p v3
135
136
  await pipe(
136
- stream.source,
137
+ stream,
137
138
  lp.decode,
138
139
  async (source) => {
139
140
  for await (const msg of source) {
@@ -157,11 +158,11 @@ export class SyncService implements Startable {
157
158
  const json = JSON.stringify(response);
158
159
  const bytes = u8FromString(json, 'utf8');
159
160
 
160
- await pipe(
161
- [bytes],
162
- lp.encode,
163
- stream.sink
164
- );
161
+ // Use stream.send() instead of piping to stream.sink in libp2p v3
162
+ const encoded = pipe([bytes], lp.encode);
163
+ for await (const chunk of encoded) {
164
+ stream.send(chunk);
165
+ }
165
166
  }
166
167
 
167
168
  /**
@@ -1,30 +0,0 @@
1
- import type { BlockId, IBlock, Transform, ActionId, ActionRev } from "@optimystic/db-core";
2
- import type { BlockMetadata } from "./struct.js";
3
- import type { IRawStorage } from "./i-raw-storage.js";
4
- export declare class FileRawStorage implements IRawStorage {
5
- private readonly basePath;
6
- constructor(basePath: string);
7
- getMetadata(blockId: BlockId): Promise<BlockMetadata | undefined>;
8
- saveMetadata(blockId: BlockId, metadata: BlockMetadata): Promise<void>;
9
- getRevision(blockId: BlockId, rev: number): Promise<ActionId | undefined>;
10
- saveRevision(blockId: BlockId, rev: number, actionId: ActionId): Promise<void>;
11
- getPendingTransaction(blockId: BlockId, actionId: ActionId): Promise<Transform | undefined>;
12
- savePendingTransaction(blockId: BlockId, actionId: ActionId, transform: Transform): Promise<void>;
13
- deletePendingTransaction(blockId: BlockId, actionId: ActionId): Promise<void>;
14
- listPendingTransactions(blockId: BlockId): AsyncIterable<ActionId>;
15
- getTransaction(blockId: BlockId, actionId: ActionId): Promise<Transform | undefined>;
16
- listRevisions(blockId: BlockId, startRev: number, endRev: number): AsyncIterable<ActionRev>;
17
- saveTransaction(blockId: BlockId, actionId: ActionId, transform: Transform): Promise<void>;
18
- getMaterializedBlock(blockId: BlockId, actionId: ActionId): Promise<IBlock | undefined>;
19
- saveMaterializedBlock(blockId: BlockId, actionId: ActionId, block?: IBlock): Promise<void>;
20
- promotePendingTransaction(blockId: BlockId, actionId: ActionId): Promise<void>;
21
- private getBlockPath;
22
- private getMetadataPath;
23
- private getRevisionPath;
24
- private getPendingActionPath;
25
- private getActionPath;
26
- private getMaterializedPath;
27
- private readIfExists;
28
- private ensureAndWriteFile;
29
- }
30
- //# sourceMappingURL=file-storage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/file-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKtD,qBAAa,cAAe,YAAW,WAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,MAAM;IAIvC,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAIjE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtE,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAIzE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9E,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAI3F,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjG,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IAYnE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAInF,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC;IAU5F,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1F,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIvF,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe1F,yBAAyB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBpF,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,mBAAmB;YAIb,YAAY;YASZ,kBAAkB;CAIhC"}
@@ -1,127 +0,0 @@
1
- import { promises as fs } from 'fs';
2
- import * as path from 'path';
3
- import { createLogger } from '../logger.js';
4
- const log = createLogger('storage:file');
5
- export class FileRawStorage {
6
- basePath;
7
- constructor(basePath) {
8
- this.basePath = basePath;
9
- // TODO: use https://www.npmjs.com/package/proper-lockfile to take a lock on the basePath, also introduce explicit dispose pattern
10
- }
11
- async getMetadata(blockId) {
12
- return this.readIfExists(this.getMetadataPath(blockId));
13
- }
14
- async saveMetadata(blockId, metadata) {
15
- await this.ensureAndWriteFile(this.getMetadataPath(blockId), JSON.stringify(metadata));
16
- }
17
- async getRevision(blockId, rev) {
18
- return this.readIfExists(this.getRevisionPath(blockId, rev));
19
- }
20
- async saveRevision(blockId, rev, actionId) {
21
- await this.ensureAndWriteFile(this.getRevisionPath(blockId, rev), actionId);
22
- }
23
- async getPendingTransaction(blockId, actionId) {
24
- return this.readIfExists(this.getPendingActionPath(blockId, actionId));
25
- }
26
- async savePendingTransaction(blockId, actionId, transform) {
27
- await this.ensureAndWriteFile(this.getPendingActionPath(blockId, actionId), JSON.stringify(transform));
28
- }
29
- async deletePendingTransaction(blockId, actionId) {
30
- const pendingPath = this.getPendingActionPath(blockId, actionId);
31
- await fs.unlink(pendingPath)
32
- .catch((err) => {
33
- // Ignore if file doesn't exist
34
- if (err?.code !== 'ENOENT')
35
- log('deletePendingTransaction unlink failed for %s/%s - %o', blockId, actionId, err);
36
- });
37
- }
38
- async *listPendingTransactions(blockId) {
39
- const pendingPath = path.join(this.getBlockPath(blockId), 'pend');
40
- const files = await fs.readdir(pendingPath).catch((err) => { log('listPendingTransactions readdir failed for %s - %o', blockId, err); return []; });
41
- for (const file of files) {
42
- if (!file.endsWith('.json'))
43
- continue;
44
- const rawActionId = file.slice(0, -5);
45
- if (!/^[\w\d]+-[\w\d]+-[\w\d]+-[\w\d]+-[\w\d]+$/.test(rawActionId))
46
- continue;
47
- yield rawActionId;
48
- }
49
- }
50
- async getTransaction(blockId, actionId) {
51
- return this.readIfExists(this.getActionPath(blockId, actionId));
52
- }
53
- async *listRevisions(blockId, startRev, endRev) {
54
- // TODO: Optimize this for sparse revs
55
- for (let rev = startRev; startRev <= endRev ? rev <= endRev : rev >= endRev; startRev <= endRev ? ++rev : --rev) {
56
- const actionId = await this.getRevision(blockId, rev);
57
- if (actionId) {
58
- yield { actionId, rev };
59
- }
60
- }
61
- }
62
- async saveTransaction(blockId, actionId, transform) {
63
- await this.ensureAndWriteFile(this.getActionPath(blockId, actionId), JSON.stringify(transform));
64
- }
65
- async getMaterializedBlock(blockId, actionId) {
66
- return this.readIfExists(this.getMaterializedPath(blockId, actionId));
67
- }
68
- async saveMaterializedBlock(blockId, actionId, block) {
69
- if (block) {
70
- await this.ensureAndWriteFile(this.getMaterializedPath(blockId, actionId), JSON.stringify(block));
71
- }
72
- else {
73
- await fs.unlink(this.getMaterializedPath(blockId, actionId))
74
- .catch((err) => {
75
- // Ignore if file doesn't exist
76
- if (err?.code !== 'ENOENT')
77
- log('saveMaterializedBlock unlink failed for %s/%s - %o', blockId, actionId, err);
78
- });
79
- }
80
- }
81
- async promotePendingTransaction(blockId, actionId) {
82
- const pendingPath = this.getPendingActionPath(blockId, actionId);
83
- const actionPath = this.getActionPath(blockId, actionId);
84
- // Ensure target directory exists
85
- await fs.mkdir(path.dirname(actionPath), { recursive: true });
86
- return fs.rename(pendingPath, actionPath)
87
- .catch(err => {
88
- if (err.code === 'ENOENT') {
89
- throw new Error(`Pending action ${actionId} not found for block ${blockId}`);
90
- }
91
- log('promotePendingTransaction rename failed for %s/%s - %o', blockId, actionId, err);
92
- throw err;
93
- });
94
- }
95
- getBlockPath(blockId) {
96
- return path.join(this.basePath, blockId);
97
- }
98
- getMetadataPath(blockId) {
99
- return path.join(this.getBlockPath(blockId), 'meta.json');
100
- }
101
- getRevisionPath(blockId, rev) {
102
- return path.join(this.getBlockPath(blockId), 'revs', `${rev}.json`);
103
- }
104
- getPendingActionPath(blockId, actionId) {
105
- return path.join(this.getBlockPath(blockId), 'pend', `${actionId}.json`);
106
- }
107
- getActionPath(blockId, actionId) {
108
- return path.join(this.getBlockPath(blockId), 'actions', `${actionId}.json`);
109
- }
110
- getMaterializedPath(blockId, actionId) {
111
- return path.join(this.getBlockPath(blockId), 'blocks', `${actionId}.json`);
112
- }
113
- async readIfExists(filePath) {
114
- return fs.readFile(filePath, 'utf-8')
115
- .then(content => JSON.parse(content))
116
- .catch(err => {
117
- if (err.code === 'ENOENT')
118
- return undefined;
119
- throw err;
120
- });
121
- }
122
- async ensureAndWriteFile(filePath, content) {
123
- await fs.mkdir(path.dirname(filePath), { recursive: true });
124
- await fs.writeFile(filePath, content);
125
- }
126
- }
127
- //# sourceMappingURL=file-storage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-storage.js","sourceRoot":"","sources":["../../../src/storage/file-storage.ts"],"names":[],"mappings":"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"}
@@ -1,163 +0,0 @@
1
- import { promises as fs } from 'fs';
2
- import * as path from 'path';
3
- import type { BlockId, IBlock, Transform, ActionId, ActionRev } from "@optimystic/db-core";
4
- import type { BlockMetadata } from "./struct.js";
5
- import type { IRawStorage } from "./i-raw-storage.js";
6
- import { createLogger } from '../logger.js'
7
-
8
- const log = createLogger('storage:file')
9
-
10
- export class FileRawStorage implements IRawStorage {
11
- constructor(private readonly basePath: string) {
12
- // TODO: use https://www.npmjs.com/package/proper-lockfile to take a lock on the basePath, also introduce explicit dispose pattern
13
- }
14
-
15
- async getMetadata(blockId: BlockId): Promise<BlockMetadata | undefined> {
16
- return this.readIfExists<BlockMetadata>(this.getMetadataPath(blockId));
17
- }
18
-
19
- async saveMetadata(blockId: BlockId, metadata: BlockMetadata): Promise<void> {
20
- await this.ensureAndWriteFile(
21
- this.getMetadataPath(blockId),
22
- JSON.stringify(metadata)
23
- );
24
- }
25
-
26
- async getRevision(blockId: BlockId, rev: number): Promise<ActionId | undefined> {
27
- return this.readIfExists<ActionId>(this.getRevisionPath(blockId, rev));
28
- }
29
-
30
- async saveRevision(blockId: BlockId, rev: number, actionId: ActionId): Promise<void> {
31
- await this.ensureAndWriteFile(
32
- this.getRevisionPath(blockId, rev),
33
- actionId
34
- );
35
- }
36
-
37
- async getPendingTransaction(blockId: BlockId, actionId: ActionId): Promise<Transform | undefined> {
38
- return this.readIfExists<Transform>(this.getPendingActionPath(blockId, actionId));
39
- }
40
-
41
- async savePendingTransaction(blockId: BlockId, actionId: ActionId, transform: Transform): Promise<void> {
42
- await this.ensureAndWriteFile(
43
- this.getPendingActionPath(blockId, actionId),
44
- JSON.stringify(transform)
45
- );
46
- }
47
-
48
- async deletePendingTransaction(blockId: BlockId, actionId: ActionId): Promise<void> {
49
- const pendingPath = this.getPendingActionPath(blockId, actionId);
50
- await fs.unlink(pendingPath)
51
- .catch((err) => {
52
- // Ignore if file doesn't exist
53
- if ((err as NodeJS.ErrnoException)?.code !== 'ENOENT') log('deletePendingTransaction unlink failed for %s/%s - %o', blockId, actionId, err)
54
- });
55
- }
56
-
57
- async *listPendingTransactions(blockId: BlockId): AsyncIterable<ActionId> {
58
- const pendingPath = path.join(this.getBlockPath(blockId), 'pend');
59
-
60
- const files = await fs.readdir(pendingPath).catch((err) => { log('listPendingTransactions readdir failed for %s - %o', blockId, err); return [] as string[] });
61
- for (const file of files) {
62
- if (!file.endsWith('.json')) continue;
63
- const rawActionId = file.slice(0, -5);
64
- if (!/^[\w\d]+-[\w\d]+-[\w\d]+-[\w\d]+-[\w\d]+$/.test(rawActionId)) continue;
65
- yield rawActionId as ActionId;
66
- }
67
- }
68
-
69
- async getTransaction(blockId: BlockId, actionId: ActionId): Promise<Transform | undefined> {
70
- return this.readIfExists<Transform>(this.getActionPath(blockId, actionId));
71
- }
72
-
73
- async *listRevisions(blockId: BlockId, startRev: number, endRev: number): AsyncIterable<ActionRev> {
74
- // TODO: Optimize this for sparse revs
75
- for (let rev = startRev; startRev <= endRev ? rev <= endRev : rev >= endRev; startRev <= endRev ? ++rev : --rev) {
76
- const actionId = await this.getRevision(blockId, rev);
77
- if (actionId) {
78
- yield { actionId, rev };
79
- }
80
- }
81
- }
82
-
83
- async saveTransaction(blockId: BlockId, actionId: ActionId, transform: Transform): Promise<void> {
84
- await this.ensureAndWriteFile(
85
- this.getActionPath(blockId, actionId),
86
- JSON.stringify(transform)
87
- );
88
- }
89
-
90
- async getMaterializedBlock(blockId: BlockId, actionId: ActionId): Promise<IBlock | undefined> {
91
- return this.readIfExists<IBlock>(this.getMaterializedPath(blockId, actionId));
92
- }
93
-
94
- async saveMaterializedBlock(blockId: BlockId, actionId: ActionId, block?: IBlock): Promise<void> {
95
- if (block) {
96
- await this.ensureAndWriteFile(
97
- this.getMaterializedPath(blockId, actionId),
98
- JSON.stringify(block)
99
- );
100
- } else {
101
- await fs.unlink(this.getMaterializedPath(blockId, actionId))
102
- .catch((err) => {
103
- // Ignore if file doesn't exist
104
- if ((err as NodeJS.ErrnoException)?.code !== 'ENOENT') log('saveMaterializedBlock unlink failed for %s/%s - %o', blockId, actionId, err)
105
- });
106
- }
107
- }
108
-
109
- async promotePendingTransaction(blockId: BlockId, actionId: ActionId): Promise<void> {
110
- const pendingPath = this.getPendingActionPath(blockId, actionId);
111
- const actionPath = this.getActionPath(blockId, actionId);
112
-
113
- // Ensure target directory exists
114
- await fs.mkdir(path.dirname(actionPath), { recursive: true });
115
-
116
- return fs.rename(pendingPath, actionPath)
117
- .catch(err => {
118
- if (err.code === 'ENOENT') {
119
- throw new Error(`Pending action ${actionId} not found for block ${blockId}`);
120
- }
121
- log('promotePendingTransaction rename failed for %s/%s - %o', blockId, actionId, err)
122
- throw err;
123
- });
124
- }
125
-
126
- private getBlockPath(blockId: BlockId): string {
127
- return path.join(this.basePath, blockId);
128
- }
129
-
130
- private getMetadataPath(blockId: BlockId): string {
131
- return path.join(this.getBlockPath(blockId), 'meta.json');
132
- }
133
-
134
- private getRevisionPath(blockId: BlockId, rev: number): string {
135
- return path.join(this.getBlockPath(blockId), 'revs', `${rev}.json`);
136
- }
137
-
138
- private getPendingActionPath(blockId: BlockId, actionId: ActionId): string {
139
- return path.join(this.getBlockPath(blockId), 'pend', `${actionId}.json`);
140
- }
141
-
142
- private getActionPath(blockId: BlockId, actionId: ActionId): string {
143
- return path.join(this.getBlockPath(blockId), 'actions', `${actionId}.json`);
144
- }
145
-
146
- private getMaterializedPath(blockId: BlockId, actionId: ActionId): string {
147
- return path.join(this.getBlockPath(blockId), 'blocks', `${actionId}.json`);
148
- }
149
-
150
- private async readIfExists<T>(filePath: string): Promise<T | undefined> {
151
- return fs.readFile(filePath, 'utf-8')
152
- .then(content => JSON.parse(content) as T)
153
- .catch(err => {
154
- if (err.code === 'ENOENT') return undefined;
155
- throw err;
156
- });
157
- }
158
-
159
- private async ensureAndWriteFile(filePath: string, content: string): Promise<void> {
160
- await fs.mkdir(path.dirname(filePath), { recursive: true });
161
- await fs.writeFile(filePath, content);
162
- }
163
- }