@fabric-harness/databricks 0.18.0 → 1.0.0
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/dist/app.d.ts +81 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +87 -0
- package/dist/app.js.map +1 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -0
- package/dist/client.js.map +1 -1
- package/dist/governance.d.ts +4 -0
- package/dist/governance.d.ts.map +1 -1
- package/dist/governance.js +14 -2
- package/dist/governance.js.map +1 -1
- package/dist/identity.d.ts +34 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +63 -0
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/mlflow-tracing.d.ts +111 -0
- package/dist/mlflow-tracing.d.ts.map +1 -0
- package/dist/mlflow-tracing.js +167 -0
- package/dist/mlflow-tracing.js.map +1 -0
- package/dist/persistence.d.ts +73 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/persistence.js +82 -0
- package/dist/persistence.js.map +1 -0
- package/dist/serving-usage.d.ts +48 -0
- package/dist/serving-usage.d.ts.map +1 -0
- package/dist/serving-usage.js +100 -0
- package/dist/serving-usage.js.map +1 -0
- package/dist/telemetry-sink.d.ts +29 -0
- package/dist/telemetry-sink.d.ts.map +1 -0
- package/dist/telemetry-sink.js +129 -0
- package/dist/telemetry-sink.js.map +1 -0
- package/dist/volumes-attachment-store.d.ts +64 -0
- package/dist/volumes-attachment-store.d.ts.map +1 -0
- package/dist/volumes-attachment-store.js +172 -0
- package/dist/volumes-attachment-store.js.map +1 -0
- package/package.json +9 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-sink.d.ts","sourceRoot":"","sources":["../src/telemetry-sink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA4B,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,cAAc,CAAC;IACvB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,IAAI,EAAE,uBAAuB,CAAC;IAC9B,6EAA6E;IAC7E,SAAS,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACrD,iEAAiE;IACjE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,2DAA2D;AAC3D,wBAAsB,+BAA+B,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA4C3F;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,mBAAmB,CA6F5F"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/** Create the telemetry tables when absent. Idempotent. */
|
|
2
|
+
export async function ensureDatabricksTelemetryTables(client) {
|
|
3
|
+
await client.query(`CREATE TABLE IF NOT EXISTS fh_submission_telemetry (
|
|
4
|
+
id BIGSERIAL PRIMARY KEY,
|
|
5
|
+
submission_id TEXT NOT NULL,
|
|
6
|
+
event_type TEXT NOT NULL,
|
|
7
|
+
kind TEXT NOT NULL,
|
|
8
|
+
agent TEXT NOT NULL,
|
|
9
|
+
instance_id TEXT NOT NULL,
|
|
10
|
+
session TEXT NOT NULL,
|
|
11
|
+
attempt_id TEXT,
|
|
12
|
+
attempt_count INTEGER,
|
|
13
|
+
outcome TEXT,
|
|
14
|
+
error TEXT,
|
|
15
|
+
duration_ms BIGINT,
|
|
16
|
+
model TEXT,
|
|
17
|
+
input_tokens BIGINT,
|
|
18
|
+
output_tokens BIGINT,
|
|
19
|
+
cost_usd DOUBLE PRECISION,
|
|
20
|
+
tenant_id TEXT,
|
|
21
|
+
principal_kind TEXT,
|
|
22
|
+
principal_id TEXT,
|
|
23
|
+
at BIGINT NOT NULL
|
|
24
|
+
)`);
|
|
25
|
+
await client.query('CREATE INDEX IF NOT EXISTS fh_submission_telemetry_submission_idx ON fh_submission_telemetry (submission_id)');
|
|
26
|
+
await client.query(`CREATE TABLE IF NOT EXISTS fh_lineage (
|
|
27
|
+
id BIGSERIAL PRIMARY KEY,
|
|
28
|
+
submission_id TEXT,
|
|
29
|
+
attempt_id TEXT,
|
|
30
|
+
tool TEXT NOT NULL,
|
|
31
|
+
service TEXT,
|
|
32
|
+
provider TEXT,
|
|
33
|
+
principal TEXT,
|
|
34
|
+
catalog TEXT,
|
|
35
|
+
schema_name TEXT,
|
|
36
|
+
ok BOOLEAN NOT NULL,
|
|
37
|
+
error TEXT,
|
|
38
|
+
tenant_id TEXT,
|
|
39
|
+
input JSONB,
|
|
40
|
+
started_at TEXT NOT NULL,
|
|
41
|
+
finished_at TEXT NOT NULL
|
|
42
|
+
)`);
|
|
43
|
+
await client.query('CREATE INDEX IF NOT EXISTS fh_lineage_submission_idx ON fh_lineage (submission_id)');
|
|
44
|
+
}
|
|
45
|
+
export function databricksTelemetry(options) {
|
|
46
|
+
const { client } = options;
|
|
47
|
+
const onError = options.onError ??
|
|
48
|
+
((context, error) => {
|
|
49
|
+
console.error(`[fabric-harness:databricks-telemetry] ${context}:`, error);
|
|
50
|
+
});
|
|
51
|
+
let initialized;
|
|
52
|
+
const ensure = () => {
|
|
53
|
+
if (options.initialize === false)
|
|
54
|
+
return Promise.resolve();
|
|
55
|
+
initialized ??= ensureDatabricksTelemetryTables(client).catch((error) => {
|
|
56
|
+
initialized = undefined;
|
|
57
|
+
throw error;
|
|
58
|
+
});
|
|
59
|
+
return initialized;
|
|
60
|
+
};
|
|
61
|
+
async function writeEvent(event) {
|
|
62
|
+
await ensure();
|
|
63
|
+
const attemptId = 'attemptId' in event ? (event.attemptId ?? null) : null;
|
|
64
|
+
const attemptCount = 'attemptCount' in event ? (event.attemptCount ?? null) : null;
|
|
65
|
+
const outcome = event.type === 'submission_settled' ? event.outcome : null;
|
|
66
|
+
const error = event.type === 'submission_settled' ? (event.error ?? null) : null;
|
|
67
|
+
const durationMs = event.type === 'submission_settled' ? (event.durationMs ?? null) : null;
|
|
68
|
+
const model = event.type === 'submission_usage' ? (event.model ?? null) : null;
|
|
69
|
+
const inputTokens = event.type === 'submission_usage' ? (event.inputTokens ?? null) : null;
|
|
70
|
+
const outputTokens = event.type === 'submission_usage' ? (event.outputTokens ?? null) : null;
|
|
71
|
+
const costUsd = event.type === 'submission_usage' ? (event.costUsd ?? null) : null;
|
|
72
|
+
await client.query(`INSERT INTO fh_submission_telemetry
|
|
73
|
+
(submission_id, event_type, kind, agent, instance_id, session, attempt_id, attempt_count, outcome, error, duration_ms, model, input_tokens, output_tokens, cost_usd, tenant_id, principal_kind, principal_id, at)
|
|
74
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)`, [
|
|
75
|
+
event.submissionId,
|
|
76
|
+
event.type,
|
|
77
|
+
event.kind,
|
|
78
|
+
event.agent,
|
|
79
|
+
event.instanceId,
|
|
80
|
+
event.session,
|
|
81
|
+
attemptId,
|
|
82
|
+
attemptCount,
|
|
83
|
+
outcome,
|
|
84
|
+
error,
|
|
85
|
+
durationMs,
|
|
86
|
+
model,
|
|
87
|
+
inputTokens,
|
|
88
|
+
outputTokens,
|
|
89
|
+
costUsd,
|
|
90
|
+
event.tenantId ?? null,
|
|
91
|
+
event.actor?.principal?.kind ?? null,
|
|
92
|
+
event.actor?.principal?.id ?? null,
|
|
93
|
+
event.at,
|
|
94
|
+
]);
|
|
95
|
+
}
|
|
96
|
+
async function writeLineage(record) {
|
|
97
|
+
await ensure();
|
|
98
|
+
await client.query(`INSERT INTO fh_lineage
|
|
99
|
+
(submission_id, attempt_id, tool, service, provider, principal, catalog, schema_name, ok, error, tenant_id, input, started_at, finished_at)
|
|
100
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12::jsonb, $13, $14)`, [
|
|
101
|
+
record.submissionId ?? null,
|
|
102
|
+
record.attemptId ?? null,
|
|
103
|
+
record.tool,
|
|
104
|
+
record.service ?? null,
|
|
105
|
+
record.provider ?? null,
|
|
106
|
+
record.principal ?? null,
|
|
107
|
+
record.catalog ?? null,
|
|
108
|
+
record.schema ?? null,
|
|
109
|
+
record.ok,
|
|
110
|
+
record.error ?? null,
|
|
111
|
+
record.tenantId ?? null,
|
|
112
|
+
JSON.stringify(record.input ?? {}),
|
|
113
|
+
record.startedAt,
|
|
114
|
+
record.finishedAt,
|
|
115
|
+
]);
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
sink: {
|
|
119
|
+
record(event) {
|
|
120
|
+
return writeEvent(event);
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
onLineage(record) {
|
|
124
|
+
void writeLineage(record).catch((error) => onError(`lineage write failed for ${record.tool}`, error));
|
|
125
|
+
},
|
|
126
|
+
migrate: ensure,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=telemetry-sink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-sink.js","sourceRoot":"","sources":["../src/telemetry-sink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { AttachmentPutInput, AttachmentRef, AttachmentStore, StoredAttachment } from '@fabric-harness/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Unity Catalog Volumes attachment backend (v2 migration, workstream C2).
|
|
4
|
+
*
|
|
5
|
+
* Implements the SDK {@link AttachmentStore} contract on a UC Volume via the
|
|
6
|
+
* Databricks Files API, so attachment bytes are governed by Unity Catalog
|
|
7
|
+
* grants like every other Databricks asset. Layout under the volume:
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* /Volumes/<catalog>/<schema>/<volume>/<rootPrefix>/<encodeURIComponent(scope)>/<digest[0:2]>/<digest>
|
|
11
|
+
* /Volumes/<catalog>/<schema>/<volume>/<rootPrefix>/<encodeURIComponent(scope)>/<digest[0:2]>/<digest>.json
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* The bare `<digest>` file holds the raw bytes; the `<digest>.json` sidecar
|
|
15
|
+
* holds the {@link AttachmentRef} metadata and doubles as the record's
|
|
16
|
+
* existence marker: `put` is first-write-wins per `(scope, digest)` — when the
|
|
17
|
+
* sidecar already exists the put is a no-op, so the first stored ref metadata
|
|
18
|
+
* is retained (contract semantics).
|
|
19
|
+
*
|
|
20
|
+
* The JSON-only `DatabricksRestClient` cannot carry raw request/response
|
|
21
|
+
* bodies, so this store uses its own minimal fetch path with per-request
|
|
22
|
+
* bearer-token resolution (mirroring the client's rotating-token handling).
|
|
23
|
+
* Requests are single-shot (no transport retries) — the harness treats
|
|
24
|
+
* attachment materialization failures as submission admission failures and
|
|
25
|
+
* retries at that level.
|
|
26
|
+
*/
|
|
27
|
+
export interface UcVolumesAttachmentStoreOptions {
|
|
28
|
+
/** Workspace host, e.g. `https://adb-1234567890.0.cloud.databricks.com`. */
|
|
29
|
+
host: string;
|
|
30
|
+
/** Static PAT or rotating token resolver (resolved per request). */
|
|
31
|
+
token: string | (() => string | Promise<string>);
|
|
32
|
+
catalog: string;
|
|
33
|
+
schema: string;
|
|
34
|
+
volume: string;
|
|
35
|
+
/** Directory under the volume root holding all attachments. Default `fh-attachments`. */
|
|
36
|
+
rootPrefix?: string;
|
|
37
|
+
fetchImpl?: typeof fetch;
|
|
38
|
+
}
|
|
39
|
+
export declare class UcVolumesAttachmentStore implements AttachmentStore {
|
|
40
|
+
private readonly host;
|
|
41
|
+
private readonly token;
|
|
42
|
+
private readonly fetchImpl;
|
|
43
|
+
private readonly volumeRoot;
|
|
44
|
+
private readonly rootPrefix;
|
|
45
|
+
constructor(options: UcVolumesAttachmentStoreOptions);
|
|
46
|
+
put(input: AttachmentPutInput): Promise<void>;
|
|
47
|
+
get(scope: string, digest: string): Promise<StoredAttachment | null>;
|
|
48
|
+
getByAttachmentId(scope: string, attachmentId: string): Promise<StoredAttachment | null>;
|
|
49
|
+
list(scope: string): Promise<AttachmentRef[]>;
|
|
50
|
+
delete(scope: string, digest: string): Promise<void>;
|
|
51
|
+
private scopeDir;
|
|
52
|
+
private bytesPath;
|
|
53
|
+
private refPath;
|
|
54
|
+
private writeFile;
|
|
55
|
+
/** Raw file bytes, or `null` when the file does not exist (404). */
|
|
56
|
+
private readFile;
|
|
57
|
+
/** True when the file existed and was deleted; false on 404. */
|
|
58
|
+
private deleteFile;
|
|
59
|
+
/** Immediate children of a directory; empty for a missing directory (404). */
|
|
60
|
+
private listDirectory;
|
|
61
|
+
private request;
|
|
62
|
+
private fail;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=volumes-attachment-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"volumes-attachment-store.d.ts","sourceRoot":"","sources":["../src/volumes-attachment-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,+BAA+B;IAC9C,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAaD,qBAAa,wBAAyB,YAAW,eAAe;IAC9D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2C;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,OAAO,EAAE,+BAA+B;IAQ9C,GAAG,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAUpE,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAOxF,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAa7C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1D,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;YAMD,SAAS;IAQvB,oEAAoE;YACtD,QAAQ;IAOtB,gEAAgE;YAClD,UAAU;IAOxB,8EAA8E;YAChE,aAAa;YAgBb,OAAO;YAqBP,IAAI;CAOnB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { AttachmentStoreError, redactText, verifyAttachmentBytes, } from '@fabric-harness/sdk';
|
|
2
|
+
export class UcVolumesAttachmentStore {
|
|
3
|
+
host;
|
|
4
|
+
token;
|
|
5
|
+
fetchImpl;
|
|
6
|
+
volumeRoot;
|
|
7
|
+
rootPrefix;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.host = options.host.replace(/\/$/, '');
|
|
10
|
+
this.token = options.token;
|
|
11
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
12
|
+
this.rootPrefix = options.rootPrefix ?? 'fh-attachments';
|
|
13
|
+
this.volumeRoot = `/Volumes/${options.catalog}/${options.schema}/${options.volume}/${this.rootPrefix}`;
|
|
14
|
+
}
|
|
15
|
+
async put(input) {
|
|
16
|
+
await verifyAttachmentBytes(input.ref, input.bytes);
|
|
17
|
+
const refPath = this.refPath(input.scope, input.ref.digest);
|
|
18
|
+
// First-write-wins per (scope, digest): the sidecar marks a complete record.
|
|
19
|
+
if (await this.readFile(refPath))
|
|
20
|
+
return;
|
|
21
|
+
await this.writeFile(this.bytesPath(input.scope, input.ref.digest), input.bytes);
|
|
22
|
+
await this.writeFile(refPath, new TextEncoder().encode(JSON.stringify(input.ref)));
|
|
23
|
+
}
|
|
24
|
+
async get(scope, digest) {
|
|
25
|
+
const refBytes = await this.readFile(this.refPath(scope, digest));
|
|
26
|
+
if (!refBytes)
|
|
27
|
+
return null;
|
|
28
|
+
const ref = parseAttachmentRef(refBytes);
|
|
29
|
+
const bytes = await this.readFile(this.bytesPath(scope, digest));
|
|
30
|
+
// Sidecar without bytes is an incomplete (interrupted) record — a miss.
|
|
31
|
+
if (!bytes)
|
|
32
|
+
return null;
|
|
33
|
+
return { ref, bytes };
|
|
34
|
+
}
|
|
35
|
+
async getByAttachmentId(scope, attachmentId) {
|
|
36
|
+
for (const ref of await this.list(scope)) {
|
|
37
|
+
if (ref.id === attachmentId)
|
|
38
|
+
return this.get(scope, ref.digest);
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
async list(scope) {
|
|
43
|
+
const refs = [];
|
|
44
|
+
for (const prefixDir of await this.listDirectory(this.scopeDir(scope))) {
|
|
45
|
+
if (!prefixDir.is_directory || !prefixDir.path)
|
|
46
|
+
continue;
|
|
47
|
+
for (const entry of await this.listDirectory(prefixDir.path)) {
|
|
48
|
+
if (entry.is_directory || !entry.path || !entry.path.endsWith('.json'))
|
|
49
|
+
continue;
|
|
50
|
+
const refBytes = await this.readFile(entry.path);
|
|
51
|
+
if (refBytes)
|
|
52
|
+
refs.push(parseAttachmentRef(refBytes));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return refs;
|
|
56
|
+
}
|
|
57
|
+
async delete(scope, digest) {
|
|
58
|
+
// The sidecar is the record marker — delete it first so the record
|
|
59
|
+
// disappears even if the bytes delete below fails.
|
|
60
|
+
if (!(await this.deleteFile(this.refPath(scope, digest)))) {
|
|
61
|
+
throw new AttachmentStoreError('NOT_FOUND', `Attachment not found: ${scope}/${digest}`);
|
|
62
|
+
}
|
|
63
|
+
await this.deleteFile(this.bytesPath(scope, digest));
|
|
64
|
+
}
|
|
65
|
+
// ─── Volume paths ─────────────────────────────────────────────────────────
|
|
66
|
+
scopeDir(scope) {
|
|
67
|
+
return `${this.volumeRoot}/${encodeURIComponent(scope)}`;
|
|
68
|
+
}
|
|
69
|
+
bytesPath(scope, digest) {
|
|
70
|
+
return `${this.scopeDir(scope)}/${digest.slice(0, 2)}/${digest}`;
|
|
71
|
+
}
|
|
72
|
+
refPath(scope, digest) {
|
|
73
|
+
return `${this.bytesPath(scope, digest)}.json`;
|
|
74
|
+
}
|
|
75
|
+
// ─── Files API ────────────────────────────────────────────────────────────
|
|
76
|
+
async writeFile(path, bytes) {
|
|
77
|
+
const response = await this.request('PUT', 'files', path, {
|
|
78
|
+
query: { overwrite: 'true' },
|
|
79
|
+
body: bytes,
|
|
80
|
+
});
|
|
81
|
+
if (!response.ok)
|
|
82
|
+
await this.fail(`PUT ${path}`, response);
|
|
83
|
+
}
|
|
84
|
+
/** Raw file bytes, or `null` when the file does not exist (404). */
|
|
85
|
+
async readFile(path) {
|
|
86
|
+
const response = await this.request('GET', 'files', path);
|
|
87
|
+
if (response.status === 404)
|
|
88
|
+
return null;
|
|
89
|
+
if (!response.ok)
|
|
90
|
+
await this.fail(`GET ${path}`, response);
|
|
91
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
92
|
+
}
|
|
93
|
+
/** True when the file existed and was deleted; false on 404. */
|
|
94
|
+
async deleteFile(path) {
|
|
95
|
+
const response = await this.request('DELETE', 'files', path);
|
|
96
|
+
if (response.status === 404)
|
|
97
|
+
return false;
|
|
98
|
+
if (!response.ok)
|
|
99
|
+
await this.fail(`DELETE ${path}`, response);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
/** Immediate children of a directory; empty for a missing directory (404). */
|
|
103
|
+
async listDirectory(path) {
|
|
104
|
+
const entries = [];
|
|
105
|
+
let pageToken;
|
|
106
|
+
do {
|
|
107
|
+
const response = await this.request('GET', 'directories', path, {
|
|
108
|
+
query: pageToken ? { page_token: pageToken } : {},
|
|
109
|
+
});
|
|
110
|
+
if (response.status === 404)
|
|
111
|
+
return entries;
|
|
112
|
+
if (!response.ok)
|
|
113
|
+
await this.fail(`LIST ${path}`, response);
|
|
114
|
+
const listing = (await response.json());
|
|
115
|
+
entries.push(...(listing.contents ?? []));
|
|
116
|
+
pageToken = listing.next_page_token;
|
|
117
|
+
} while (pageToken);
|
|
118
|
+
return entries;
|
|
119
|
+
}
|
|
120
|
+
async request(method, api, path, options = {}) {
|
|
121
|
+
const url = new URL(`${this.host}/api/2.0/fs/${api}${encodeVolumePath(path)}`);
|
|
122
|
+
for (const [key, value] of Object.entries(options.query ?? {})) {
|
|
123
|
+
url.searchParams.set(key, value);
|
|
124
|
+
}
|
|
125
|
+
const token = typeof this.token === 'function' ? await this.token() : this.token;
|
|
126
|
+
return this.fetchImpl(url, {
|
|
127
|
+
method,
|
|
128
|
+
headers: {
|
|
129
|
+
authorization: `Bearer ${token}`,
|
|
130
|
+
...(options.body !== undefined ? { 'content-type': 'application/octet-stream' } : {}),
|
|
131
|
+
},
|
|
132
|
+
...(options.body !== undefined ? { body: viewToBuffer(options.body) } : {}),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
async fail(operation, response) {
|
|
136
|
+
const token = typeof this.token === 'function' ? await this.token() : this.token;
|
|
137
|
+
const text = redactText(await response.text().catch(() => ''), { additionalSecrets: [token] });
|
|
138
|
+
throw new Error(`databricks volumes: ${operation}: ${response.status} ${response.statusText}: ${text.slice(0, 1000)}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Percent-encode each segment of a volume path for use in a Files API URL.
|
|
143
|
+
* The scope directory name is itself `encodeURIComponent(scope)` (a literal
|
|
144
|
+
* name containing `%xx` sequences), so its `%` signs are re-encoded here and
|
|
145
|
+
* the server-decoded path matches the literal layout exactly.
|
|
146
|
+
*/
|
|
147
|
+
function encodeVolumePath(path) {
|
|
148
|
+
return path
|
|
149
|
+
.split('/')
|
|
150
|
+
.map((segment) => encodeURIComponent(segment))
|
|
151
|
+
.join('/');
|
|
152
|
+
}
|
|
153
|
+
function parseAttachmentRef(bytes) {
|
|
154
|
+
const parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
155
|
+
if (typeof parsed.id !== 'string' ||
|
|
156
|
+
typeof parsed.mimeType !== 'string' ||
|
|
157
|
+
typeof parsed.sizeBytes !== 'number' ||
|
|
158
|
+
typeof parsed.digest !== 'string') {
|
|
159
|
+
throw new Error('databricks volumes: malformed attachment ref sidecar');
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
id: parsed.id,
|
|
163
|
+
mimeType: parsed.mimeType,
|
|
164
|
+
sizeBytes: parsed.sizeBytes,
|
|
165
|
+
digest: parsed.digest,
|
|
166
|
+
...(typeof parsed.filename === 'string' ? { filename: parsed.filename } : {}),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function viewToBuffer(bytes) {
|
|
170
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=volumes-attachment-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"volumes-attachment-store.js","sourceRoot":"","sources":["../src/volumes-attachment-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fabric-harness/databricks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Databricks tools and filesystem sources for Fabric Harness agents.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Fabric",
|
|
@@ -52,19 +52,24 @@
|
|
|
52
52
|
"LICENSE"
|
|
53
53
|
],
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@fabric-harness/sdk": "^
|
|
55
|
+
"@fabric-harness/sdk": "^2.0.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"pg": "^8.11.0"
|
|
58
|
+
"pg": "^8.11.0",
|
|
59
|
+
"@fabric-harness/node": ">=1.14.0 <3"
|
|
59
60
|
},
|
|
60
61
|
"peerDependenciesMeta": {
|
|
61
62
|
"pg": {
|
|
62
63
|
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"@fabric-harness/node": {
|
|
66
|
+
"optional": true
|
|
63
67
|
}
|
|
64
68
|
},
|
|
65
69
|
"devDependencies": {
|
|
66
70
|
"typescript": "^5.8.3",
|
|
67
|
-
"vitest": "^4.1.5"
|
|
71
|
+
"vitest": "^4.1.5",
|
|
72
|
+
"@fabric-harness/node": "^2.0.0"
|
|
68
73
|
},
|
|
69
74
|
"scripts": {
|
|
70
75
|
"build": "tsc -p tsconfig.json",
|