@backstage/backend-dev-utils 0.1.5 → 0.1.6

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @backstage/backend-dev-utils
2
2
 
3
+ ## 0.1.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 2bae83a: Internal update for Node.js v24 support.
8
+
9
+ ## 0.1.6-next.0
10
+
11
+ ### Patch Changes
12
+
13
+ - 2bae83a: Internal update for Node.js v24 support.
14
+
3
15
  ## 0.1.5
4
16
 
5
17
  ### Patch Changes
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var ipcClient = require('./ipcClient.cjs.js');
4
+
5
+ class DevDataStore {
6
+ static #instance;
7
+ /**
8
+ * Tries to acquire a DevDataStore instance. This will only succeed when the backend
9
+ * process is being run through the `@backstage/cli` in development mode.
10
+ *
11
+ * @returns A DevDataStore instance, or undefined if not available.
12
+ */
13
+ static get() {
14
+ if (ipcClient.ipcClient) {
15
+ if (!this.#instance) {
16
+ this.#instance = new DevDataStore(ipcClient.ipcClient);
17
+ }
18
+ return this.#instance;
19
+ }
20
+ return void 0;
21
+ }
22
+ /** @internal */
23
+ static forTest(client) {
24
+ return new DevDataStore(client);
25
+ }
26
+ #client;
27
+ constructor(client) {
28
+ this.#client = client;
29
+ }
30
+ /**
31
+ * Save data to the data store.
32
+ *
33
+ * @param key - The key used to identify the data.
34
+ * @param data - The data to save. The data will be serialized using advanced IPC serialization.
35
+ * @returns A promise that resolves to a result object that indicates whether the data was saved.
36
+ */
37
+ async save(key, data) {
38
+ return this.#client.request(
39
+ "DevDataStore.save",
40
+ { key, data }
41
+ );
42
+ }
43
+ /**
44
+ * Loads data from the data store.
45
+ *
46
+ * @param key - The key used to identify the data.
47
+ * @returns A promise that resolves to a result object that indicates whether the data was loaded, as well as the data.
48
+ */
49
+ async load(key) {
50
+ const result = await this.#client.request(
51
+ "DevDataStore.load",
52
+ { key }
53
+ );
54
+ return result;
55
+ }
56
+ }
57
+
58
+ exports.DevDataStore = DevDataStore;
59
+ //# sourceMappingURL=DevDataStore.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DevDataStore.cjs.js","sources":["../src/DevDataStore.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackstageIpcClient, ipcClient } from './ipcClient';\n\ninterface SaveRequest {\n key: string;\n data: unknown;\n}\n\ninterface SaveResponse {\n saved: boolean;\n}\n\ninterface LoadRequest {\n key: string;\n}\n\ninterface LoadResponse {\n loaded: boolean;\n data: unknown;\n}\n\n/**\n * A data store that can be used to store temporary data during development.\n *\n * @public\n */\nexport class DevDataStore {\n static #instance?: DevDataStore;\n\n /**\n * Tries to acquire a DevDataStore instance. This will only succeed when the backend\n * process is being run through the `@backstage/cli` in development mode.\n *\n * @returns A DevDataStore instance, or undefined if not available.\n */\n static get(): DevDataStore | undefined {\n if (ipcClient) {\n if (!this.#instance) {\n this.#instance = new DevDataStore(ipcClient);\n }\n return this.#instance;\n }\n return undefined;\n }\n\n /** @internal */\n static forTest(client: Pick<BackstageIpcClient, 'request'>): DevDataStore {\n return new DevDataStore(client as BackstageIpcClient);\n }\n\n #client: BackstageIpcClient;\n\n private constructor(client: BackstageIpcClient) {\n this.#client = client;\n }\n\n /**\n * Save data to the data store.\n *\n * @param key - The key used to identify the data.\n * @param data - The data to save. The data will be serialized using advanced IPC serialization.\n * @returns A promise that resolves to a result object that indicates whether the data was saved.\n */\n async save<T>(key: string, data: T): Promise<{ saved: boolean }> {\n return this.#client.request<SaveRequest, SaveResponse>(\n 'DevDataStore.save',\n { key, data },\n );\n }\n\n /**\n * Loads data from the data store.\n *\n * @param key - The key used to identify the data.\n * @returns A promise that resolves to a result object that indicates whether the data was loaded, as well as the data.\n */\n async load<T>(key: string): Promise<{ loaded: boolean; data: T }> {\n const result = await this.#client.request<LoadRequest, LoadResponse>(\n 'DevDataStore.load',\n { key },\n );\n return result as { loaded: boolean; data: T };\n }\n}\n"],"names":["ipcClient"],"mappings":";;;;AAyCO,MAAM,YAAA,CAAa;AAAA,EACxB,OAAO,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQP,OAAO,GAAA,GAAgC;AACrC,IAAA,IAAIA,mBAAA,EAAW;AACb,MAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,QAAA,IAAA,CAAK,SAAA,GAAY,IAAI,YAAA,CAAaA,mBAAS,CAAA;AAAA,MAC7C;AACA,MAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACd;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,QAAQ,MAAA,EAA2D;AACxE,IAAA,OAAO,IAAI,aAAa,MAA4B,CAAA;AAAA,EACtD;AAAA,EAEA,OAAA;AAAA,EAEQ,YAAY,MAAA,EAA4B;AAC9C,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CAAQ,GAAA,EAAa,IAAA,EAAsC;AAC/D,IAAA,OAAO,KAAK,OAAA,CAAQ,OAAA;AAAA,MAClB,mBAAA;AAAA,MACA,EAAE,KAAK,IAAA;AAAK,KACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAQ,GAAA,EAAoD;AAChE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA;AAAA,MAChC,mBAAA;AAAA,MACA,EAAE,GAAA;AAAI,KACR;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;;"}
package/dist/index.cjs.js CHANGED
@@ -1,130 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const requestType = "@backstage/cli/channel/request";
4
- const responseType = "@backstage/cli/channel/response";
5
- const IPC_TIMEOUT_MS = 5e3;
6
- class BackstageIpcClient {
7
- #messageId = 0;
8
- #sendMessage;
9
- #handlers = /* @__PURE__ */ new Map();
10
- /**
11
- * Creates a new client if we're in a child process with IPC and BACKSTAGE_CLI_CHANNEL is set.
12
- */
13
- static create() {
14
- const sendMessage = process.send?.bind(process);
15
- const client = sendMessage && process.env.BACKSTAGE_CLI_CHANNEL ? new BackstageIpcClient(sendMessage) : void 0;
16
- if (client) {
17
- process.on(
18
- "message",
19
- (message, _sendHandle) => client.handleMessage(message, _sendHandle)
20
- );
21
- }
22
- return client;
23
- }
24
- constructor(sendMessage) {
25
- this.#sendMessage = sendMessage;
26
- }
27
- handleMessage(message, _sendHandle) {
28
- const isResponse = (msg) => msg?.type === responseType;
29
- if (isResponse(message)) {
30
- this.#handlers.get(message.id)?.(message);
31
- }
32
- }
33
- /**
34
- * Send a request to the parent process and wait for a response.
35
- */
36
- async request(method, body) {
37
- return new Promise((resolve, reject) => {
38
- const id = this.#messageId++;
39
- const request = {
40
- type: requestType,
41
- id,
42
- method,
43
- body
44
- };
45
- let timeout = void 0;
46
- const responseHandler = (response) => {
47
- clearTimeout(timeout);
48
- timeout = void 0;
49
- this.#handlers.delete(id);
50
- if ("error" in response) {
51
- const error = new Error(response.error.message);
52
- if (response.error.name) {
53
- error.name = response.error.name;
54
- }
55
- reject(error);
56
- } else {
57
- resolve(response.body);
58
- }
59
- };
60
- timeout = setTimeout(() => {
61
- reject(new Error(`IPC request '${method}' with ID ${id} timed out`));
62
- this.#handlers.delete(id);
63
- }, IPC_TIMEOUT_MS);
64
- timeout.unref();
65
- this.#handlers.set(id, responseHandler);
66
- this.#sendMessage(request, (e) => {
67
- if (e) {
68
- reject(e);
69
- }
70
- });
71
- });
72
- }
73
- }
74
- const ipcClient = BackstageIpcClient.create();
3
+ var DevDataStore = require('./DevDataStore.cjs.js');
75
4
 
