@dbx-tools/databricks 0.6.182 → 0.6.183
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/README.md +4 -22
- package/index.ts +1 -2
- package/lib/index.d.ts +15 -0
- package/lib/index.js +15 -1033
- package/lib/src/cloud.d.ts +80 -0
- package/lib/src/cloud.js +240 -0
- package/lib/src/databricks-fs.d.ts +93 -0
- package/lib/src/databricks-fs.js +327 -0
- package/lib/src/databricks-path.d.ts +67 -0
- package/lib/src/databricks-path.js +113 -0
- package/lib/src/net.d.ts +29 -0
- package/lib/src/net.js +68 -0
- package/lib/src/workspace.d.ts +43 -0
- package/lib/src/workspace.js +110 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +38 -20
- package/src/_bindings-ffi.ts +0 -396
- package/src/_bindings.ts +0 -102
- package/src/bindings.ts +0 -11
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databricks {@link FileSystem} backed by {@link WorkspaceClient}.
|
|
3
|
+
*
|
|
4
|
+
* Extends {@link BaseFileSystem}. Routes I/O by absolute path:
|
|
5
|
+
* - `/Workspace`, `/Users`, `/Repos`, `/Shared` → workspace objects API
|
|
6
|
+
* - `/Volumes/...` (or `catalog.schema.volume` roots) → Unity Catalog Files API
|
|
7
|
+
* - `/dbfs/...` → DBFS API
|
|
8
|
+
*
|
|
9
|
+
* Every primitive picks its API through {@link DatabricksFileSystem.dispatch}
|
|
10
|
+
* rather than re-branching by hand, and error normalization is inherited from
|
|
11
|
+
* {@link BaseFileSystem}, so a primitive here is just the SDK call.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { hash, object } from "@dbx-tools/shared-core";
|
|
16
|
+
import { BaseFileSystem, baseFS, FileSystemError, posixPath, } from "@dbx-tools/shared-fs";
|
|
17
|
+
import { isHomeRelativePath, normalizeDatabricksRoot, resolveDatabricksFilesBackend, resolveDatabricksRoot, } from "./databricks-path.js";
|
|
18
|
+
import { getWorkspaceClient } from "./workspace.js";
|
|
19
|
+
const DBFS_READ_CHUNK_BYTES = 1024 * 1024;
|
|
20
|
+
const DBFS_PUT_MAX_BYTES = 1024 * 1024;
|
|
21
|
+
/** Segments in `/Volumes/<catalog>/<schema>/<volume>`, provisioned out of band. */
|
|
22
|
+
const VOLUME_ROOT_DEPTH = 4;
|
|
23
|
+
/**
|
|
24
|
+
* {@link FileSystem} implementation over Databricks workspace files, UC
|
|
25
|
+
* volumes, and DBFS.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const fs = new DatabricksFileSystem({ root: "main.default.assets" });
|
|
30
|
+
* await fs.writeFile("notes/hello.txt", "hi");
|
|
31
|
+
*
|
|
32
|
+
* const home = await DatabricksFileSystem.create({ root: "~" });
|
|
33
|
+
* const listing = await home.readdir(".");
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export class DatabricksFileSystem extends BaseFileSystem {
|
|
37
|
+
client;
|
|
38
|
+
clientOption;
|
|
39
|
+
constructor(options) {
|
|
40
|
+
const root = normalizeDatabricksRoot(options.root, { userName: options.userName });
|
|
41
|
+
super({
|
|
42
|
+
id: options.id ?? `databricks-${hash.fnvHash(root)}`,
|
|
43
|
+
backend: "databricks",
|
|
44
|
+
root,
|
|
45
|
+
readOnly: options.readOnly,
|
|
46
|
+
createRoot: options.createRoot ?? false,
|
|
47
|
+
});
|
|
48
|
+
this.clientOption = options.client;
|
|
49
|
+
this.client = options.client;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Construct a {@link DatabricksFileSystem}, resolving `~` roots via the
|
|
53
|
+
* workspace current user when needed.
|
|
54
|
+
*/
|
|
55
|
+
static async create(options) {
|
|
56
|
+
if (!isHomeRelativePath(options.root) || options.userName?.trim()) {
|
|
57
|
+
return new DatabricksFileSystem(options);
|
|
58
|
+
}
|
|
59
|
+
const client = options.client ?? (await getWorkspaceClient());
|
|
60
|
+
const root = await resolveDatabricksRoot(options.root, { client });
|
|
61
|
+
return new DatabricksFileSystem({ ...options, root, client });
|
|
62
|
+
}
|
|
63
|
+
async onInit() {
|
|
64
|
+
this.client = this.clientOption ?? (await getWorkspaceClient());
|
|
65
|
+
}
|
|
66
|
+
/** Run the handler for `absolutePath`'s Databricks API with the live client. */
|
|
67
|
+
dispatch(absolutePath, handlers) {
|
|
68
|
+
if (!this.client) {
|
|
69
|
+
throw new FileSystemError("IO_ERROR", "Databricks filesystem is not initialized (no WorkspaceClient)", absolutePath);
|
|
70
|
+
}
|
|
71
|
+
return handlers[resolveDatabricksFilesBackend(absolutePath)](this.client);
|
|
72
|
+
}
|
|
73
|
+
/* ------------------------------------------------------------------ */
|
|
74
|
+
/* Primitives */
|
|
75
|
+
/* ------------------------------------------------------------------ */
|
|
76
|
+
async createRootDirectory() {
|
|
77
|
+
await this.createDirectoryAt(this.root);
|
|
78
|
+
}
|
|
79
|
+
async readBytesAt(resolvedPath) {
|
|
80
|
+
const buffer = await this.dispatch(resolvedPath, {
|
|
81
|
+
dbfs: (client) => this.readDbfsFile(client, resolvedPath),
|
|
82
|
+
workspace: async (client) => {
|
|
83
|
+
const response = await client.workspace.export({ path: resolvedPath, format: "AUTO" });
|
|
84
|
+
return decodeBase64(response.content);
|
|
85
|
+
},
|
|
86
|
+
volumes: async (client) => {
|
|
87
|
+
const response = await client.files.download({ file_path: resolvedPath });
|
|
88
|
+
return readResponseBody(response.contents);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
92
|
+
}
|
|
93
|
+
async writeBytesAt(resolvedPath, content, options) {
|
|
94
|
+
const buffer = Buffer.from(content);
|
|
95
|
+
const overwrite = options.overwrite;
|
|
96
|
+
await this.dispatch(resolvedPath, {
|
|
97
|
+
dbfs: (client) => this.writeDbfsFile(client, resolvedPath, buffer, overwrite),
|
|
98
|
+
workspace: (client) => client.workspace.import({
|
|
99
|
+
path: resolvedPath,
|
|
100
|
+
format: "AUTO",
|
|
101
|
+
content: buffer.toString("base64"),
|
|
102
|
+
overwrite,
|
|
103
|
+
}),
|
|
104
|
+
volumes: (client) => client.files.upload({
|
|
105
|
+
file_path: resolvedPath,
|
|
106
|
+
contents: bufferToReadableStream(buffer),
|
|
107
|
+
overwrite,
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async deleteFileAt(resolvedPath) {
|
|
112
|
+
await this.dispatch(resolvedPath, {
|
|
113
|
+
dbfs: (client) => client.dbfs.delete({ path: resolvedPath, recursive: false }),
|
|
114
|
+
workspace: (client) => client.workspace.delete({ path: resolvedPath, recursive: false }),
|
|
115
|
+
volumes: (client) => client.files.delete({ file_path: resolvedPath }),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async createDirectoryAt(resolvedPath) {
|
|
119
|
+
await this.dispatch(resolvedPath, {
|
|
120
|
+
dbfs: (client) => client.dbfs.mkdirs({ path: resolvedPath }),
|
|
121
|
+
workspace: (client) => client.workspace.mkdirs({ path: resolvedPath }),
|
|
122
|
+
volumes: (client) => this.createVolumeDirectories(client, resolvedPath),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async removeDirectoryAt(resolvedPath) {
|
|
126
|
+
await this.dispatch(resolvedPath, {
|
|
127
|
+
dbfs: (client) => client.dbfs.delete({ path: resolvedPath, recursive: false }),
|
|
128
|
+
workspace: (client) => client.workspace.delete({ path: resolvedPath, recursive: false }),
|
|
129
|
+
volumes: (client) => client.files.deleteDirectory({ directory_path: resolvedPath }),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async listDirectoryAt(resolvedPath) {
|
|
133
|
+
return this.dispatch(resolvedPath, {
|
|
134
|
+
dbfs: (client) => collect(client.dbfs.list({ path: resolvedPath }), (info) => ({
|
|
135
|
+
name: posixPath.basename(info.path ?? ""),
|
|
136
|
+
type: info.is_dir ? "directory" : "file",
|
|
137
|
+
size: info.file_size,
|
|
138
|
+
})),
|
|
139
|
+
workspace: (client) => collect(client.workspace.list({ path: resolvedPath }), (info) => ({
|
|
140
|
+
name: posixPath.basename(info.path ?? ""),
|
|
141
|
+
type: info.object_type === "DIRECTORY" ? "directory" : "file",
|
|
142
|
+
})),
|
|
143
|
+
volumes: (client) => collect(client.files.listDirectoryContents({ directory_path: resolvedPath }), (entry) => ({
|
|
144
|
+
name: entry.name ?? posixPath.basename(entry.path ?? ""),
|
|
145
|
+
type: entry.is_directory ? "directory" : "file",
|
|
146
|
+
size: entry.file_size,
|
|
147
|
+
})),
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async statAt(resolvedPath) {
|
|
151
|
+
const fallbackName = posixPath.basename(resolvedPath) || posixPath.basename(this.root);
|
|
152
|
+
return this.dispatch(resolvedPath, {
|
|
153
|
+
dbfs: async (client) => {
|
|
154
|
+
const info = await client.dbfs.getStatus({ path: resolvedPath });
|
|
155
|
+
const modified = object.toDate(info.modification_time);
|
|
156
|
+
return {
|
|
157
|
+
name: posixPath.basename(info.path ?? resolvedPath) || fallbackName,
|
|
158
|
+
type: info.is_dir ? "directory" : "file",
|
|
159
|
+
size: info.file_size,
|
|
160
|
+
createdAt: modified,
|
|
161
|
+
modifiedAt: modified,
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
workspace: async (client) => {
|
|
165
|
+
const info = await client.workspace.getStatus({ path: resolvedPath });
|
|
166
|
+
return {
|
|
167
|
+
name: posixPath.basename(info.path ?? resolvedPath) || fallbackName,
|
|
168
|
+
type: info.object_type === "DIRECTORY" ? "directory" : "file",
|
|
169
|
+
createdAt: object.toDate(info.created_at),
|
|
170
|
+
modifiedAt: object.toDate(info.modified_at),
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
volumes: (client) => this.statVolumePath(client, resolvedPath, fallbackName),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
async tryMoveFileAt(sourcePath, destinationPath, _options) {
|
|
177
|
+
// Only DBFS exposes a server-side move; everything else falls back to the
|
|
178
|
+
// portable copy + delete in BaseFileSystem.
|
|
179
|
+
if (resolveDatabricksFilesBackend(sourcePath) !== "dbfs" ||
|
|
180
|
+
resolveDatabricksFilesBackend(destinationPath) !== "dbfs") {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
await this.dispatch(sourcePath, {
|
|
184
|
+
dbfs: (client) => client.dbfs.move({ source_path: sourcePath, destination_path: destinationPath }),
|
|
185
|
+
workspace: unreachableBackend,
|
|
186
|
+
volumes: unreachableBackend,
|
|
187
|
+
});
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
/* ------------------------------------------------------------------ */
|
|
191
|
+
/* Backend-specific I/O */
|
|
192
|
+
/* ------------------------------------------------------------------ */
|
|
193
|
+
/**
|
|
194
|
+
* UC `createDirectory` is single-level, so walk the path creating each level
|
|
195
|
+
* below the volume itself. A level that already exists is not an error.
|
|
196
|
+
*/
|
|
197
|
+
async createVolumeDirectories(client, absolutePath) {
|
|
198
|
+
const parts = absolutePath.split("/").filter(Boolean);
|
|
199
|
+
let current = "";
|
|
200
|
+
for (let i = 0; i < parts.length; i++) {
|
|
201
|
+
current = `${current}/${parts[i]}`;
|
|
202
|
+
if (i < VOLUME_ROOT_DEPTH)
|
|
203
|
+
continue;
|
|
204
|
+
try {
|
|
205
|
+
await client.files.createDirectory({ directory_path: current });
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
// Already present is fine; anything else is a real failure.
|
|
209
|
+
try {
|
|
210
|
+
await client.files.getDirectoryMetadata({ directory_path: current });
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
throw err;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Stat a UC path: file metadata first, then a directory probe. */
|
|
219
|
+
async statVolumePath(client, absolutePath, fallbackName) {
|
|
220
|
+
try {
|
|
221
|
+
const metadata = await client.files.getMetadata({ file_path: absolutePath });
|
|
222
|
+
const modified = object.toDate(metadata["last-modified"]);
|
|
223
|
+
return {
|
|
224
|
+
name: fallbackName,
|
|
225
|
+
type: "file",
|
|
226
|
+
size: Number(metadata["content-length"] ?? 0),
|
|
227
|
+
createdAt: modified,
|
|
228
|
+
modifiedAt: modified,
|
|
229
|
+
mimeType: metadata["content-type"],
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
catch (fileErr) {
|
|
233
|
+
// A directory has no file metadata, and an unreadable one reports as
|
|
234
|
+
// missing / denied - both are worth a directory probe before failing.
|
|
235
|
+
const code = baseFS.mapFileSystemError(fileErr, absolutePath).code;
|
|
236
|
+
if (code !== "NOT_FOUND" && code !== "PERMISSION_DENIED")
|
|
237
|
+
throw fileErr;
|
|
238
|
+
await client.files.getDirectoryMetadata({ directory_path: absolutePath });
|
|
239
|
+
return { name: fallbackName, type: "directory" };
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async readDbfsFile(client, absolutePath) {
|
|
243
|
+
const chunks = [];
|
|
244
|
+
let offset = 0;
|
|
245
|
+
while (true) {
|
|
246
|
+
const response = await client.dbfs.read({
|
|
247
|
+
path: absolutePath,
|
|
248
|
+
offset,
|
|
249
|
+
length: DBFS_READ_CHUNK_BYTES,
|
|
250
|
+
});
|
|
251
|
+
const chunk = decodeBase64(response.data);
|
|
252
|
+
if (chunk.length === 0)
|
|
253
|
+
break;
|
|
254
|
+
chunks.push(chunk);
|
|
255
|
+
offset += chunk.length;
|
|
256
|
+
if (chunk.length < DBFS_READ_CHUNK_BYTES)
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
return Buffer.concat(chunks);
|
|
260
|
+
}
|
|
261
|
+
async writeDbfsFile(client, absolutePath, buffer, overwrite) {
|
|
262
|
+
if (buffer.length <= DBFS_PUT_MAX_BYTES) {
|
|
263
|
+
await client.dbfs.put({
|
|
264
|
+
path: absolutePath,
|
|
265
|
+
contents: buffer.toString("base64"),
|
|
266
|
+
overwrite,
|
|
267
|
+
});
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const created = await client.dbfs.create({ path: absolutePath, overwrite });
|
|
271
|
+
const handle = created.handle;
|
|
272
|
+
if (handle === undefined) {
|
|
273
|
+
throw new FileSystemError("IO_ERROR", "DBFS upload handle missing", absolutePath);
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
for (let offset = 0; offset < buffer.length; offset += DBFS_PUT_MAX_BYTES) {
|
|
277
|
+
const slice = buffer.subarray(offset, offset + DBFS_PUT_MAX_BYTES);
|
|
278
|
+
await client.dbfs.addBlock({ handle, data: slice.toString("base64") });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
await client.dbfs.close({ handle }).catch(() => undefined);
|
|
283
|
+
throw err;
|
|
284
|
+
}
|
|
285
|
+
await client.dbfs.close({ handle });
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/* ------------------------------ helpers ------------------------------ */
|
|
289
|
+
/** Drain an SDK async iterable into a mapped array. */
|
|
290
|
+
async function collect(source, map) {
|
|
291
|
+
const items = [];
|
|
292
|
+
for await (const item of source)
|
|
293
|
+
items.push(map(item));
|
|
294
|
+
return items;
|
|
295
|
+
}
|
|
296
|
+
/** Handler for a backend a call site has already ruled out. */
|
|
297
|
+
function unreachableBackend() {
|
|
298
|
+
throw new FileSystemError("NOT_SUPPORTED", "Unsupported Databricks backend for this operation");
|
|
299
|
+
}
|
|
300
|
+
function decodeBase64(data) {
|
|
301
|
+
if (!data)
|
|
302
|
+
return Buffer.alloc(0);
|
|
303
|
+
return Buffer.from(data, "base64");
|
|
304
|
+
}
|
|
305
|
+
async function readResponseBody(contents) {
|
|
306
|
+
if (!contents)
|
|
307
|
+
return Buffer.alloc(0);
|
|
308
|
+
const reader = contents.getReader();
|
|
309
|
+
const chunks = [];
|
|
310
|
+
while (true) {
|
|
311
|
+
const { done, value } = await reader.read();
|
|
312
|
+
if (done)
|
|
313
|
+
break;
|
|
314
|
+
if (value)
|
|
315
|
+
chunks.push(value);
|
|
316
|
+
}
|
|
317
|
+
return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)));
|
|
318
|
+
}
|
|
319
|
+
function bufferToReadableStream(buffer) {
|
|
320
|
+
return new ReadableStream({
|
|
321
|
+
start(controller) {
|
|
322
|
+
controller.enqueue(new Uint8Array(buffer));
|
|
323
|
+
controller.close();
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJyaWNrcy1mcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kYXRhYnJpY2tzLWZzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFFSCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3RELE9BQU8sRUFDTCxjQUFjLEVBQ2QsTUFBTSxFQUNOLGVBQWUsRUFDZixTQUFTLEdBS1YsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQ0wsa0JBQWtCLEVBQ2xCLHVCQUF1QixFQUN2Qiw2QkFBNkIsRUFDN0IscUJBQXFCLEdBRXRCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLGtCQUFrQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBRTFFLE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQztBQUMxQyxNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFdkMsbUZBQW1GO0FBQ25GLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBK0M1Qjs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLE9BQU8sb0JBQXFCLFNBQVEsY0FBNEI7SUFDNUQsTUFBTSxDQUE4QjtJQUMzQixZQUFZLENBQThCO0lBRTNELFlBQVksT0FBb0M7UUFDOUMsTUFBTSxJQUFJLEdBQUcsdUJBQXVCLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUNuRixLQUFLLENBQUM7WUFDSixFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUUsSUFBSSxjQUFjLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDcEQsT0FBTyxFQUFFLFlBQVk7WUFDckIsSUFBSTtZQUNKLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtZQUMxQixVQUFVLEVB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QUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERhdGFicmlja3Mge0BsaW5rIEZpbGVTeXN0ZW19IGJhY2tlZCBieSB7QGxpbmsgV29ya3NwYWNlQ2xpZW50fS5cbiAqXG4gKiBFeHRlbmRzIHtAbGluayBCYXNlRmlsZVN5c3RlbX0uIFJvdXRlcyBJL08gYnkgYWJzb2x1dGUgcGF0aDpcbiAqIC0gYC9Xb3Jrc3BhY2VgLCBgL1VzZXJzYCwgYC9SZXBvc2AsIGAvU2hhcmVkYCDihpIgd29ya3NwYWNlIG9iamVjdHMgQVBJXG4gKiAtIGAvVm9sdW1lcy8uLi5gIChvciBgY2F0YWxvZy5zY2hlbWEudm9sdW1lYCByb290cykg4oaSIFVuaXR5IENhdGFsb2cgRmlsZXMgQVBJXG4gKiAtIGAvZGJmcy8uLi5gIOKGkiBEQkZTIEFQSVxuICpcbiAqIEV2ZXJ5IHByaW1pdGl2ZSBwaWNrcyBpdHMgQVBJIHRocm91Z2gge0BsaW5rIERhdGFicmlja3NGaWxlU3lzdGVtLmRpc3BhdGNofVxuICogcmF0aGVyIHRoYW4gcmUtYnJhbmNoaW5nIGJ5IGhhbmQsIGFuZCBlcnJvciBub3JtYWxpemF0aW9uIGlzIGluaGVyaXRlZCBmcm9tXG4gKiB7QGxpbmsgQmFzZUZpbGVTeXN0ZW19LCBzbyBhIHByaW1pdGl2ZSBoZXJlIGlzIGp1c3QgdGhlIFNESyBjYWxsLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBoYXNoLCBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHtcbiAgQmFzZUZpbGVTeXN0ZW0sXG4gIGJhc2VGUyxcbiAgRmlsZVN5c3RlbUVycm9yLFxuICBwb3NpeFBhdGgsXG4gIHR5cGUgQ29weU9wdGlvbnMsXG4gIHR5cGUgRmlsZUVudHJ5LFxuICB0eXBlIEZpbGVTdGF0LFxuICB0eXBlIFdyaXRlRmlsZU9wdGlvbnMsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1mc1wiO1xuaW1wb3J0IHtcbiAgaXNIb21lUmVsYXRpdmVQYXRoLFxuICBub3JtYWxpemVEYXRhYnJpY2tzUm9vdCxcbiAgcmVzb2x2ZURhdGFicmlja3NGaWxlc0JhY2tlbmQsXG4gIHJlc29sdmVEYXRhYnJpY2tzUm9vdCxcbiAgdHlwZSBEYXRhYnJpY2tzRmlsZXNCYWNrZW5kLFxufSBmcm9tIFwiLi9kYXRhYnJpY2tzLXBhdGgudHNcIjtcbmltcG9ydCB7IGdldFdvcmtzcGFjZUNsaWVudCwgdHlwZSBXb3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiLi93b3Jrc3BhY2UudHNcIjtcblxuY29uc3QgREJGU19SRUFEX0NIVU5LX0JZVEVTID0gMTAyNCAqIDEwMjQ7XG5jb25zdCBEQkZTX1BVVF9NQVhfQllURVMgPSAxMDI0ICogMTAyNDtcblxuLyoqIFNlZ21lbnRzIGluIGAvVm9sdW1lcy88Y2F0YWxvZz4vPHNjaGVtYT4vPHZvbHVtZT5gLCBwcm92aXNpb25lZCBvdXQgb2YgYmFuZC4gKi9cbmNvbnN0IFZPTFVNRV9ST09UX0RFUFRIID0gNDtcblxuLyoqXG4gKiBPbmUgaGFuZGxlciBwZXIgRGF0YWJyaWNrcyBBUEksIGtleWVkIGJ5IHtAbGluayBEYXRhYnJpY2tzRmlsZXNCYWNrZW5kfSBzb1xuICogYWRkaW5nIGEgYmFja2VuZCBpcyBhIGNvbXBpbGUgZXJyb3IgdW50aWwgZXZlcnkgY2FsbCBzaXRlIGhhbmRsZXMgaXQuXG4gKi9cbnR5cGUgQmFja2VuZEhhbmRsZXJzPFQ+ID0gUmVjb3JkPERhdGFicmlja3NGaWxlc0JhY2tlbmQsIChjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCkgPT4gUHJvbWlzZTxUPj47XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgRGF0YWJyaWNrc0ZpbGVTeXN0ZW19LiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhYnJpY2tzRmlsZVN5c3RlbU9wdGlvbnMge1xuICAvKiogVW5pcXVlIGlkZW50aWZpZXIuIERlZmF1bHRzIHRvIGEgc3RhYmxlIGhhc2ggb2YgdGhlIG5vcm1hbGl6ZWQgcm9vdC4gKi9cbiAgaWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEZpbGVzeXN0ZW0gcm9vdC4gQWNjZXB0czpcbiAgICogLSBgL1ZvbHVtZXMvY2F0YWxvZy9zY2hlbWEvdm9sdW1lYCAoYWxzbyBgL1ZvbHVtZS8uLi5gKVxuICAgKiAtIGBjYXRhbG9nLnNjaGVtYS52b2x1bWVgXG4gICAqIC0gYH5gIC8gYH4vLi4uYCDihpIgYC9Xb3Jrc3BhY2UvVXNlcnMvPHVzZXJOYW1lPi8uLi5gIChuZWVkcyB7QGxpbmsgdXNlck5hbWV9LFxuICAgKiAgIG9yIHVzZSB7QGxpbmsgRGF0YWJyaWNrc0ZpbGVTeXN0ZW0uY3JlYXRlfSlcbiAgICogLSBgL1dvcmtzcGFjZS8uLi5gLCBgL1VzZXJzLy4uLmAsIGAvUmVwb3MvLi4uYCwgYC9TaGFyZWQvLi4uYFxuICAgKiAtIGAvZGJmcy8uLi5gXG4gICAqL1xuICByb290OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFVzZXJuYW1lIGZvciBleHBhbmRpbmcgYH5gLiBXaGVuIG9taXR0ZWQgYW5kIHtAbGluayByb290fSBpcyBob21lLXJlbGF0aXZlLFxuICAgKiBwcmVmZXIge0BsaW5rIERhdGFicmlja3NGaWxlU3lzdGVtLmNyZWF0ZX0gd2hpY2ggcmVzb2x2ZXMgaXQgdmlhXG4gICAqIGBnZXRDdXJyZW50VXNlck5hbWVgLlxuICAgKi9cbiAgdXNlck5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERhdGFicmlja3Mgd29ya3NwYWNlIGNsaWVudC4gRGVmYXVsdHMgdG8gYHRyeUdldFdvcmtzcGFjZUNsaWVudCgpYCwgb3RoZXJ3aXNlXG4gICAqIGEgZGVmYXVsdCB7QGxpbmsgV29ya3NwYWNlQ2xpZW50fSBmcm9tIGVudiAvIHByb2ZpbGUgYXV0aC5cbiAgICovXG4gIGNsaWVudD86IFdvcmtzcGFjZUNsaWVudDtcblxuICAvKiogQmxvY2sgYWxsIHdyaXRlIG9wZXJhdGlvbnMuIERlZmF1bHRzIHRvIGZhbHNlLiAqL1xuICByZWFkT25seT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIENyZWF0ZSB7QGxpbmsgcm9vdH0gKGFuZCBwYXJlbnRzKSBkdXJpbmcgaW5pdC4gRGVmYXVsdHMgdG8gZmFsc2UgKHZvbHVtZVxuICAgKiBhbmQgd29ya3NwYWNlIHJvb3RzIGFyZSB1c3VhbGx5IHByb3Zpc2lvbmVkIG91dCBvZiBiYW5kKS5cbiAgICovXG4gIGNyZWF0ZVJvb3Q/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIHtAbGluayBGaWxlU3lzdGVtfSBpbXBsZW1lbnRhdGlvbiBvdmVyIERhdGFicmlja3Mgd29ya3NwYWNlIGZpbGVzLCBVQ1xuICogdm9sdW1lcywgYW5kIERCRlMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBjb25zdCBmcyA9IG5ldyBEYXRhYnJpY2tzRmlsZVN5c3RlbSh7IHJvb3Q6IFwibWFpbi5kZWZhdWx0LmFzc2V0c1wiIH0pO1xuICogYXdhaXQgZnMud3JpdGVGaWxlKFwibm90ZXMvaGVsbG8udHh0XCIsIFwiaGlcIik7XG4gKlxuICogY29uc3QgaG9tZSA9IGF3YWl0IERhdGFicmlja3NGaWxlU3lzdGVtLmNyZWF0ZSh7IHJvb3Q6IFwiflwiIH0pO1xuICogY29uc3QgbGlzdGluZyA9IGF3YWl0IGhvbWUucmVhZGRpcihcIi5cIik7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIERhdGFicmlja3NGaWxlU3lzdGVtIGV4dGVuZHMgQmFzZUZpbGVTeXN0ZW08XCJkYXRhYnJpY2tzXCI+IHtcbiAgcHJpdmF0ZSBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBjbGllbnRPcHRpb246IFdvcmtzcGFjZUNsaWVudCB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBEYXRhYnJpY2tzRmlsZVN5c3RlbU9wdGlvbnMpIHtcbiAgICBjb25zdCByb290ID0gbm9ybWFsaXplRGF0YWJyaWNrc1Jvb3Qob3B0aW9ucy5yb290LCB7IHVzZXJOYW1lOiBvcHRpb25zLnVzZXJOYW1lIH0pO1xuICAgIHN1cGVyKHtcbiAgICAgIGlkOiBvcHRpb25zLmlkID8/IGBkYXRhYnJpY2tzLSR7aGFzaC5mbnZIYXNoKHJvb3QpfWAsXG4gICAgICBiYWNrZW5kOiBcImRhdGFicmlja3NcIixcbiAgICAgIHJvb3QsXG4gICAgICByZWFkT25seTogb3B0aW9ucy5yZWFkT25seSxcbiAgICAgIGNyZWF0ZVJvb3Q6IG9wdGlvbnMuY3JlYXRlUm9vdCA/PyBmYWxzZSxcbiAgICB9KTtcbiAgICB0aGlzLmNsaWVudE9wdGlvbiA9IG9wdGlvbnMuY2xpZW50O1xuICAgIHRoaXMuY2xpZW50ID0gb3B0aW9ucy5jbGllbnQ7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0IGEge0BsaW5rIERhdGFicmlja3NGaWxlU3lzdGVtfSwgcmVzb2x2aW5nIGB+YCByb290cyB2aWEgdGhlXG4gICAqIHdvcmtzcGFjZSBjdXJyZW50IHVzZXIgd2hlbiBuZWVkZWQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgY3JlYXRlKG9wdGlvbnM6IERhdGFicmlja3NGaWxlU3lzdGVtT3B0aW9ucyk6IFByb21pc2U8RGF0YWJyaWNrc0ZpbGVTeXN0ZW0+IHtcbiAgICBpZiAoIWlzSG9tZVJlbGF0aXZlUGF0aChvcHRpb25zLnJvb3QpIHx8IG9wdGlvbnMudXNlck5hbWU/LnRyaW0oKSkge1xuICAgICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzRmlsZVN5c3RlbShvcHRpb25zKTtcbiAgICB9XG4gICAgY29uc3QgY2xpZW50ID0gb3B0aW9ucy5jbGllbnQgPz8gKGF3YWl0IGdldFdvcmtzcGFjZUNsaWVudCgpKTtcbiAgICBjb25zdCByb290ID0gYXdhaXQgcmVzb2x2ZURhdGFicmlja3NSb290KG9wdGlvbnMucm9vdCwgeyBjbGllbnQgfSk7XG4gICAgcmV0dXJuIG5ldyBEYXRhYnJpY2tzRmlsZVN5c3RlbSh7IC4uLm9wdGlvbnMsIHJvb3QsIGNsaWVudCB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBvbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5jbGllbnQgPSB0aGlzLmNsaWVudE9wdGlvbiA/PyAoYXdhaXQgZ2V0V29ya3NwYWNlQ2xpZW50KCkpO1xuICB9XG5cbiAgLyoqIFJ1biB0aGUgaGFuZGxlciBmb3IgYGFic29sdXRlUGF0aGAncyBEYXRhYnJpY2tzIEFQSSB3aXRoIHRoZSBsaXZlIGNsaWVudC4gKi9cbiAgcHJpdmF0ZSBkaXNwYXRjaDxUPihhYnNvbHV0ZVBhdGg6IHN0cmluZywgaGFuZGxlcnM6IEJhY2tlbmRIYW5kbGVyczxUPik6IFByb21pc2U8VD4ge1xuICAgIGlmICghdGhpcy5jbGllbnQpIHtcbiAgICAgIHRocm93IG5ldyBGaWxlU3lzdGVtRXJyb3IoXG4gICAgICAgIFwiSU9fRVJST1JcIixcbiAgICAgICAgXCJEYXRhYnJpY2tzIGZpbGVzeXN0ZW0gaXMgbm90IGluaXRpYWxpemVkIChubyBXb3Jrc3BhY2VDbGllbnQpXCIsXG4gICAgICAgIGFic29sdXRlUGF0aCxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBoYW5kbGVyc1tyZXNvbHZlRGF0YWJyaWNrc0ZpbGVzQmFja2VuZChhYnNvbHV0ZVBhdGgpXSh0aGlzLmNsaWVudCk7XG4gIH1cblxuICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgLyogUHJpbWl0aXZlcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4gIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBjcmVhdGVSb290RGlyZWN0b3J5KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuY3JlYXRlRGlyZWN0b3J5QXQodGhpcy5yb290KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyByZWFkQnl0ZXNBdChyZXNvbHZlZFBhdGg6IHN0cmluZyk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IHRoaXMuZGlzcGF0Y2g8QnVmZmVyPihyZXNvbHZlZFBhdGgsIHtcbiAgICAgIGRiZnM6IChjbGllbnQpID0+IHRoaXMucmVhZERiZnNGaWxlKGNsaWVudCwgcmVzb2x2ZWRQYXRoKSxcbiAgICAgIHdvcmtzcGFjZTogYXN5bmMgKGNsaWVudCkgPT4ge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC53b3Jrc3BhY2UuZXhwb3J0KHsgcGF0aDogcmVzb2x2ZWRQYXRoLCBmb3JtYXQ6IFwiQVVUT1wiIH0pO1xuICAgICAgICByZXR1cm4gZGVjb2RlQmFzZTY0KHJlc3BvbnNlLmNvbnRlbnQpO1xuICAgICAgfSxcbiAgICAgIHZvbHVtZXM6IGFzeW5jIChjbGllbnQpID0+IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZmlsZXMuZG93bmxvYWQoeyBmaWxlX3BhdGg6IHJlc29sdmVkUGF0aCB9KTtcbiAgICAgICAgcmV0dXJuIHJlYWRSZXNwb25zZUJvZHkoXG4gICAgICAgICAgcmVzcG9uc2UuY29udGVudHMgYXMgZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB8IHVuZGVmaW5lZCxcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGJ1ZmZlci5idWZmZXIsIGJ1ZmZlci5ieXRlT2Zmc2V0LCBidWZmZXIuYnl0ZUxlbmd0aCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgd3JpdGVCeXRlc0F0KFxuICAgIHJlc29sdmVkUGF0aDogc3RyaW5nLFxuICAgIGNvbnRlbnQ6IFVpbnQ4QXJyYXksXG4gICAgb3B0aW9uczogUmVxdWlyZWQ8V3JpdGVGaWxlT3B0aW9ucz4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGNvbnRlbnQpO1xuICAgIGNvbnN0IG92ZXJ3cml0ZSA9IG9wdGlvbnMub3ZlcndyaXRlO1xuICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2g8dW5rbm93bj4ocmVzb2x2ZWRQYXRoLCB7XG4gICAgICBkYmZzOiAoY2xpZW50KSA9PiB0aGlzLndyaXRlRGJmc0ZpbGUoY2xpZW50LCByZXNvbHZlZFBhdGgsIGJ1ZmZlciwgb3ZlcndyaXRlKSxcbiAgICAgIHdvcmtzcGFjZTogKGNsaWVudCkgPT5cbiAgICAgICAgY2xpZW50LndvcmtzcGFjZS5pbXBvcnQoe1xuICAgICAgICAgIHBhdGg6IHJlc29sdmVkUGF0aCxcbiAgICAgICAgICBmb3JtYXQ6IFwiQVVUT1wiLFxuICAgICAgICAgIGNvbnRlbnQ6IGJ1ZmZlci50b1N0cmluZyhcImJhc2U2NFwiKSxcbiAgICAgICAgICBvdmVyd3JpdGUsXG4gICAgICAgIH0pLFxuICAgICAgdm9sdW1lczogKGNsaWVudCkgPT5cbiAgICAgICAgY2xpZW50LmZpbGVzLnVwbG9hZCh7XG4gICAgICAgICAgZmlsZV9wYXRoOiByZXNvbHZlZFBhdGgsXG4gICAgICAgICAgY29udGVudHM6IGJ1ZmZlclRvUmVhZGFibGVTdHJlYW0oYnVmZmVyKSBhcyBuZXZlcixcbiAgICAgICAgICBvdmVyd3JpdGUsXG4gICAgICAgIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGRlbGV0ZUZpbGVBdChyZXNvbHZlZFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2g8dW5rbm93bj4ocmVzb2x2ZWRQYXRoLCB7XG4gICAgICBkYmZzOiAoY2xpZW50KSA9PiBjbGllbnQuZGJmcy5kZWxldGUoeyBwYXRoOiByZXNvbHZlZFBhdGgsIHJlY3Vyc2l2ZTogZmFsc2UgfSksXG4gICAgICB3b3Jrc3BhY2U6IChjbGllbnQpID0+IGNsaWVudC53b3Jrc3BhY2UuZGVsZXRlKHsgcGF0aDogcmVzb2x2ZWRQYXRoLCByZWN1cnNpdmU6IGZhbHNlIH0pLFxuICAgICAgdm9sdW1lczogKGNsaWVudCkgPT4gY2xpZW50LmZpbGVzLmRlbGV0ZSh7IGZpbGVfcGF0aDogcmVzb2x2ZWRQYXRoIH0pLFxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZURpcmVjdG9yeUF0KHJlc29sdmVkUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5kaXNwYXRjaDx1bmtub3duPihyZXNvbHZlZFBhdGgsIHtcbiAgICAgIGRiZnM6IChjbGllbnQpID0+IGNsaWVudC5kYmZzLm1rZGlycyh7IHBhdGg6IHJlc29sdmVkUGF0aCB9KSxcbiAgICAgIHdvcmtzcGFjZTogKGNsaWVudCkgPT4gY2xpZW50LndvcmtzcGFjZS5ta2RpcnMoeyBwYXRoOiByZXNvbHZlZFBhdGggfSksXG4gICAgICB2b2x1bWVzOiAoY2xpZW50KSA9PiB0aGlzLmNyZWF0ZVZvbHVtZURpcmVjdG9yaWVzKGNsaWVudCwgcmVzb2x2ZWRQYXRoKSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyByZW1vdmVEaXJlY3RvcnlBdChyZXNvbHZlZFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2g8dW5rbm93bj4ocmVzb2x2ZWRQYXRoLCB7XG4gICAgICBkYmZzOiAoY2xpZW50KSA9PiBjbGllbnQuZGJmcy5kZWxldGUoeyBwYXRoOiByZXNvbHZlZFBhdGgsIHJlY3Vyc2l2ZTogZmFsc2UgfSksXG4gICAgICB3b3Jrc3BhY2U6IChjbGllbnQpID0+IGNsaWVudC53b3Jrc3BhY2UuZGVsZXRlKHsgcGF0aDogcmVzb2x2ZWRQYXRoLCByZWN1cnNpdmU6IGZhbHNlIH0pLFxuICAgICAgdm9sdW1lczogKGNsaWVudCkgPT4gY2xpZW50LmZpbGVzLmRlbGV0ZURpcmVjdG9yeSh7IGRpcmVjdG9yeV9wYXRoOiByZXNvbHZlZFBhdGggfSksXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgbGlzdERpcmVjdG9yeUF0KHJlc29sdmVkUGF0aDogc3RyaW5nKTogUHJvbWlzZTxGaWxlRW50cnlbXT4ge1xuICAgIHJldHVybiB0aGlzLmRpc3BhdGNoPEZpbGVFbnRyeVtdPihyZXNvbHZlZFBhdGgsIHtcbiAgICAgIGRiZnM6IChjbGllbnQpID0+XG4gICAgICAgIGNvbGxlY3QoY2xpZW50LmRiZnMubGlzdCh7IHBhdGg6IHJlc29sdmVkUGF0aCB9KSwgKGluZm8pID0+ICh7XG4gICAgICAgICAgbmFtZTogcG9zaXhQYXRoLmJhc2VuYW1lKGluZm8ucGF0aCA/PyBcIlwiKSxcbiAgICAgICAgICB0eXBlOiBpbmZvLmlzX2RpciA/IFwiZGlyZWN0b3J5XCIgOiBcImZpbGVcIixcbiAgICAgICAgICBzaXplOiBpbmZvLmZpbGVfc2l6ZSxcbiAgICAgICAgfSkpLFxuICAgICAgd29ya3NwYWNlOiAoY2xpZW50KSA9PlxuICAgICAgICBjb2xsZWN0KGNsaWVudC53b3Jrc3BhY2UubGlzdCh7IHBhdGg6IHJlc29sdmVkUGF0aCB9KSwgKGluZm8pID0+ICh7XG4gICAgICAgICAgbmFtZTogcG9zaXhQYXRoLmJhc2VuYW1lKGluZm8ucGF0aCA/PyBcIlwiKSxcbiAgICAgICAgICB0eXBlOiBpbmZvLm9iamVjdF90eXBlID09PSBcIkRJUkVDVE9SWVwiID8gXCJkaXJlY3RvcnlcIiA6IFwiZmlsZVwiLFxuICAgICAgICB9KSksXG4gICAgICB2b2x1bWVzOiAoY2xpZW50KSA9PlxuICAgICAgICBjb2xsZWN0KGNsaWVudC5maWxlcy5saXN0RGlyZWN0b3J5Q29udGVudHMoeyBkaXJlY3RvcnlfcGF0aDogcmVzb2x2ZWRQYXRoIH0pLCAoZW50cnkpID0+ICh7XG4gICAgICAgICAgbmFtZTogZW50cnkubmFtZSA/PyBwb3NpeFBhdGguYmFzZW5hbWUoZW50cnkucGF0aCA/PyBcIlwiKSxcbiAgICAgICAgICB0eXBlOiBlbnRyeS5pc19kaXJlY3RvcnkgPyBcImRpcmVjdG9yeVwiIDogXCJmaWxlXCIsXG4gICAgICAgICAgc2l6ZTogZW50cnkuZmlsZV9zaXplLFxuICAgICAgICB9KSksXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgc3RhdEF0KHJlc29sdmVkUGF0aDogc3RyaW5nKTogUHJvbWlzZTxPbWl0PEZpbGVTdGF0LCBcInBhdGhcIj4+IHtcbiAgICBjb25zdCBmYWxsYmFja05hbWUgPSBwb3NpeFBhdGguYmFzZW5hbWUocmVzb2x2ZWRQYXRoKSB8fCBwb3NpeFBhdGguYmFzZW5hbWUodGhpcy5yb290KTtcbiAgICByZXR1cm4gdGhpcy5kaXNwYXRjaDxPbWl0PEZpbGVTdGF0LCBcInBhdGhcIj4+KHJlc29sdmVkUGF0aCwge1xuICAgICAgZGJmczogYXN5bmMgKGNsaWVudCkgPT4ge1xuICAgICAgICBjb25zdCBpbmZvID0gYXdhaXQgY2xpZW50LmRiZnMuZ2V0U3RhdHVzKHsgcGF0aDogcmVzb2x2ZWRQYXRoIH0pO1xuICAgICAgICBjb25zdCBtb2RpZmllZCA9IG9iamVjdC50b0RhdGUoaW5mby5tb2RpZmljYXRpb25fdGltZSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogcG9zaXhQYXRoLmJhc2VuYW1lKGluZm8ucGF0aCA/PyByZXNvbHZlZFBhdGgpIHx8IGZhbGxiYWNrTmFtZSxcbiAgICAgICAgICB0eXBlOiBpbmZvLmlzX2RpciA/IFwiZGlyZWN0b3J5XCIgOiBcImZpbGVcIixcbiAgICAgICAgICBzaXplOiBpbmZvLmZpbGVfc2l6ZSxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG1vZGlmaWVkLFxuICAgICAgICAgIG1vZGlmaWVkQXQ6IG1vZGlmaWVkLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIHdvcmtzcGFjZTogYXN5bmMgKGNsaWVudCkgPT4ge1xuICAgICAgICBjb25zdCBpbmZvID0gYXdhaXQgY2xpZW50LndvcmtzcGFjZS5nZXRTdGF0dXMoeyBwYXRoOiByZXNvbHZlZFBhdGggfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogcG9zaXhQYXRoLmJhc2VuYW1lKGluZm8ucGF0aCA/PyByZXNvbHZlZFBhdGgpIHx8IGZhbGxiYWNrTmFtZSxcbiAgICAgICAgICB0eXBlOiBpbmZvLm9iamVjdF90eXBlID09PSBcIkRJUkVDVE9SWVwiID8gXCJkaXJlY3RvcnlcIiA6IFwiZmlsZVwiLFxuICAgICAgICAgIGNyZWF0ZWRBdDogb2JqZWN0LnRvRGF0ZShpbmZvLmNyZWF0ZWRfYXQpLFxuICAgICAgICAgIG1vZGlmaWVkQXQ6IG9iamVjdC50b0RhdGUoaW5mby5tb2RpZmllZF9hdCksXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgdm9sdW1lczogKGNsaWVudCkgPT4gdGhpcy5zdGF0Vm9sdW1lUGF0aChjbGllbnQsIHJlc29sdmVkUGF0aCwgZmFsbGJhY2tOYW1lKSxcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyB0cnlNb3ZlRmlsZUF0KFxuICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICBkZXN0aW5hdGlvblBhdGg6IHN0cmluZyxcbiAgICBfb3B0aW9uczogUmVxdWlyZWQ8Q29weU9wdGlvbnM+LFxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBPbmx5IERCRlMgZXhwb3NlcyBhIHNlcnZlci1zaWRlIG1vdmU7IGV2ZXJ5dGhpbmcgZWxzZSBmYWxscyBiYWNrIHRvIHRoZVxuICAgIC8vIHBvcnRhYmxlIGNvcHkgKyBkZWxldGUgaW4gQmFzZUZpbGVTeXN0ZW0uXG4gICAgaWYgKFxuICAgICAgcmVzb2x2ZURhdGFicmlja3NGaWxlc0JhY2tlbmQoc291cmNlUGF0aCkgIT09IFwiZGJmc1wiIHx8XG4gICAgICByZXNvbHZlRGF0YWJyaWNrc0ZpbGVzQmFja2VuZChkZXN0aW5hdGlvblBhdGgpICE9PSBcImRiZnNcIlxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLmRpc3BhdGNoPHVua25vd24+KHNvdXJjZVBhdGgsIHtcbiAgICAgIGRiZnM6IChjbGllbnQpID0+XG4gICAgICAgIGNsaWVudC5kYmZzLm1vdmUoeyBzb3VyY2VfcGF0aDogc291cmNlUGF0aCwgZGVzdGluYXRpb25fcGF0aDogZGVzdGluYXRpb25QYXRoIH0pLFxuICAgICAgd29ya3NwYWNlOiB1bnJlYWNoYWJsZUJhY2tlbmQsXG4gICAgICB2b2x1bWVzOiB1bnJlYWNoYWJsZUJhY2tlbmQsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cbiAgLyogQmFja2VuZC1zcGVjaWZpYyBJL08gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4gIC8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gIC8qKlxuICAgKiBVQyBgY3JlYXRlRGlyZWN0b3J5YCBpcyBzaW5nbGUtbGV2ZWwsIHNvIHdhbGsgdGhlIHBhdGggY3JlYXRpbmcgZWFjaCBsZXZlbFxuICAgKiBiZWxvdyB0aGUgdm9sdW1lIGl0c2VsZi4gQSBsZXZlbCB0aGF0IGFscmVhZHkgZXhpc3RzIGlzIG5vdCBhbiBlcnJvci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY3JlYXRlVm9sdW1lRGlyZWN0b3JpZXMoXG4gICAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gICAgYWJzb2x1dGVQYXRoOiBzdHJpbmcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBhcnRzID0gYWJzb2x1dGVQYXRoLnNwbGl0KFwiL1wiKS5maWx0ZXIoQm9vbGVhbik7XG4gICAgbGV0IGN1cnJlbnQgPSBcIlwiO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGN1cnJlbnQgPSBgJHtjdXJyZW50fS8ke3BhcnRzW2ldfWA7XG4gICAgICBpZiAoaSA8IFZPTFVNRV9ST09UX0RFUFRIKSBjb250aW51ZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5maWxlcy5jcmVhdGVEaXJlY3RvcnkoeyBkaXJlY3RvcnlfcGF0aDogY3VycmVudCB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBBbHJlYWR5IHByZXNlbnQgaXMgZmluZTsgYW55dGhpbmcgZWxzZSBpcyBhIHJlYWwgZmFpbHVyZS5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBjbGllbnQuZmlsZXMuZ2V0RGlyZWN0b3J5TWV0YWRhdGEoeyBkaXJlY3RvcnlfcGF0aDogY3VycmVudCB9KTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIFN0YXQgYSBVQyBwYXRoOiBmaWxlIG1ldGFkYXRhIGZpcnN0LCB0aGVuIGEgZGlyZWN0b3J5IHByb2JlLiAqL1xuICBwcml2YXRlIGFzeW5jIHN0YXRWb2x1bWVQYXRoKFxuICAgIGNsaWVudDogV29ya3NwYWNlQ2xpZW50LFxuICAgIGFic29sdXRlUGF0aDogc3RyaW5nLFxuICAgIGZhbGxiYWNrTmFtZTogc3RyaW5nLFxuICApOiBQcm9taXNlPE9taXQ8RmlsZVN0YXQsIFwicGF0aFwiPj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGF3YWl0IGNsaWVudC5maWxlcy5nZXRNZXRhZGF0YSh7IGZpbGVfcGF0aDogYWJzb2x1dGVQYXRoIH0pO1xuICAgICAgY29uc3QgbW9kaWZpZWQgPSBvYmplY3QudG9EYXRlKG1ldGFkYXRhW1wibGFzdC1tb2RpZmllZFwiXSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBmYWxsYmFja05hbWUsXG4gICAgICAgIHR5cGU6IFwiZmlsZVwiLFxuICAgICAgICBzaXplOiBOdW1iZXIobWV0YWRhdGFbXCJjb250ZW50LWxlbmd0aFwiXSA/PyAwKSxcbiAgICAgICAgY3JlYXRlZEF0OiBtb2RpZmllZCxcbiAgICAgICAgbW9kaWZpZWRBdDogbW9kaWZpZWQsXG4gICAgICAgIG1pbWVUeXBlOiBtZXRhZGF0YVtcImNvbnRlbnQtdHlwZVwiXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZmlsZUVycikge1xuICAgICAgLy8gQSBkaXJlY3RvcnkgaGFzIG5vIGZpbGUgbWV0YWRhdGEsIGFuZCBhbiB1bnJlYWRhYmxlIG9uZSByZXBvcnRzIGFzXG4gICAgICAvLyBtaXNzaW5nIC8gZGVuaWVkIC0gYm90aCBhcmUgd29ydGggYSBkaXJlY3RvcnkgcHJvYmUgYmVmb3JlIGZhaWxpbmcuXG4gICAgICBjb25zdCBjb2RlID0gYmFzZUZTLm1hcEZpbGVTeXN0ZW1FcnJvcihmaWxlRXJyLCBhYnNvbHV0ZVBhdGgpLmNvZGU7XG4gICAgICBpZiAoY29kZSAhPT0gXCJOT1RfRk9VTkRcIiAmJiBjb2RlICE9PSBcIlBFUk1JU1NJT05fREVOSUVEXCIpIHRocm93IGZpbGVFcnI7XG4gICAgICBhd2FpdCBjbGllbnQuZmlsZXMuZ2V0RGlyZWN0b3J5TWV0YWRhdGEoeyBkaXJlY3RvcnlfcGF0aDogYWJzb2x1dGVQYXRoIH0pO1xuICAgICAgcmV0dXJuIHsgbmFtZTogZmFsbGJhY2tOYW1lLCB0eXBlOiBcImRpcmVjdG9yeVwiIH07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWFkRGJmc0ZpbGUoY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsIGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICBjb25zdCBjaHVua3M6IEJ1ZmZlcltdID0gW107XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmRiZnMucmVhZCh7XG4gICAgICAgIHBhdGg6IGFic29sdXRlUGF0aCxcbiAgICAgICAgb2Zmc2V0LFxuICAgICAgICBsZW5ndGg6IERCRlNfUkVBRF9DSFVOS19CWVRFUyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgY2h1bmsgPSBkZWNvZGVCYXNlNjQocmVzcG9uc2UuZGF0YSk7XG4gICAgICBpZiAoY2h1bmsubGVuZ3RoID09PSAwKSBicmVhaztcbiAgICAgIGNodW5rcy5wdXNoKGNodW5rKTtcbiAgICAgIG9mZnNldCArPSBjaHVuay5sZW5ndGg7XG4gICAgICBpZiAoY2h1bmsubGVuZ3RoIDwgREJGU19SRUFEX0NIVU5LX0JZVEVTKSBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIEJ1ZmZlci5jb25jYXQoY2h1bmtzKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgd3JpdGVEYmZzRmlsZShcbiAgICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCxcbiAgICBhYnNvbHV0ZVBhdGg6IHN0cmluZyxcbiAgICBidWZmZXI6IEJ1ZmZlcixcbiAgICBvdmVyd3JpdGU6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChidWZmZXIubGVuZ3RoIDw9IERCRlNfUFVUX01BWF9CWVRFUykge1xuICAgICAgYXdhaXQgY2xpZW50LmRiZnMucHV0KHtcbiAgICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgICBjb250ZW50czogYnVmZmVyLnRvU3RyaW5nKFwiYmFzZTY0XCIpLFxuICAgICAgICBvdmVyd3JpdGUsXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IGNsaWVudC5kYmZzLmNyZWF0ZSh7IHBhdGg6IGFic29sdXRlUGF0aCwgb3ZlcndyaXRlIH0pO1xuICAgIGNvbnN0IGhhbmRsZSA9IGNyZWF0ZWQuaGFuZGxlO1xuICAgIGlmIChoYW5kbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEZpbGVTeXN0ZW1FcnJvcihcIklPX0VSUk9SXCIsIFwiREJGUyB1cGxvYWQgaGFuZGxlIG1pc3NpbmdcIiwgYWJzb2x1dGVQYXRoKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGJ1ZmZlci5sZW5ndGg7IG9mZnNldCArPSBEQkZTX1BVVF9NQVhfQllURVMpIHtcbiAgICAgICAgY29uc3Qgc2xpY2UgPSBidWZmZXIuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBEQkZTX1BVVF9NQVhfQllURVMpO1xuICAgICAgICBhd2FpdCBjbGllbnQuZGJmcy5hZGRCbG9jayh7IGhhbmRsZSwgZGF0YTogc2xpY2UudG9TdHJpbmcoXCJiYXNlNjRcIikgfSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBhd2FpdCBjbGllbnQuZGJmcy5jbG9zZSh7IGhhbmRsZSB9KS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbiAgICBhd2FpdCBjbGllbnQuZGJmcy5jbG9zZSh7IGhhbmRsZSB9KTtcbiAgfVxufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaGVscGVycyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuLyoqIERyYWluIGFuIFNESyBhc3luYyBpdGVyYWJsZSBpbnRvIGEgbWFwcGVkIGFycmF5LiAqL1xuYXN5bmMgZnVuY3Rpb24gY29sbGVjdDxTLCBUPihzb3VyY2U6IEFzeW5jSXRlcmFibGU8Uz4sIG1hcDogKGl0ZW06IFMpID0+IFQpOiBQcm9taXNlPFRbXT4ge1xuICBjb25zdCBpdGVtczogVFtdID0gW107XG4gIGZvciBhd2FpdCAoY29uc3QgaXRlbSBvZiBzb3VyY2UpIGl0ZW1zLnB1c2gobWFwKGl0ZW0pKTtcbiAgcmV0dXJuIGl0ZW1zO1xufVxuXG4vKiogSGFuZGxlciBmb3IgYSBiYWNrZW5kIGEgY2FsbCBzaXRlIGhhcyBhbHJlYWR5IHJ1bGVkIG91dC4gKi9cbmZ1bmN0aW9uIHVucmVhY2hhYmxlQmFja2VuZCgpOiBQcm9taXNlPG5ldmVyPiB7XG4gIHRocm93IG5ldyBGaWxlU3lzdGVtRXJyb3IoXCJOT1RfU1VQUE9SVEVEXCIsIFwiVW5zdXBwb3J0ZWQgRGF0YWJyaWNrcyBiYWNrZW5kIGZvciB0aGlzIG9wZXJhdGlvblwiKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlQmFzZTY0KGRhdGE6IHN0cmluZyB8IHVuZGVmaW5lZCk6IEJ1ZmZlciB7XG4gIGlmICghZGF0YSkgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKTtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEsIFwiYmFzZTY0XCIpO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkUmVzcG9uc2VCb2R5KFxuICBjb250ZW50czogZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB8IHVuZGVmaW5lZCxcbik6IFByb21pc2U8QnVmZmVyPiB7XG4gIGlmICghY29udGVudHMpIHJldHVybiBCdWZmZXIuYWxsb2MoMCk7XG4gIGNvbnN0IHJlYWRlciA9IGNvbnRlbnRzLmdldFJlYWRlcigpO1xuICBjb25zdCBjaHVua3M6IFVpbnQ4QXJyYXlbXSA9IFtdO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGRvbmUpIGJyZWFrO1xuICAgIGlmICh2YWx1ZSkgY2h1bmtzLnB1c2godmFsdWUpO1xuICB9XG4gIHJldHVybiBCdWZmZXIuY29uY2F0KGNodW5rcy5tYXAoKGNodW5rKSA9PiBCdWZmZXIuZnJvbShjaHVuaykpKTtcbn1cblxuZnVuY3Rpb24gYnVmZmVyVG9SZWFkYWJsZVN0cmVhbShidWZmZXI6IEJ1ZmZlcik6IGdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4ge1xuICByZXR1cm4gbmV3IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+KHtcbiAgICBzdGFydChjb250cm9sbGVyKSB7XG4gICAgICBjb250cm9sbGVyLmVucXVldWUobmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSk7XG4gICAgICBjb250cm9sbGVyLmNsb3NlKCk7XG4gICAgfSxcbiAgfSk7XG59XG4iXX0=
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databricks path recognition and normalization for {@link DatabricksFileSystem}.
|
|
3
|
+
*
|
|
4
|
+
* Roots may be written as:
|
|
5
|
+
* - Unity Catalog volume: `/Volumes/catalog/schema/volume` (also accepts `/Volume/...`)
|
|
6
|
+
* - Three-part volume id: `catalog.schema.volume` → `/Volumes/catalog/schema/volume`
|
|
7
|
+
* - Home shorthand: `~` / `~/...` → `/Workspace/Users/<userName>/...`
|
|
8
|
+
* - Workspace tree: `/Workspace/...`, `/Users/...`, `/Repos/...`, `/Shared/...`
|
|
9
|
+
* - DBFS: `/dbfs/...`
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { posixPath } from "@dbx-tools/shared-fs";
|
|
14
|
+
import { type WorkspaceClient } from "./workspace.ts";
|
|
15
|
+
/** Which Databricks Files API serves an absolute path. */
|
|
16
|
+
export type DatabricksFilesBackend = "workspace" | "volumes" | "dbfs";
|
|
17
|
+
/** Options for synchronous {@link normalizeDatabricksRoot}. */
|
|
18
|
+
export interface NormalizeDatabricksRootOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Username used to expand `~` → `/Workspace/Users/<userName>`.
|
|
21
|
+
* Required when {@link root} is `~` or `~/...`. Prefer
|
|
22
|
+
* {@link resolveDatabricksRoot} when the name should come from the workspace
|
|
23
|
+
* client.
|
|
24
|
+
*/
|
|
25
|
+
userName?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Options for async {@link resolveDatabricksRoot}. */
|
|
28
|
+
export interface ResolveDatabricksRootOptions {
|
|
29
|
+
/** Client used to resolve the current username for `~` expansion. */
|
|
30
|
+
client?: WorkspaceClient;
|
|
31
|
+
}
|
|
32
|
+
/** True when {@link input} is `~` or a path under `~/`. See {@link posixPath.isHomeRelativePath}. */
|
|
33
|
+
export declare const isHomeRelativePath: typeof posixPath.isHomeRelativePath;
|
|
34
|
+
/**
|
|
35
|
+
* Expand `~` / `~/...` to `/Workspace/Users/<userName>/...`.
|
|
36
|
+
* Non-home inputs are returned unchanged (POSIX separators only).
|
|
37
|
+
*/
|
|
38
|
+
export declare function expandHomePath(input: string, userName: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Normalize a Databricks filesystem root to an absolute POSIX path.
|
|
41
|
+
*
|
|
42
|
+
* - `catalog.schema.volume` → `/Volumes/catalog/schema/volume`
|
|
43
|
+
* - `/Volume/...` → `/Volumes/...` (singular typo / shorthand)
|
|
44
|
+
* - `~` / `~/...` → `/Workspace/Users/<userName>/...` (needs {@link NormalizeDatabricksRootOptions.userName})
|
|
45
|
+
* - strips trailing slashes (except `/`)
|
|
46
|
+
*
|
|
47
|
+
* For `~` without a known username, use {@link resolveDatabricksRoot}.
|
|
48
|
+
*/
|
|
49
|
+
export declare function normalizeDatabricksRoot(root: string, options?: NormalizeDatabricksRootOptions): string;
|
|
50
|
+
/**
|
|
51
|
+
* Like {@link normalizeDatabricksRoot}, but resolves `~` via
|
|
52
|
+
* {@link getCurrentUserName} (AppKit context user, else `currentUser.me()`).
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveDatabricksRoot(root: string, options?: ResolveDatabricksRootOptions): Promise<string>;
|
|
55
|
+
/** True when {@link absolutePath} is served by the workspace objects API. */
|
|
56
|
+
export declare function isWorkspaceFilesPath(absolutePath: string): boolean;
|
|
57
|
+
/** True when {@link absolutePath} is a Unity Catalog volume path. */
|
|
58
|
+
export declare function isVolumesPath(absolutePath: string): boolean;
|
|
59
|
+
/** True when {@link absolutePath} is a DBFS path. */
|
|
60
|
+
export declare function isDbfsPath(absolutePath: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Pick the Databricks API backend for an absolute path.
|
|
63
|
+
*
|
|
64
|
+
* Volume three-part roots are normalized before this runs, so callers should
|
|
65
|
+
* pass paths from {@link normalizeDatabricksRoot} / {@link BaseFileSystem.resolvePath}.
|
|
66
|
+
*/
|
|
67
|
+
export declare function resolveDatabricksFilesBackend(absolutePath: string): DatabricksFilesBackend;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databricks path recognition and normalization for {@link DatabricksFileSystem}.
|
|
3
|
+
*
|
|
4
|
+
* Roots may be written as:
|
|
5
|
+
* - Unity Catalog volume: `/Volumes/catalog/schema/volume` (also accepts `/Volume/...`)
|
|
6
|
+
* - Three-part volume id: `catalog.schema.volume` → `/Volumes/catalog/schema/volume`
|
|
7
|
+
* - Home shorthand: `~` / `~/...` → `/Workspace/Users/<userName>/...`
|
|
8
|
+
* - Workspace tree: `/Workspace/...`, `/Users/...`, `/Repos/...`, `/Shared/...`
|
|
9
|
+
* - DBFS: `/dbfs/...`
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { posixPath } from "@dbx-tools/shared-fs";
|
|
14
|
+
import { getCurrentUserName } from "./workspace.js";
|
|
15
|
+
/** `catalog.schema.volume` (no slashes, exactly three dotted segments). */
|
|
16
|
+
const VOLUME_THREE_PART = /^([^.\/\s]+)\.([^.\/\s]+)\.([^.\/\s]+)$/;
|
|
17
|
+
/** True when {@link input} is `~` or a path under `~/`. See {@link posixPath.isHomeRelativePath}. */
|
|
18
|
+
export const isHomeRelativePath = posixPath.isHomeRelativePath;
|
|
19
|
+
/**
|
|
20
|
+
* Expand `~` / `~/...` to `/Workspace/Users/<userName>/...`.
|
|
21
|
+
* Non-home inputs are returned unchanged (POSIX separators only).
|
|
22
|
+
*/
|
|
23
|
+
export function expandHomePath(input, userName) {
|
|
24
|
+
const name = userName.trim();
|
|
25
|
+
if (!name) {
|
|
26
|
+
throw new TypeError("Databricks home expansion requires a non-empty userName");
|
|
27
|
+
}
|
|
28
|
+
if (!isHomeRelativePath(input)) {
|
|
29
|
+
return posixPath.toPosix(input.trim());
|
|
30
|
+
}
|
|
31
|
+
return posixPath.expandHome(input, `/Workspace/Users/${name}`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Normalize a Databricks filesystem root to an absolute POSIX path.
|
|
35
|
+
*
|
|
36
|
+
* - `catalog.schema.volume` → `/Volumes/catalog/schema/volume`
|
|
37
|
+
* - `/Volume/...` → `/Volumes/...` (singular typo / shorthand)
|
|
38
|
+
* - `~` / `~/...` → `/Workspace/Users/<userName>/...` (needs {@link NormalizeDatabricksRootOptions.userName})
|
|
39
|
+
* - strips trailing slashes (except `/`)
|
|
40
|
+
*
|
|
41
|
+
* For `~` without a known username, use {@link resolveDatabricksRoot}.
|
|
42
|
+
*/
|
|
43
|
+
export function normalizeDatabricksRoot(root, options = {}) {
|
|
44
|
+
const trimmed = root.trim();
|
|
45
|
+
if (!trimmed) {
|
|
46
|
+
throw new TypeError("Databricks filesystem root cannot be empty");
|
|
47
|
+
}
|
|
48
|
+
if (isHomeRelativePath(trimmed)) {
|
|
49
|
+
if (!options.userName?.trim()) {
|
|
50
|
+
throw new TypeError(`Databricks home path "${root}" requires userName; use resolveDatabricksRoot() or pass userName`);
|
|
51
|
+
}
|
|
52
|
+
return posixPath.normalizeRoot(expandHomePath(trimmed, options.userName));
|
|
53
|
+
}
|
|
54
|
+
const threePart = VOLUME_THREE_PART.exec(trimmed);
|
|
55
|
+
if (threePart) {
|
|
56
|
+
return posixPath.normalizeRoot(`/Volumes/${threePart[1]}/${threePart[2]}/${threePart[3]}`);
|
|
57
|
+
}
|
|
58
|
+
let posix = posixPath.toPosix(trimmed);
|
|
59
|
+
if (posix === "/Volume" || posix.startsWith("/Volume/")) {
|
|
60
|
+
posix = `/Volumes${posix.slice("/Volume".length)}`;
|
|
61
|
+
}
|
|
62
|
+
if (!posixPath.isAbsolute(posix)) {
|
|
63
|
+
throw new TypeError(`Databricks filesystem root must be absolute, catalog.schema.volume, or ~, got: ${root}`);
|
|
64
|
+
}
|
|
65
|
+
return posixPath.normalizeRoot(posix);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Like {@link normalizeDatabricksRoot}, but resolves `~` via
|
|
69
|
+
* {@link getCurrentUserName} (AppKit context user, else `currentUser.me()`).
|
|
70
|
+
*/
|
|
71
|
+
export async function resolveDatabricksRoot(root, options = {}) {
|
|
72
|
+
if (!isHomeRelativePath(root)) {
|
|
73
|
+
return normalizeDatabricksRoot(root);
|
|
74
|
+
}
|
|
75
|
+
const userName = await getCurrentUserName(options.client);
|
|
76
|
+
return normalizeDatabricksRoot(root, { userName });
|
|
77
|
+
}
|
|
78
|
+
/** True when {@link absolutePath} is served by the workspace objects API. */
|
|
79
|
+
export function isWorkspaceFilesPath(absolutePath) {
|
|
80
|
+
const p = posixPath.toPosix(absolutePath);
|
|
81
|
+
return (p === "/Workspace" ||
|
|
82
|
+
p.startsWith("/Workspace/") ||
|
|
83
|
+
p.startsWith("/Users/") ||
|
|
84
|
+
p.startsWith("/Repos/") ||
|
|
85
|
+
p.startsWith("/Shared/"));
|
|
86
|
+
}
|
|
87
|
+
/** True when {@link absolutePath} is a Unity Catalog volume path. */
|
|
88
|
+
export function isVolumesPath(absolutePath) {
|
|
89
|
+
const p = posixPath.toPosix(absolutePath);
|
|
90
|
+
return p === "/Volumes" || p.startsWith("/Volumes/");
|
|
91
|
+
}
|
|
92
|
+
/** True when {@link absolutePath} is a DBFS path. */
|
|
93
|
+
export function isDbfsPath(absolutePath) {
|
|
94
|
+
const p = posixPath.toPosix(absolutePath);
|
|
95
|
+
return p === "/dbfs" || p.startsWith("/dbfs/");
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Pick the Databricks API backend for an absolute path.
|
|
99
|
+
*
|
|
100
|
+
* Volume three-part roots are normalized before this runs, so callers should
|
|
101
|
+
* pass paths from {@link normalizeDatabricksRoot} / {@link BaseFileSystem.resolvePath}.
|
|
102
|
+
*/
|
|
103
|
+
export function resolveDatabricksFilesBackend(absolutePath) {
|
|
104
|
+
if (isDbfsPath(absolutePath))
|
|
105
|
+
return "dbfs";
|
|
106
|
+
if (isWorkspaceFilesPath(absolutePath))
|
|
107
|
+
return "workspace";
|
|
108
|
+
if (isVolumesPath(absolutePath))
|
|
109
|
+
return "volumes";
|
|
110
|
+
// Default: UC Files API (covers unusual absolute roots under the workspace host).
|
|
111
|
+
return "volumes";
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJyaWNrcy1wYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RhdGFicmlja3MtcGF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7R0FXRztBQUVILE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNqRCxPQUFPLEVBQUUsa0JBQWtCLEVBQXdCLE1BQU0sZ0JBQWdCLENBQUM7QUFLMUUsMkVBQTJFO0FBQzNFLE1BQU0saUJBQWlCLEdBQUcseUNBQXlDLENBQUM7QUFtQnBFLHFHQUFxRztBQUNyRyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUM7QUFFL0Q7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFhLEVBQUUsUUFBZ0I7SUFDNUQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzdCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNWLE1BQU0sSUFBSSxTQUFTLENBQUMseURBQXlELENBQUMsQ0FBQztJQUNqRixDQUFDO0lBQ0QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDL0IsT0FBTyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLG9CQUFvQixJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ2pFLENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsdUJBQXVCLENBQ3JDLElBQVksRUFDWixVQUEwQyxFQUFFO0lBRTVDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUM1QixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixNQUFNLElBQUksU0FBUyxDQUFDLDRD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Q0FBQyxRQUFRLENBQUMsQ0FBQztBQUNqRCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsNkJBQTZCLENBQUMsWUFBb0I7SUFDaEUsSUFBSSxVQUFVLENBQUMsWUFBWSxDQUFDO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDNUMsSUFBSSxvQkFBb0IsQ0FBQyxZQUFZLENBQUM7UUFBRSxPQUFPLFdBQVcsQ0FBQztJQUMzRCxJQUFJLGFBQWEsQ0FBQyxZQUFZLENBQUM7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNsRCxrRkFBa0Y7SUFDbEYsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGF0YWJyaWNrcyBwYXRoIHJlY29nbml0aW9uIGFuZCBub3JtYWxpemF0aW9uIGZvciB7QGxpbmsgRGF0YWJyaWNrc0ZpbGVTeXN0ZW19LlxuICpcbiAqIFJvb3RzIG1heSBiZSB3cml0dGVuIGFzOlxuICogLSBVbml0eSBDYXRhbG9nIHZvbHVtZTogYC9Wb2x1bWVzL2NhdGFsb2cvc2NoZW1hL3ZvbHVtZWAgKGFsc28gYWNjZXB0cyBgL1ZvbHVtZS8uLi5gKVxuICogLSBUaHJlZS1wYXJ0IHZvbHVtZSBpZDogYGNhdGFsb2cuc2NoZW1hLnZvbHVtZWAg4oaSIGAvVm9sdW1lcy9jYXRhbG9nL3NjaGVtYS92b2x1bWVgXG4gKiAtIEhvbWUgc2hvcnRoYW5kOiBgfmAgLyBgfi8uLi5gIOKGkiBgL1dvcmtzcGFjZS9Vc2Vycy88dXNlck5hbWU+Ly4uLmBcbiAqIC0gV29ya3NwYWNlIHRyZWU6IGAvV29ya3NwYWNlLy4uLmAsIGAvVXNlcnMvLi4uYCwgYC9SZXBvcy8uLi5gLCBgL1NoYXJlZC8uLi5gXG4gKiAtIERCRlM6IGAvZGJmcy8uLi5gXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHBvc2l4UGF0aCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1mc1wiO1xuaW1wb3J0IHsgZ2V0Q3VycmVudFVzZXJOYW1lLCB0eXBlIFdvcmtzcGFjZUNsaWVudCB9IGZyb20gXCIuL3dvcmtzcGFjZS50c1wiO1xuXG4vKiogV2hpY2ggRGF0YWJyaWNrcyBGaWxlcyBBUEkgc2VydmVzIGFuIGFic29sdXRlIHBhdGguICovXG5leHBvcnQgdHlwZSBEYXRhYnJpY2tzRmlsZXNCYWNrZW5kID0gXCJ3b3Jrc3BhY2VcIiB8IFwidm9sdW1lc1wiIHwgXCJkYmZzXCI7XG5cbi8qKiBgY2F0YWxvZy5zY2hlbWEudm9sdW1lYCAobm8gc2xhc2hlcywgZXhhY3RseSB0aHJlZSBkb3R0ZWQgc2VnbWVudHMpLiAqL1xuY29uc3QgVk9MVU1FX1RIUkVFX1BBUlQgPSAvXihbXi5cXC9cXHNdKylcXC4oW14uXFwvXFxzXSspXFwuKFteLlxcL1xcc10rKSQvO1xuXG4vKiogT3B0aW9ucyBmb3Igc3luY2hyb25vdXMge0BsaW5rIG5vcm1hbGl6ZURhdGFicmlja3NSb290fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9ybWFsaXplRGF0YWJyaWNrc1Jvb3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIFVzZXJuYW1lIHVzZWQgdG8gZXhwYW5kIGB+YCDihpIgYC9Xb3Jrc3BhY2UvVXNlcnMvPHVzZXJOYW1lPmAuXG4gICAqIFJlcXVpcmVkIHdoZW4ge0BsaW5rIHJvb3R9IGlzIGB+YCBvciBgfi8uLi5gLiBQcmVmZXJcbiAgICoge0BsaW5rIHJlc29sdmVEYXRhYnJpY2tzUm9vdH0gd2hlbiB0aGUgbmFtZSBzaG91bGQgY29tZSBmcm9tIHRoZSB3b3Jrc3BhY2VcbiAgICogY2xpZW50LlxuICAgKi9cbiAgdXNlck5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKiBPcHRpb25zIGZvciBhc3luYyB7QGxpbmsgcmVzb2x2ZURhdGFicmlja3NSb290fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZURhdGFicmlja3NSb290T3B0aW9ucyB7XG4gIC8qKiBDbGllbnQgdXNlZCB0byByZXNvbHZlIHRoZSBjdXJyZW50IHVzZXJuYW1lIGZvciBgfmAgZXhwYW5zaW9uLiAqL1xuICBjbGllbnQ/OiBXb3Jrc3BhY2VDbGllbnQ7XG59XG5cbi8qKiBUcnVlIHdoZW4ge0BsaW5rIGlucHV0fSBpcyBgfmAgb3IgYSBwYXRoIHVuZGVyIGB+L2AuIFNlZSB7QGxpbmsgcG9zaXhQYXRoLmlzSG9tZVJlbGF0aXZlUGF0aH0uICovXG5leHBvcnQgY29uc3QgaXNIb21lUmVsYXRpdmVQYXRoID0gcG9zaXhQYXRoLmlzSG9tZVJlbGF0aXZlUGF0aDtcblxuLyoqXG4gKiBFeHBhbmQgYH5gIC8gYH4vLi4uYCB0byBgL1dvcmtzcGFjZS9Vc2Vycy88dXNlck5hbWU+Ly4uLmAuXG4gKiBOb24taG9tZSBpbnB1dHMgYXJlIHJldHVybmVkIHVuY2hhbmdlZCAoUE9TSVggc2VwYXJhdG9ycyBvbmx5KS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4cGFuZEhvbWVQYXRoKGlucHV0OiBzdHJpbmcsIHVzZXJOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBuYW1lID0gdXNlck5hbWUudHJpbSgpO1xuICBpZiAoIW5hbWUpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRGF0YWJyaWNrcyBob21lIGV4cGFuc2lvbiByZXF1aXJlcyBhIG5vbi1lbXB0eSB1c2VyTmFtZVwiKTtcbiAgfVxuICBpZiAoIWlzSG9tZVJlbGF0aXZlUGF0aChpbnB1dCkpIHtcbiAgICByZXR1cm4gcG9zaXhQYXRoLnRvUG9zaXgoaW5wdXQudHJpbSgpKTtcbiAgfVxuICByZXR1cm4gcG9zaXhQYXRoLmV4cGFuZEhvbWUoaW5wdXQsIGAvV29ya3NwYWNlL1VzZXJzLyR7bmFtZX1gKTtcbn1cblxuLyoqXG4gKiBOb3JtYWxpemUgYSBEYXRhYnJpY2tzIGZpbGVzeXN0ZW0gcm9vdCB0byBhbiBhYnNvbHV0ZSBQT1NJWCBwYXRoLlxuICpcbiAqIC0gYGNhdGFsb2cuc2NoZW1hLnZvbHVtZWAg4oaSIGAvVm9sdW1lcy9jYXRhbG9nL3NjaGVtYS92b2x1bWVgXG4gKiAtIGAvVm9sdW1lLy4uLmAg4oaSIGAvVm9sdW1lcy8uLi5gIChzaW5ndWxhciB0eXBvIC8gc2hvcnRoYW5kKVxuICogLSBgfmAgLyBgfi8uLi5gIOKGkiBgL1dvcmtzcGFjZS9Vc2Vycy88dXNlck5hbWU+Ly4uLmAgKG5lZWRzIHtAbGluayBOb3JtYWxpemVEYXRhYnJpY2tzUm9vdE9wdGlvbnMudXNlck5hbWV9KVxuICogLSBzdHJpcHMgdHJhaWxpbmcgc2xhc2hlcyAoZXhjZXB0IGAvYClcbiAqXG4gKiBGb3IgYH5gIHdpdGhvdXQgYSBrbm93biB1c2VybmFtZSwgdXNlIHtAbGluayByZXNvbHZlRGF0YWJyaWNrc1Jvb3R9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplRGF0YWJyaWNrc1Jvb3QoXG4gIHJvb3Q6IHN0cmluZyxcbiAgb3B0aW9uczogTm9ybWFsaXplRGF0YWJyaWNrc1Jvb3RPcHRpb25zID0ge30sXG4pOiBzdHJpbmcge1xuICBjb25zdCB0cmltbWVkID0gcm9vdC50cmltKCk7XG4gIGlmICghdHJpbW1lZCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJEYXRhYnJpY2tzIGZpbGVzeXN0ZW0gcm9vdCBjYW5ub3QgYmUgZW1wdHlcIik7XG4gIH1cblxuICBpZiAoaXNIb21lUmVsYXRpdmVQYXRoKHRyaW1tZWQpKSB7XG4gICAgaWYgKCFvcHRpb25zLnVzZXJOYW1lPy50cmltKCkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgIGBEYXRhYnJpY2tzIGhvbWUgcGF0aCBcIiR7cm9vdH1cIiByZXF1aXJlcyB1c2VyTmFtZTsgdXNlIHJlc29sdmVEYXRhYnJpY2tzUm9vdCgpIG9yIHBhc3MgdXNlck5hbWVgLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHBvc2l4UGF0aC5ub3JtYWxpemVSb290KGV4cGFuZEhvbWVQYXRoKHRyaW1tZWQsIG9wdGlvbnMudXNlck5hbWUpKTtcbiAgfVxuXG4gIGNvbnN0IHRocmVlUGFydCA9IFZPTFVNRV9USFJFRV9QQVJULmV4ZWModHJpbW1lZCk7XG4gIGlmICh0aHJlZVBhcnQpIHtcbiAgICByZXR1cm4gcG9zaXhQYXRoLm5vcm1hbGl6ZVJvb3QoYC9Wb2x1bWVzLyR7dGhyZWVQYXJ0WzFdfS8ke3RocmVlUGFydFsyXX0vJHt0aHJlZVBhcnRbM119YCk7XG4gIH1cblxuICBsZXQgcG9zaXggPSBwb3NpeFBhdGgudG9Qb3NpeCh0cmltbWVkKTtcbiAgaWYgKHBvc2l4ID09PSBcIi9Wb2x1bWVcIiB8fCBwb3NpeC5zdGFydHNXaXRoKFwiL1ZvbHVtZS9cIikpIHtcbiAgICBwb3NpeCA9IGAvVm9sdW1lcyR7cG9zaXguc2xpY2UoXCIvVm9sdW1lXCIubGVuZ3RoKX1gO1xuICB9XG5cbiAgaWYgKCFwb3NpeFBhdGguaXNBYnNvbHV0ZShwb3NpeCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgYERhdGFicmlja3MgZmlsZXN5c3RlbSByb290IG11c3QgYmUgYWJzb2x1dGUsIGNhdGFsb2cuc2NoZW1hLnZvbHVtZSwgb3IgfiwgZ290OiAke3Jvb3R9YCxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHBvc2l4UGF0aC5ub3JtYWxpemVSb290KHBvc2l4KTtcbn1cblxuLyoqXG4gKiBMaWtlIHtAbGluayBub3JtYWxpemVEYXRhYnJpY2tzUm9vdH0sIGJ1dCByZXNvbHZlcyBgfmAgdmlhXG4gKiB7QGxpbmsgZ2V0Q3VycmVudFVzZXJOYW1lfSAoQXBwS2l0IGNvbnRleHQgdXNlciwgZWxzZSBgY3VycmVudFVzZXIubWUoKWApLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZURhdGFicmlja3NSb290KFxuICByb290OiBzdHJpbmcsXG4gIG9wdGlvbnM6IFJlc29sdmVEYXRhYnJpY2tzUm9vdE9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmICghaXNIb21lUmVsYXRpdmVQYXRoKHJvb3QpKSB7XG4gICAgcmV0dXJuIG5vcm1hbGl6ZURhdGFicmlja3NSb290KHJvb3QpO1xuICB9XG4gIGNvbnN0IHVzZXJOYW1lID0gYXdhaXQgZ2V0Q3VycmVudFVzZXJOYW1lKG9wdGlvbnMuY2xpZW50KTtcbiAgcmV0dXJuIG5vcm1hbGl6ZURhdGFicmlja3NSb290KHJvb3QsIHsgdXNlck5hbWUgfSk7XG59XG5cbi8qKiBUcnVlIHdoZW4ge0BsaW5rIGFic29sdXRlUGF0aH0gaXMgc2VydmVkIGJ5IHRoZSB3b3Jrc3BhY2Ugb2JqZWN0cyBBUEkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNXb3Jrc3BhY2VGaWxlc1BhdGgoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgcCA9IHBvc2l4UGF0aC50b1Bvc2l4KGFic29sdXRlUGF0aCk7XG4gIHJldHVybiAoXG4gICAgcCA9PT0gXCIvV29ya3NwYWNlXCIgfHxcbiAgICBwLnN0YXJ0c1dpdGgoXCIvV29ya3NwYWNlL1wiKSB8fFxuICAgIHAuc3RhcnRzV2l0aChcIi9Vc2Vycy9cIikgfHxcbiAgICBwLnN0YXJ0c1dpdGgoXCIvUmVwb3MvXCIpIHx8XG4gICAgcC5zdGFydHNXaXRoKFwiL1NoYXJlZC9cIilcbiAgKTtcbn1cblxuLyoqIFRydWUgd2hlbiB7QGxpbmsgYWJzb2x1dGVQYXRofSBpcyBhIFVuaXR5IENhdGFsb2cgdm9sdW1lIHBhdGguICovXG5leHBvcnQgZnVuY3Rpb24gaXNWb2x1bWVzUGF0aChhYnNvbHV0ZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBwID0gcG9zaXhQYXRoLnRvUG9zaXgoYWJzb2x1dGVQYXRoKTtcbiAgcmV0dXJuIHAgPT09IFwiL1ZvbHVtZXNcIiB8fCBwLnN0YXJ0c1dpdGgoXCIvVm9sdW1lcy9cIik7XG59XG5cbi8qKiBUcnVlIHdoZW4ge0BsaW5rIGFic29sdXRlUGF0aH0gaXMgYSBEQkZTIHBhdGguICovXG5leHBvcnQgZnVuY3Rpb24gaXNEYmZzUGF0aChhYnNvbHV0ZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBwID0gcG9zaXhQYXRoLnRvUG9zaXgoYWJzb2x1dGVQYXRoKTtcbiAgcmV0dXJuIHAgPT09IFwiL2RiZnNcIiB8fCBwLnN0YXJ0c1dpdGgoXCIvZGJmcy9cIik7XG59XG5cbi8qKlxuICogUGljayB0aGUgRGF0YWJyaWNrcyBBUEkgYmFja2VuZCBmb3IgYW4gYWJzb2x1dGUgcGF0aC5cbiAqXG4gKiBWb2x1bWUgdGhyZWUtcGFydCByb290cyBhcmUgbm9ybWFsaXplZCBiZWZvcmUgdGhpcyBydW5zLCBzbyBjYWxsZXJzIHNob3VsZFxuICogcGFzcyBwYXRocyBmcm9tIHtAbGluayBub3JtYWxpemVEYXRhYnJpY2tzUm9vdH0gLyB7QGxpbmsgQmFzZUZpbGVTeXN0ZW0ucmVzb2x2ZVBhdGh9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZURhdGFicmlja3NGaWxlc0JhY2tlbmQoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBEYXRhYnJpY2tzRmlsZXNCYWNrZW5kIHtcbiAgaWYgKGlzRGJmc1BhdGgoYWJzb2x1dGVQYXRoKSkgcmV0dXJuIFwiZGJmc1wiO1xuICBpZiAoaXNXb3Jrc3BhY2VGaWxlc1BhdGgoYWJzb2x1dGVQYXRoKSkgcmV0dXJuIFwid29ya3NwYWNlXCI7XG4gIGlmIChpc1ZvbHVtZXNQYXRoKGFic29sdXRlUGF0aCkpIHJldHVybiBcInZvbHVtZXNcIjtcbiAgLy8gRGVmYXVsdDogVUMgRmlsZXMgQVBJIChjb3ZlcnMgdW51c3VhbCBhYnNvbHV0ZSByb290cyB1bmRlciB0aGUgd29ya3NwYWNlIGhvc3QpLlxuICByZXR1cm4gXCJ2b2x1bWVzXCI7XG59XG4iXX0=
|
package/lib/src/net.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side networking helpers that need Node builtins, layered over the
|
|
3
|
+
* browser-safe URL / IP toolkit in `@dbx-tools/shared-core`'s `net` module: DNS
|
|
4
|
+
* resolution ({@link resolveHostIps}, `node:dns`) and public-IP discovery
|
|
5
|
+
* ({@link getPublicIp}).
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { net } from "@dbx-tools/shared-core";
|
|
10
|
+
/**
|
|
11
|
+
* This process's outbound public IP, cached for 5 minutes. Asks Cloudflare's
|
|
12
|
+
* `cdn-cgi/trace` first and falls back to ipify. Useful for allowlisting or for
|
|
13
|
+
* reasoning about egress from a Databricks App.
|
|
14
|
+
*/
|
|
15
|
+
export declare const getPublicIp: () => Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the host of `input` to its IP address(es) via the OS resolver
|
|
18
|
+
* (`dns.lookup` with `all: true`, so both A and AAAA records are returned when
|
|
19
|
+
* the host is dual-stacked). Accepts any `net.UrlLike` - a bare hostname, a full
|
|
20
|
+
* URL, or a `{ url }` wrapper - and returns the deduplicated list of literal
|
|
21
|
+
* addresses. Never throws: an unparseable input, an IP-literal host (returned
|
|
22
|
+
* as-is without a DNS round-trip), or a resolution failure all yield the
|
|
23
|
+
* appropriate list or `[]`.
|
|
24
|
+
*
|
|
25
|
+
* `dns.lookup` (not `resolve4` / `resolve6`) is used so `/etc/hosts` and the
|
|
26
|
+
* platform resolver order are honored, matching what an outbound connection to
|
|
27
|
+
* the host would actually use.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveHostIps(input: net.UrlLike): Promise<string[]>;
|