@tomflow/proflow-dev-tunnel 0.1.21 → 0.1.23
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 +12 -0
- package/dist/deployment/adapter.d.ts +64 -64
- package/dist/deployment/adapter.js +45 -1
- package/dist/deployment/descriptor.d.ts +1 -1
- package/dist/deployment/descriptor.js +1 -1
- package/dist/src/cli-resolver.js +3 -1
- package/dist/src/resource-adapter.js +14 -4
- package/package.json +1 -1
- package/proflow.module.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @tomflow/proflow-dev-tunnel
|
|
2
2
|
|
|
3
|
+
## 0.1.23
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Require live HTTPS ingress readiness before dev-tunnel start reports RUNNING, and clean up the host when readiness fails.
|
|
8
|
+
|
|
9
|
+
## 0.1.22
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Accept Microsoft Dev Tunnel canonical cluster suffixes while preserving the deterministic workspace Tunnel identity.
|
|
14
|
+
|
|
3
15
|
## 0.1.21
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -28,7 +28,7 @@ export declare function createDevTunnelBehaviorAdapter(dependencies?: {
|
|
|
28
28
|
readonly ok: true;
|
|
29
29
|
readonly status: "SUCCEEDED";
|
|
30
30
|
readonly moduleRef: "dev-tunnel";
|
|
31
|
-
readonly moduleVersion: "0.1.
|
|
31
|
+
readonly moduleVersion: "0.1.23";
|
|
32
32
|
};
|
|
33
33
|
observedEffects: never[];
|
|
34
34
|
}>;
|
|
@@ -38,14 +38,14 @@ export declare function createDevTunnelBehaviorAdapter(dependencies?: {
|
|
|
38
38
|
readonly ok: true;
|
|
39
39
|
readonly status: "SUCCEEDED";
|
|
40
40
|
readonly moduleRef: "dev-tunnel";
|
|
41
|
-
readonly moduleVersion: "0.1.
|
|
41
|
+
readonly moduleVersion: "0.1.23";
|
|
42
42
|
};
|
|
43
43
|
observedEffects: string[];
|
|
44
44
|
} | {
|
|
45
45
|
result: {
|
|
46
46
|
contract: "deployment.result.v1";
|
|
47
47
|
moduleRef: "dev-tunnel";
|
|
48
|
-
moduleVersion: "0.1.
|
|
48
|
+
moduleVersion: "0.1.23";
|
|
49
49
|
ok: false;
|
|
50
50
|
status: "FAILED";
|
|
51
51
|
error: {
|
|
@@ -62,7 +62,7 @@ export declare function createDevTunnelBehaviorAdapter(dependencies?: {
|
|
|
62
62
|
ok: true;
|
|
63
63
|
status: "SUCCEEDED";
|
|
64
64
|
moduleRef: "dev-tunnel";
|
|
65
|
-
moduleVersion: "0.1.
|
|
65
|
+
moduleVersion: "0.1.23";
|
|
66
66
|
data: {
|
|
67
67
|
setupStatus: "ACTION_REQUIRED" | "READY";
|
|
68
68
|
runtimeStatus: "FAILED" | "RUNNING" | "STOPPED";
|
|
@@ -89,67 +89,67 @@ export declare function createDevTunnelBehaviorAdapter(dependencies?: {
|
|
|
89
89
|
ok: true;
|
|
90
90
|
status: "SUCCEEDED";
|
|
91
91
|
moduleRef: "dev-tunnel";
|
|
92
|
-
moduleVersion: "0.1.
|
|
92
|
+
moduleVersion: "0.1.23";
|
|
93
93
|
data: {
|
|
94
94
|
docs: string;
|
|
95
95
|
};
|
|
96
96
|
};
|
|
97
97
|
observedEffects: never[];
|
|
98
98
|
}>;
|
|
99
|
-
readonly
|
|
99
|
+
readonly stop: (context: ModuleCommandContext) => Promise<{
|
|
100
|
+
result: {
|
|
101
|
+
readonly contract: "deployment.result.v1";
|
|
102
|
+
readonly ok: true;
|
|
103
|
+
readonly status: "SUCCEEDED";
|
|
104
|
+
readonly moduleRef: "dev-tunnel";
|
|
105
|
+
readonly moduleVersion: "0.1.23";
|
|
106
|
+
};
|
|
107
|
+
observedEffects: string[];
|
|
108
|
+
} | {
|
|
100
109
|
result: {
|
|
101
110
|
contract: "deployment.result.v1";
|
|
102
111
|
moduleRef: "dev-tunnel";
|
|
103
|
-
moduleVersion: "0.1.
|
|
112
|
+
moduleVersion: "0.1.23";
|
|
104
113
|
ok: false;
|
|
105
114
|
status: "FAILED";
|
|
106
115
|
error: {
|
|
107
|
-
code: "
|
|
116
|
+
code: "STOP_FAILED";
|
|
108
117
|
message: string;
|
|
109
118
|
retryable: boolean;
|
|
110
119
|
};
|
|
111
120
|
};
|
|
112
121
|
observedEffects: never[];
|
|
113
|
-
} | {
|
|
114
|
-
result: {
|
|
115
|
-
contract: "deployment.result.v1";
|
|
116
|
-
ok: true;
|
|
117
|
-
status: "SUCCEEDED";
|
|
118
|
-
moduleRef: "dev-tunnel";
|
|
119
|
-
moduleVersion: "0.1.21";
|
|
120
|
-
data: import("../src/resource-adapter.ts").DevTunnelObservation;
|
|
121
|
-
};
|
|
122
|
-
observedEffects: string[];
|
|
123
122
|
}>;
|
|
124
|
-
readonly
|
|
125
|
-
result: {
|
|
126
|
-
readonly contract: "deployment.result.v1";
|
|
127
|
-
readonly ok: true;
|
|
128
|
-
readonly status: "SUCCEEDED";
|
|
129
|
-
readonly moduleRef: "dev-tunnel";
|
|
130
|
-
readonly moduleVersion: "0.1.21";
|
|
131
|
-
};
|
|
132
|
-
observedEffects: string[];
|
|
133
|
-
} | {
|
|
123
|
+
readonly start: (context: ModuleCommandContext) => Promise<{
|
|
134
124
|
result: {
|
|
135
125
|
contract: "deployment.result.v1";
|
|
136
126
|
moduleRef: "dev-tunnel";
|
|
137
|
-
moduleVersion: "0.1.
|
|
127
|
+
moduleVersion: "0.1.23";
|
|
138
128
|
ok: false;
|
|
139
129
|
status: "FAILED";
|
|
140
130
|
error: {
|
|
141
|
-
code: "
|
|
131
|
+
code: "START_FAILED";
|
|
142
132
|
message: string;
|
|
143
133
|
retryable: boolean;
|
|
144
134
|
};
|
|
145
135
|
};
|
|
146
136
|
observedEffects: never[];
|
|
137
|
+
} | {
|
|
138
|
+
result: {
|
|
139
|
+
contract: "deployment.result.v1";
|
|
140
|
+
ok: true;
|
|
141
|
+
status: "SUCCEEDED";
|
|
142
|
+
moduleRef: "dev-tunnel";
|
|
143
|
+
moduleVersion: "0.1.23";
|
|
144
|
+
data: import("../src/resource-adapter.ts").DevTunnelObservation;
|
|
145
|
+
};
|
|
146
|
+
observedEffects: string[];
|
|
147
147
|
}>;
|
|
148
148
|
readonly setup: (context: ModuleCommandContext) => Promise<{
|
|
149
149
|
result: {
|
|
150
150
|
contract: "deployment.result.v1";
|
|
151
151
|
moduleRef: "dev-tunnel";
|
|
152
|
-
moduleVersion: "0.1.
|
|
152
|
+
moduleVersion: "0.1.23";
|
|
153
153
|
ok: false;
|
|
154
154
|
status: "FAILED";
|
|
155
155
|
error: {
|
|
@@ -165,7 +165,7 @@ export declare function createDevTunnelBehaviorAdapter(dependencies?: {
|
|
|
165
165
|
ok: true;
|
|
166
166
|
status: "SUCCEEDED";
|
|
167
167
|
moduleRef: "dev-tunnel";
|
|
168
|
-
moduleVersion: "0.1.
|
|
168
|
+
moduleVersion: "0.1.23";
|
|
169
169
|
data: SetupState;
|
|
170
170
|
};
|
|
171
171
|
observedEffects: string[];
|
|
@@ -178,7 +178,7 @@ export declare const behaviorAdapter: {
|
|
|
178
178
|
readonly ok: true;
|
|
179
179
|
readonly status: "SUCCEEDED";
|
|
180
180
|
readonly moduleRef: "dev-tunnel";
|
|
181
|
-
readonly moduleVersion: "0.1.
|
|
181
|
+
readonly moduleVersion: "0.1.23";
|
|
182
182
|
};
|
|
183
183
|
observedEffects: never[];
|
|
184
184
|
}>;
|
|
@@ -188,14 +188,14 @@ export declare const behaviorAdapter: {
|
|
|
188
188
|
readonly ok: true;
|
|
189
189
|
readonly status: "SUCCEEDED";
|
|
190
190
|
readonly moduleRef: "dev-tunnel";
|
|
191
|
-
readonly moduleVersion: "0.1.
|
|
191
|
+
readonly moduleVersion: "0.1.23";
|
|
192
192
|
};
|
|
193
193
|
observedEffects: string[];
|
|
194
194
|
} | {
|
|
195
195
|
result: {
|
|
196
196
|
contract: "deployment.result.v1";
|
|
197
197
|
moduleRef: "dev-tunnel";
|
|
198
|
-
moduleVersion: "0.1.
|
|
198
|
+
moduleVersion: "0.1.23";
|
|
199
199
|
ok: false;
|
|
200
200
|
status: "FAILED";
|
|
201
201
|
error: {
|
|
@@ -212,7 +212,7 @@ export declare const behaviorAdapter: {
|
|
|
212
212
|
ok: true;
|
|
213
213
|
status: "SUCCEEDED";
|
|
214
214
|
moduleRef: "dev-tunnel";
|
|
215
|
-
moduleVersion: "0.1.
|
|
215
|
+
moduleVersion: "0.1.23";
|
|
216
216
|
data: {
|
|
217
217
|
setupStatus: "ACTION_REQUIRED" | "READY";
|
|
218
218
|
runtimeStatus: "FAILED" | "RUNNING" | "STOPPED";
|
|
@@ -239,67 +239,67 @@ export declare const behaviorAdapter: {
|
|
|
239
239
|
ok: true;
|
|
240
240
|
status: "SUCCEEDED";
|
|
241
241
|
moduleRef: "dev-tunnel";
|
|
242
|
-
moduleVersion: "0.1.
|
|
242
|
+
moduleVersion: "0.1.23";
|
|
243
243
|
data: {
|
|
244
244
|
docs: string;
|
|
245
245
|
};
|
|
246
246
|
};
|
|
247
247
|
observedEffects: never[];
|
|
248
248
|
}>;
|
|
249
|
-
readonly
|
|
249
|
+
readonly stop: (context: ModuleCommandContext) => Promise<{
|
|
250
|
+
result: {
|
|
251
|
+
readonly contract: "deployment.result.v1";
|
|
252
|
+
readonly ok: true;
|
|
253
|
+
readonly status: "SUCCEEDED";
|
|
254
|
+
readonly moduleRef: "dev-tunnel";
|
|
255
|
+
readonly moduleVersion: "0.1.23";
|
|
256
|
+
};
|
|
257
|
+
observedEffects: string[];
|
|
258
|
+
} | {
|
|
250
259
|
result: {
|
|
251
260
|
contract: "deployment.result.v1";
|
|
252
261
|
moduleRef: "dev-tunnel";
|
|
253
|
-
moduleVersion: "0.1.
|
|
262
|
+
moduleVersion: "0.1.23";
|
|
254
263
|
ok: false;
|
|
255
264
|
status: "FAILED";
|
|
256
265
|
error: {
|
|
257
|
-
code: "
|
|
266
|
+
code: "STOP_FAILED";
|
|
258
267
|
message: string;
|
|
259
268
|
retryable: boolean;
|
|
260
269
|
};
|
|
261
270
|
};
|
|
262
271
|
observedEffects: never[];
|
|
263
|
-
} | {
|
|
264
|
-
result: {
|
|
265
|
-
contract: "deployment.result.v1";
|
|
266
|
-
ok: true;
|
|
267
|
-
status: "SUCCEEDED";
|
|
268
|
-
moduleRef: "dev-tunnel";
|
|
269
|
-
moduleVersion: "0.1.21";
|
|
270
|
-
data: import("../src/resource-adapter.ts").DevTunnelObservation;
|
|
271
|
-
};
|
|
272
|
-
observedEffects: string[];
|
|
273
272
|
}>;
|
|
274
|
-
readonly
|
|
275
|
-
result: {
|
|
276
|
-
readonly contract: "deployment.result.v1";
|
|
277
|
-
readonly ok: true;
|
|
278
|
-
readonly status: "SUCCEEDED";
|
|
279
|
-
readonly moduleRef: "dev-tunnel";
|
|
280
|
-
readonly moduleVersion: "0.1.21";
|
|
281
|
-
};
|
|
282
|
-
observedEffects: string[];
|
|
283
|
-
} | {
|
|
273
|
+
readonly start: (context: ModuleCommandContext) => Promise<{
|
|
284
274
|
result: {
|
|
285
275
|
contract: "deployment.result.v1";
|
|
286
276
|
moduleRef: "dev-tunnel";
|
|
287
|
-
moduleVersion: "0.1.
|
|
277
|
+
moduleVersion: "0.1.23";
|
|
288
278
|
ok: false;
|
|
289
279
|
status: "FAILED";
|
|
290
280
|
error: {
|
|
291
|
-
code: "
|
|
281
|
+
code: "START_FAILED";
|
|
292
282
|
message: string;
|
|
293
283
|
retryable: boolean;
|
|
294
284
|
};
|
|
295
285
|
};
|
|
296
286
|
observedEffects: never[];
|
|
287
|
+
} | {
|
|
288
|
+
result: {
|
|
289
|
+
contract: "deployment.result.v1";
|
|
290
|
+
ok: true;
|
|
291
|
+
status: "SUCCEEDED";
|
|
292
|
+
moduleRef: "dev-tunnel";
|
|
293
|
+
moduleVersion: "0.1.23";
|
|
294
|
+
data: import("../src/resource-adapter.ts").DevTunnelObservation;
|
|
295
|
+
};
|
|
296
|
+
observedEffects: string[];
|
|
297
297
|
}>;
|
|
298
298
|
readonly setup: (context: ModuleCommandContext) => Promise<{
|
|
299
299
|
result: {
|
|
300
300
|
contract: "deployment.result.v1";
|
|
301
301
|
moduleRef: "dev-tunnel";
|
|
302
|
-
moduleVersion: "0.1.
|
|
302
|
+
moduleVersion: "0.1.23";
|
|
303
303
|
ok: false;
|
|
304
304
|
status: "FAILED";
|
|
305
305
|
error: {
|
|
@@ -315,7 +315,7 @@ export declare const behaviorAdapter: {
|
|
|
315
315
|
ok: true;
|
|
316
316
|
status: "SUCCEEDED";
|
|
317
317
|
moduleRef: "dev-tunnel";
|
|
318
|
-
moduleVersion: "0.1.
|
|
318
|
+
moduleVersion: "0.1.23";
|
|
319
319
|
data: SetupState;
|
|
320
320
|
};
|
|
321
321
|
observedEffects: string[];
|
|
@@ -3,8 +3,8 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { readModuleSharedFacts, writeModuleSharedFacts, } from "@tomflow/proflow-module-contract";
|
|
6
|
-
import { createDevTunnelAutomation, createDevTunnelRuntime, verifyProvisionedPublicBaseUrl, } from "../src/resource-adapter.js";
|
|
7
6
|
import { devTunnelCliPath, resolveDevTunnelCli } from "../src/cli-resolver.js";
|
|
7
|
+
import { createDevTunnelAutomation, createDevTunnelRuntime, verifyProvisionedPublicBaseUrl, } from "../src/resource-adapter.js";
|
|
8
8
|
import { descriptor } from "./descriptor.js";
|
|
9
9
|
const base = {
|
|
10
10
|
contract: "deployment.result.v1",
|
|
@@ -367,6 +367,50 @@ export function createDevTunnelBehaviorAdapter(dependencies) {
|
|
|
367
367
|
const verifyPublicBaseUrl = dependencies?.verifyPublicBaseUrl ?? verifyProvisionedPublicBaseUrl;
|
|
368
368
|
return {
|
|
369
369
|
...baseBehaviorAdapter,
|
|
370
|
+
start: async (context) => {
|
|
371
|
+
const state = await readState(context);
|
|
372
|
+
if (state?.phase !== "READY" || !state.publicBaseUrl)
|
|
373
|
+
return baseBehaviorAdapter.start(context);
|
|
374
|
+
const rt = createRuntime({
|
|
375
|
+
command: devTunnelCliPath(),
|
|
376
|
+
tunnelId: state.tunnelId,
|
|
377
|
+
publicBaseUrl: state.publicBaseUrl,
|
|
378
|
+
processStateFile: processFile(context),
|
|
379
|
+
});
|
|
380
|
+
try {
|
|
381
|
+
const observed = await rt.start();
|
|
382
|
+
if (observed.login !== "LOGGED_IN")
|
|
383
|
+
throw new Error("Microsoft Dev Tunnel login is not ready");
|
|
384
|
+
if (observed.state !== "RUNNING")
|
|
385
|
+
throw new Error("dev-tunnel did not reach RUNNING");
|
|
386
|
+
try {
|
|
387
|
+
await verifyPublicBaseUrl(state.publicBaseUrl);
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
await rt.stop().catch(() => undefined);
|
|
391
|
+
throw error;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
result: { ...base, data: observed },
|
|
395
|
+
observedEffects: [processEffect],
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
return {
|
|
400
|
+
result: {
|
|
401
|
+
...base,
|
|
402
|
+
ok: false,
|
|
403
|
+
status: "FAILED",
|
|
404
|
+
error: {
|
|
405
|
+
code: "START_FAILED",
|
|
406
|
+
message: error instanceof Error ? error.message : "failed to start dev-tunnel",
|
|
407
|
+
retryable: true,
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
observedEffects: [],
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
},
|
|
370
414
|
setup: async (context) => {
|
|
371
415
|
try {
|
|
372
416
|
const previous = await readState(context);
|
|
@@ -3,7 +3,7 @@ export declare const descriptor: {
|
|
|
3
3
|
readonly contractVersion: "1.0.0";
|
|
4
4
|
readonly moduleRef: "dev-tunnel";
|
|
5
5
|
readonly packageName: "@tomflow/proflow-dev-tunnel";
|
|
6
|
-
readonly moduleVersion: "0.1.
|
|
6
|
+
readonly moduleVersion: "0.1.23";
|
|
7
7
|
readonly kind: "external-resource";
|
|
8
8
|
readonly templateVersion: "1.0.0";
|
|
9
9
|
readonly platformCompatibility: ">=1.0.0 <2.0.0";
|
|
@@ -3,7 +3,7 @@ export const descriptor = {
|
|
|
3
3
|
contractVersion: "1.0.0",
|
|
4
4
|
moduleRef: "dev-tunnel",
|
|
5
5
|
packageName: "@tomflow/proflow-dev-tunnel",
|
|
6
|
-
moduleVersion: "0.1.
|
|
6
|
+
moduleVersion: "0.1.23",
|
|
7
7
|
kind: "external-resource",
|
|
8
8
|
templateVersion: "1.0.0",
|
|
9
9
|
platformCompatibility: ">=1.0.0 <2.0.0",
|
package/dist/src/cli-resolver.js
CHANGED
|
@@ -62,7 +62,9 @@ async function version(command) {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
async function sha256(path) {
|
|
65
|
-
return createHash("sha256")
|
|
65
|
+
return createHash("sha256")
|
|
66
|
+
.update(await readFile(path))
|
|
67
|
+
.digest("hex");
|
|
66
68
|
}
|
|
67
69
|
async function validCached(path) {
|
|
68
70
|
try {
|
|
@@ -94,6 +94,14 @@ function parseTunnel(input) {
|
|
|
94
94
|
return z.object({ tunnel: tunnelPayloadSchema }).passthrough().parse(input)
|
|
95
95
|
.tunnel;
|
|
96
96
|
}
|
|
97
|
+
function sameTunnelIdentity(requested, observed) {
|
|
98
|
+
if (observed === requested)
|
|
99
|
+
return true;
|
|
100
|
+
if (requested.includes("."))
|
|
101
|
+
return false;
|
|
102
|
+
const prefix = `${requested}.`;
|
|
103
|
+
return (observed.startsWith(prefix) && !observed.slice(prefix.length).includes("."));
|
|
104
|
+
}
|
|
97
105
|
function parseJson(text, label) {
|
|
98
106
|
try {
|
|
99
107
|
return JSON.parse(text);
|
|
@@ -174,7 +182,9 @@ export function createDevTunnelAutomation(input) {
|
|
|
174
182
|
const command = input?.command ?? "devtunnel";
|
|
175
183
|
const run = input?.runCommand ?? defaultCommandRunner;
|
|
176
184
|
const runRemoteQuery = async (args, retryTimeout = true) => {
|
|
177
|
-
let result = await run(command, args, {
|
|
185
|
+
let result = await run(command, args, {
|
|
186
|
+
timeoutMs: REMOTE_QUERY_TIMEOUT_MS,
|
|
187
|
+
});
|
|
178
188
|
if (!retryTimeout ||
|
|
179
189
|
result.exitCode !== null ||
|
|
180
190
|
!/timed out/i.test(commandText(result)))
|
|
@@ -225,7 +235,7 @@ export function createDevTunnelAutomation(input) {
|
|
|
225
235
|
}
|
|
226
236
|
try {
|
|
227
237
|
const tunnel = parseTunnel(parseJson(result.stdout, "devtunnel show --json"));
|
|
228
|
-
if (tunnel.tunnelId
|
|
238
|
+
if (!sameTunnelIdentity(tunnelId, tunnel.tunnelId))
|
|
229
239
|
return { state: "UNKNOWN", hostState: "UNKNOWN" };
|
|
230
240
|
const hostState = tunnel.hostConnections !== undefined
|
|
231
241
|
? tunnel.hostConnections > 0
|
|
@@ -246,9 +256,9 @@ export function createDevTunnelAutomation(input) {
|
|
|
246
256
|
const result = await run(command, ["create", tunnelId, "--allow-anonymous", "--json"], { timeoutMs: REMOTE_COMMAND_TIMEOUT_MS });
|
|
247
257
|
assertCommandSucceeded(result, "devtunnel create --json");
|
|
248
258
|
const tunnel = parseTunnel(parseJson(result.stdout, "devtunnel create --json"));
|
|
249
|
-
if (tunnel.tunnelId
|
|
259
|
+
if (!sameTunnelIdentity(tunnelId, tunnel.tunnelId))
|
|
250
260
|
throw new Error("devtunnel create returned an unexpected tunnelId");
|
|
251
|
-
return
|
|
261
|
+
return tunnelId;
|
|
252
262
|
},
|
|
253
263
|
async ensurePort(tunnelId, port) {
|
|
254
264
|
const listed = await runRemoteQuery(["port", "list", tunnelId, "--json"]);
|
package/package.json
CHANGED
package/proflow.module.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"contractVersion": "1.0.0",
|
|
4
4
|
"moduleRef": "dev-tunnel",
|
|
5
5
|
"packageName": "@tomflow/proflow-dev-tunnel",
|
|
6
|
-
"moduleVersion": "0.1.
|
|
6
|
+
"moduleVersion": "0.1.23",
|
|
7
7
|
"kind": "external-resource",
|
|
8
8
|
"templateVersion": "1.0.0",
|
|
9
9
|
"platformCompatibility": ">=1.0.0 <2.0.0",
|