76
- class DevDataStore {
77
- static #instance;
78
- /**
79
- * Tries to acquire a DevDataStore instance. This will only succeed when the backend
80
- * process is being run through the `@backstage/cli` in development mode.
81
- *
82
- * @returns A DevDataStore instance, or undefined if not available.
83
- */
84
- static get() {
85
- if (ipcClient) {
86
- if (!this.#instance) {
87
- this.#instance = new DevDataStore(ipcClient);
88
- }
89
- return this.#instance;
90
- }
91
- return void 0;
92
- }
93
- /** @internal */
94
- static forTest(client) {
95
- return new DevDataStore(client);
96
- }
97
- #client;
98
- constructor(client) {
99
- this.#client = client;
100
- }
101
- /**
102
- * Save data to the data store.
103
- *
104
- * @param key - The key used to identify the data.
105
- * @param data - The data to save. The data will be serialized using advanced IPC serialization.
106
- * @returns A promise that resolves to a result object that indicates whether the data was saved.
107
- */
108
- async save(key, data) {
109
- return this.#client.request(
110
- "DevDataStore.save",
111
- { key, data }
112
- );
113
- }
114
- /**
115
- * Loads data from the data store.
116
- *
117
- * @param key - The key used to identify the data.
118
- * @returns A promise that resolves to a result object that indicates whether the data was loaded, as well as the data.
119
- */
120
- async load(key) {
121
- const result = await this.#client.request(
122
- "DevDataStore.load",
123
- { key }
124
- );
125
- return result;
126
- }
127
- }
128
5
 
129
- exports.DevDataStore = DevDataStore;
6
+
7
+ exports.DevDataStore = DevDataStore.DevDataStore;
130
8
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/ipcClient.ts","../src/DevDataStore.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype SendMessage = Exclude<typeof process.send, undefined>;\n\ninterface Request {\n id: number;\n method: string;\n body: unknown;\n type: string;\n}\n\ntype Response =\n | {\n type: string;\n id: number;\n body: unknown;\n }\n | {\n type: string;\n id: number;\n error: Error;\n };\n\ntype ResponseHandler = (response: Response) => void;\n\nconst requestType = '@backstage/cli/channel/request';\nconst responseType = '@backstage/cli/channel/response';\n\nconst IPC_TIMEOUT_MS = 5000;\n\n/**\n * The client side of an IPC communication channel.\n *\n * @internal\n */\nexport class BackstageIpcClient {\n #messageId = 0;\n #sendMessage: SendMessage;\n #handlers: Map<number, ResponseHandler> = new Map();\n\n /**\n * Creates a new client if we're in a child process with IPC and BACKSTAGE_CLI_CHANNEL is set.\n */\n static create(): BackstageIpcClient | undefined {\n const sendMessage = process.send?.bind(process);\n const client =\n sendMessage && process.env.BACKSTAGE_CLI_CHANNEL\n ? new BackstageIpcClient(sendMessage)\n : undefined;\n\n if (client) {\n process.on('message', (message, _sendHandle) =>\n client.handleMessage(message, _sendHandle),\n );\n }\n\n return client;\n }\n\n constructor(sendMessage: SendMessage) {\n this.#sendMessage = sendMessage;\n }\n\n private handleMessage(message: unknown, _sendHandle: unknown) {\n const isResponse = (msg: unknown): msg is Response =>\n (msg as Response)?.type === responseType;\n\n if (isResponse(message)) {\n this.#handlers.get(message.id)?.(message);\n }\n }\n\n /**\n * Send a request to the parent process and wait for a response.\n */\n async request<TRequestBody, TResponseBody>(\n method: string,\n body: TRequestBody,\n ): Promise<TResponseBody> {\n return new Promise((resolve, reject) => {\n const id = this.#messageId++;\n\n const request: Request = {\n type: requestType,\n id,\n method,\n body,\n };\n\n let timeout: NodeJS.Timeout | undefined = undefined;\n\n const responseHandler: ResponseHandler = (response: Response) => {\n clearTimeout(timeout);\n timeout = undefined;\n this.#handlers.delete(id);\n\n if ('error' in response) {\n const error = new Error(response.error.message);\n if (response.error.name) {\n error.name = response.error.name;\n }\n reject(error);\n } else {\n resolve(response.body as TResponseBody);\n }\n };\n\n timeout = setTimeout(() => {\n reject(new Error(`IPC request '${method}' with ID ${id} timed out`));\n this.#handlers.delete(id);\n }, IPC_TIMEOUT_MS);\n timeout.unref();\n\n this.#handlers.set(id, responseHandler);\n this.#sendMessage(request, (e: Error) => {\n if (e) {\n reject(e);\n }\n });\n });\n }\n}\n\nexport const ipcClient = BackstageIpcClient.create();\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { BackstageIpcClient, ipcClient } from './ipcClient';\n\ninterface SaveRequest {\n key: string;\n data: unknown;\n}\n\ninterface SaveResponse {\n saved: boolean;\n}\n\ninterface LoadRequest {\n key: string;\n}\n\ninterface LoadResponse {\n loaded: boolean;\n data: unknown;\n}\n\n/**\n * A data store that can be used to store temporary data during development.\n *\n * @public\n */\nexport class DevDataStore {\n static #instance?: DevDataStore;\n\n /**\n * Tries to acquire a DevDataStore instance. This will only succeed when the backend\n * process is being run through the `@backstage/cli` in development mode.\n *\n * @returns A DevDataStore instance, or undefined if not available.\n */\n static get(): DevDataStore | undefined {\n if (ipcClient) {\n if (!this.#instance) {\n this.#instance = new DevDataStore(ipcClient);\n }\n return this.#instance;\n }\n return undefined;\n }\n\n /** @internal */\n static forTest(client: Pick<BackstageIpcClient, 'request'>): DevDataStore {\n return new DevDataStore(client as BackstageIpcClient);\n }\n\n #client: BackstageIpcClient;\n\n private constructor(client: BackstageIpcClient) {\n this.#client = client;\n }\n\n /**\n * Save data to the data store.\n *\n * @param key - The key used to identify the data.\n * @param data - The data to save. The data will be serialized using advanced IPC serialization.\n * @returns A promise that resolves to a result object that indicates whether the data was saved.\n */\n async save<T>(key: string, data: T): Promise<{ saved: boolean }> {\n return this.#client.request<SaveRequest, SaveResponse>(\n 'DevDataStore.save',\n { key, data },\n );\n }\n\n /**\n * Loads data from the data store.\n *\n * @param key - The key used to identify the data.\n * @returns A promise that resolves to a result object that indicates whether the data was loaded, as well as the data.\n */\n async load<T>(key: string): Promise<{ loaded: boolean; data: T }> {\n const result = await this.#client.request<LoadRequest, LoadResponse>(\n 'DevDataStore.load',\n { key },\n );\n return result as { loaded: boolean; data: T };\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ const requestType = "@backstage/cli/channel/request";
4
+ const responseType = "@backstage/cli/channel/response";
5
+ const IPC_TIMEOUT_MS = 5e3;
6
+ class BackstageIpcClient {
7
+ #messageId = 0;
8
+ #sendMessage;
9
+ #handlers = /* @__PURE__ */ new Map();
10
+ /**
11
+ * Creates a new client if we're in a child process with IPC and BACKSTAGE_CLI_CHANNEL is set.
12
+ */
13
+ static create() {
14
+ const sendMessage = process.send?.bind(process);
15
+ const client = sendMessage && process.env.BACKSTAGE_CLI_CHANNEL ? new BackstageIpcClient(sendMessage) : void 0;
16
+ if (client) {
17
+ process.on(
18
+ "message",
19
+ (message, _sendHandle) => client.handleMessage(message, _sendHandle)
20
+ );
21
+ }
22
+ return client;
23
+ }
24
+ constructor(sendMessage) {
25
+ this.#sendMessage = sendMessage;
26
+ }
27
+ handleMessage(message, _sendHandle) {
28
+ const isResponse = (msg) => msg?.type === responseType;
29
+ if (isResponse(message)) {
30
+ this.#handlers.get(message.id)?.(message);
31
+ }
32
+ }
33
+ /**
34
+ * Send a request to the parent process and wait for a response.
35
+ */
36
+ async request(method, body) {
37
+ return new Promise((resolve, reject) => {
38
+ const id = this.#messageId++;
39
+ const request = {
40
+ type: requestType,
41
+ id,
42
+ method,
43
+ body
44
+ };
45
+ let timeout = void 0;
46
+ const responseHandler = (response) => {
47
+ clearTimeout(timeout);
48
+ timeout = void 0;
49
+ this.#handlers.delete(id);
50
+ if ("error" in response) {
51
+ const error = new Error(response.error.message);
52
+ if (response.error.name) {
53
+ error.name = response.error.name;
54
+ }
55
+ reject(error);
56
+ } else {
57
+ resolve(response.body);
58
+ }
59
+ };
60
+ timeout = setTimeout(() => {
61
+ reject(new Error(`IPC request '${method}' with ID ${id} timed out`));
62
+ this.#handlers.delete(id);
63
+ }, IPC_TIMEOUT_MS);
64
+ timeout.unref();
65
+ this.#handlers.set(id, responseHandler);
66
+ this.#sendMessage(request, void 0, void 0, (e) => {
67
+ if (e) {
68
+ reject(e);
69
+ }
70
+ });
71
+ });
72
+ }
73
+ }
74
+ const ipcClient = BackstageIpcClient.create();
75
+
76
+ exports.BackstageIpcClient = BackstageIpcClient;
77
+ exports.ipcClient = ipcClient;
78
+ //# sourceMappingURL=ipcClient.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipcClient.cjs.js","sources":["../src/ipcClient.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype SendMessage = Exclude<typeof process.send, undefined>;\n\ninterface Request {\n id: number;\n method: string;\n body: unknown;\n type: string;\n}\n\ntype Response =\n | {\n type: string;\n id: number;\n body: unknown;\n }\n | {\n type: string;\n id: number;\n error: Error;\n };\n\ntype ResponseHandler = (response: Response) => void;\n\nconst requestType = '@backstage/cli/channel/request';\nconst responseType = '@backstage/cli/channel/response';\n\nconst IPC_TIMEOUT_MS = 5000;\n\n/**\n * The client side of an IPC communication channel.\n *\n * @internal\n */\nexport class BackstageIpcClient {\n #messageId = 0;\n #sendMessage: SendMessage;\n #handlers: Map<number, ResponseHandler> = new Map();\n\n /**\n * Creates a new client if we're in a child process with IPC and BACKSTAGE_CLI_CHANNEL is set.\n */\n static create(): BackstageIpcClient | undefined {\n const sendMessage = process.send?.bind(process);\n const client =\n sendMessage && process.env.BACKSTAGE_CLI_CHANNEL\n ? new BackstageIpcClient(sendMessage)\n : undefined;\n\n if (client) {\n process.on('message', (message, _sendHandle) =>\n client.handleMessage(message, _sendHandle),\n );\n }\n\n return client;\n }\n\n constructor(sendMessage: SendMessage) {\n this.#sendMessage = sendMessage;\n }\n\n private handleMessage(message: unknown, _sendHandle: unknown) {\n const isResponse = (msg: unknown): msg is Response =>\n (msg as Response)?.type === responseType;\n\n if (isResponse(message)) {\n this.#handlers.get(message.id)?.(message);\n }\n }\n\n /**\n * Send a request to the parent process and wait for a response.\n */\n async request<TRequestBody, TResponseBody>(\n method: string,\n body: TRequestBody,\n ): Promise<TResponseBody> {\n return new Promise((resolve, reject) => {\n const id = this.#messageId++;\n\n const request: Request = {\n type: requestType,\n id,\n method,\n body,\n };\n\n let timeout: NodeJS.Timeout | undefined = undefined;\n\n const responseHandler: ResponseHandler = (response: Response) => {\n clearTimeout(timeout);\n timeout = undefined;\n this.#handlers.delete(id);\n\n if ('error' in response) {\n const error = new Error(response.error.message);\n if (response.error.name) {\n error.name = response.error.name;\n }\n reject(error);\n } else {\n resolve(response.body as TResponseBody);\n }\n };\n\n timeout = setTimeout(() => {\n reject(new Error(`IPC request '${method}' with ID ${id} timed out`));\n this.#handlers.delete(id);\n }, IPC_TIMEOUT_MS);\n timeout.unref();\n\n this.#handlers.set(id, responseHandler);\n this.#sendMessage(request, undefined, undefined, (e: Error | null) => {\n if (e) {\n reject(e);\n }\n });\n });\n }\n}\n\nexport const ipcClient = BackstageIpcClient.create();\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-dev-utils",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "backstage": {
5
5
  "role": "node-library"
6
6
  },
@@ -31,6 +31,13 @@
31
31
  "test": "backstage-cli package test"
32
32
  },
33
33
  "devDependencies": {
34
- "@backstage/cli": "^0.27.0"
34
+ "@backstage/cli": "^0.35.0"
35
+ },
36
+ "typesVersions": {
37
+ "*": {
38
+ "package.json": [
39
+ "package.json"
40
+ ]
41
+ }
35
42
  }
36
43
  }