@skenora/resources 0.1.2
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 +60 -0
- package/dist/http.d.ts +2 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +2 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/memory.d.ts +2 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +2 -0
- package/dist/memory.js.map +1 -0
- package/dist/providers/http-provider.d.ts +22 -0
- package/dist/providers/http-provider.d.ts.map +1 -0
- package/dist/providers/http-provider.js +157 -0
- package/dist/providers/http-provider.js.map +1 -0
- package/dist/providers/memory-provider.d.ts +19 -0
- package/dist/providers/memory-provider.d.ts.map +1 -0
- package/dist/providers/memory-provider.js +131 -0
- package/dist/providers/memory-provider.js.map +1 -0
- package/dist/providers/workspace-provider.d.ts +14 -0
- package/dist/providers/workspace-provider.d.ts.map +1 -0
- package/dist/providers/workspace-provider.js +126 -0
- package/dist/providers/workspace-provider.js.map +1 -0
- package/dist/resource-bindings.d.ts +94 -0
- package/dist/resource-bindings.d.ts.map +1 -0
- package/dist/resource-bindings.js +546 -0
- package/dist/resource-bindings.js.map +1 -0
- package/dist/resource-manager.d.ts +29 -0
- package/dist/resource-manager.d.ts.map +1 -0
- package/dist/resource-manager.js +380 -0
- package/dist/resource-manager.js.map +1 -0
- package/dist/types.d.ts +144 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +30 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace-resource-context.d.ts +21 -0
- package/dist/workspace-resource-context.d.ts.map +1 -0
- package/dist/workspace-resource-context.js +22 -0
- package/dist/workspace-resource-context.js.map +1 -0
- package/dist/workspace.d.ts +3 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +3 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @skenora/resources
|
|
2
|
+
|
|
3
|
+
Provider-based resource discovery, policy, caching, integrity checks, and
|
|
4
|
+
lifetime management for Skenora.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pnpm add @skenora/resources
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Entry points:
|
|
11
|
+
|
|
12
|
+
| Import | Purpose |
|
|
13
|
+
| ------------------------------ | -------------------------------------------------------- |
|
|
14
|
+
| `@skenora/resources` | `ResourceManager`, provider contracts, discovery helpers |
|
|
15
|
+
| `@skenora/resources/workspace` | workspace provider and shared resource context |
|
|
16
|
+
| `@skenora/resources/http` | opt-in allowlisted HTTPS provider |
|
|
17
|
+
| `@skenora/resources/memory` | in-memory Blob resources |
|
|
18
|
+
|
|
19
|
+
Resource providers translate persistent locators into acquired bytes.
|
|
20
|
+
`ResourceScope` owns temporary Blob URLs and must be disposed. Network loading
|
|
21
|
+
is unavailable until the host explicitly installs and authorizes an HTTP or
|
|
22
|
+
custom provider.
|
|
23
|
+
|
|
24
|
+
See the [resource guide](https://github.com/zhangjiadi225/skenora/blob/main/docs/RESOURCES.md).
|
|
25
|
+
|
|
26
|
+
## Scene-plan bindings and leases
|
|
27
|
+
|
|
28
|
+
Scene-plan inputs use logical references. The host supplies an already
|
|
29
|
+
authorized `ResourceBinding` and may validate it against the plan's kind,
|
|
30
|
+
media type, and SHA-256 integrity requirement without performing I/O:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import {
|
|
34
|
+
createResourceBindingScope,
|
|
35
|
+
createResourceBindingTable,
|
|
36
|
+
} from "@skenora/resources";
|
|
37
|
+
|
|
38
|
+
const bindings = createResourceBindingTable(
|
|
39
|
+
[{ assetRef: "chair", asset: authorizedAsset }],
|
|
40
|
+
[{ assetRef: "chair", kind: "model" }],
|
|
41
|
+
);
|
|
42
|
+
const bindingScope = createResourceBindingScope(resources, bindings);
|
|
43
|
+
const chair = bindingScope.acquire("chair");
|
|
44
|
+
const resolved = await chair.resource;
|
|
45
|
+
|
|
46
|
+
// Keep the lease until Runtime projection has completed.
|
|
47
|
+
bindingScope.dispose();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`ModelVisibleResourceDescriptor` and
|
|
51
|
+
`toModelVisibleResourceDescriptor()` expose only an opaque logical reference
|
|
52
|
+
and safe metadata. They omit provider ids, sources, paths, URLs, thumbnails,
|
|
53
|
+
credentials, and Blob URLs. The existing `ResourceDescriptor` remains
|
|
54
|
+
available for trusted host/provider code for backward compatibility; callers
|
|
55
|
+
must project it before returning data to a model.
|
|
56
|
+
|
|
57
|
+
`ResourceBindingScope` creates one child `ResourceScope` per lease. Releasing
|
|
58
|
+
a lease or disposing the binding scope delegates to the existing
|
|
59
|
+
reference-counted cache and Blob URL cleanup. Authorization, downloads,
|
|
60
|
+
imports, and workspace writes remain outside this package.
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC"}
|
package/dist/http.js
ADDED
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC"}
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
package/dist/memory.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { HttpResourceLocator, ResourceLocator } from "@skenora/contracts";
|
|
2
|
+
import type { ResourceProvider, ResourceRequestContext, ResourceResponse } from "../types.js";
|
|
3
|
+
export interface HttpResourceProviderOptions {
|
|
4
|
+
allowedOrigins?: Iterable<string>;
|
|
5
|
+
allowSameOrigin?: boolean;
|
|
6
|
+
allowRedirects?: boolean;
|
|
7
|
+
allowPrivateHosts?: boolean;
|
|
8
|
+
maxBytes?: number;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
credentials?: RequestCredentials;
|
|
11
|
+
headers?: (locator: Readonly<HttpResourceLocator>) => HeadersInit | Promise<HeadersInit>;
|
|
12
|
+
fetch?: typeof fetch;
|
|
13
|
+
}
|
|
14
|
+
export declare class HttpResourceProvider implements ResourceProvider {
|
|
15
|
+
#private;
|
|
16
|
+
readonly type = "http";
|
|
17
|
+
constructor(options?: HttpResourceProviderOptions);
|
|
18
|
+
canonicalize(locator: ResourceLocator): string;
|
|
19
|
+
open(locator: ResourceLocator, context: ResourceRequestContext): Promise<ResourceResponse>;
|
|
20
|
+
resolveRelative(base: ResourceLocator, relativeUri: string): HttpResourceLocator;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=http-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-provider.d.ts","sourceRoot":"","sources":["../../src/providers/http-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,2BAA2B;IAC1C,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,QAAQ,CAAC,mBAAmB,CAAC,KACnC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,qBAAa,oBAAqB,YAAW,gBAAgB;;IAC3D,QAAQ,CAAC,IAAI,UAAU;gBAWX,OAAO,GAAE,2BAAgC;IAoBrD,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM;IAIxC,IAAI,CACR,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IAqD5B,eAAe,CACb,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM,GAClB,mBAAmB;CAgCvB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
export class HttpResourceProvider {
|
|
2
|
+
type = "http";
|
|
3
|
+
#allowedOrigins;
|
|
4
|
+
#allowSameOrigin;
|
|
5
|
+
#allowRedirects;
|
|
6
|
+
#allowPrivateHosts;
|
|
7
|
+
#maxBytes;
|
|
8
|
+
#timeoutMs;
|
|
9
|
+
#credentials;
|
|
10
|
+
#headers;
|
|
11
|
+
#fetch;
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
this.#allowedOrigins = new Set([...(options.allowedOrigins ?? [])].map(normalizeOrigin));
|
|
14
|
+
this.#allowSameOrigin = options.allowSameOrigin ?? true;
|
|
15
|
+
this.#allowRedirects = options.allowRedirects ?? false;
|
|
16
|
+
this.#allowPrivateHosts = options.allowPrivateHosts ?? false;
|
|
17
|
+
this.#maxBytes = options.maxBytes ?? 100 * 1024 * 1024;
|
|
18
|
+
this.#timeoutMs = options.timeoutMs ?? 30_000;
|
|
19
|
+
this.#credentials = options.credentials ?? "omit";
|
|
20
|
+
this.#headers = options.headers;
|
|
21
|
+
this.#fetch = options.fetch ?? fetch;
|
|
22
|
+
if (!Number.isFinite(this.#maxBytes) || this.#maxBytes <= 0) {
|
|
23
|
+
throw new Error("HTTP resource maxBytes must be positive");
|
|
24
|
+
}
|
|
25
|
+
if (!Number.isFinite(this.#timeoutMs) || this.#timeoutMs <= 0) {
|
|
26
|
+
throw new Error("HTTP resource timeoutMs must be positive");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
canonicalize(locator) {
|
|
30
|
+
return this.#assertAllowed(httpLocator(locator).url).href;
|
|
31
|
+
}
|
|
32
|
+
async open(locator, context) {
|
|
33
|
+
const input = httpLocator(locator);
|
|
34
|
+
const url = this.#assertAllowed(input.url);
|
|
35
|
+
const timeout = new AbortController();
|
|
36
|
+
const timeoutId = setTimeout(() => timeout.abort(), this.#timeoutMs);
|
|
37
|
+
const combined = combineSignals(context.signal, timeout.signal);
|
|
38
|
+
try {
|
|
39
|
+
const response = await this.#fetch(url, {
|
|
40
|
+
method: "GET",
|
|
41
|
+
mode: "cors",
|
|
42
|
+
credentials: this.#credentials,
|
|
43
|
+
redirect: this.#allowRedirects ? "follow" : "error",
|
|
44
|
+
signal: combined.signal,
|
|
45
|
+
...(this.#headers ? { headers: await this.#headers(input) } : {}),
|
|
46
|
+
});
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`HTTP resource request failed (${response.status}): ${url.href}`);
|
|
49
|
+
}
|
|
50
|
+
const finalUrl = this.#assertAllowed(response.url || url.href);
|
|
51
|
+
const declaredSize = Number(response.headers.get("content-length"));
|
|
52
|
+
if (Number.isFinite(declaredSize) && declaredSize > this.#maxBytes) {
|
|
53
|
+
throw new Error(`HTTP resource exceeds maxBytes: ${declaredSize}`);
|
|
54
|
+
}
|
|
55
|
+
const blob = await response.blob();
|
|
56
|
+
if (blob.size > this.#maxBytes) {
|
|
57
|
+
throw new Error(`HTTP resource exceeds maxBytes: ${blob.size}`);
|
|
58
|
+
}
|
|
59
|
+
const name = decodeURIComponent(finalUrl.pathname.split("/").at(-1) || "resource");
|
|
60
|
+
const mediaType = response.headers.get("content-type")?.split(";", 1)[0];
|
|
61
|
+
return {
|
|
62
|
+
blob,
|
|
63
|
+
name,
|
|
64
|
+
resolvedLocator: { type: "http", url: finalUrl.href },
|
|
65
|
+
...(mediaType ? { mediaType } : {}),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (timeout.signal.aborted && !context.signal.aborted) {
|
|
70
|
+
throw new DOMException("HTTP resource request timed out", "TimeoutError");
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
clearTimeout(timeoutId);
|
|
76
|
+
combined.dispose();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
resolveRelative(base, relativeUri) {
|
|
80
|
+
const resolved = new URL(relativeUri, this.#assertAllowed(httpLocator(base).url));
|
|
81
|
+
this.#assertAllowed(resolved.href);
|
|
82
|
+
return { type: "http", url: resolved.href };
|
|
83
|
+
}
|
|
84
|
+
#assertAllowed(input) {
|
|
85
|
+
let url;
|
|
86
|
+
try {
|
|
87
|
+
url = new URL(input);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
throw new Error(`HTTP resource URL is invalid: ${input}`);
|
|
91
|
+
}
|
|
92
|
+
if (url.protocol !== "https:") {
|
|
93
|
+
throw new Error(`HTTP resource URL must use HTTPS: ${url.href}`);
|
|
94
|
+
}
|
|
95
|
+
if (!this.#allowPrivateHosts && isPrivateHostname(url.hostname)) {
|
|
96
|
+
throw new Error(`HTTP resource host is private: ${url.hostname}`);
|
|
97
|
+
}
|
|
98
|
+
const sameOrigin = this.#allowSameOrigin &&
|
|
99
|
+
typeof location !== "undefined" &&
|
|
100
|
+
url.origin === location.origin;
|
|
101
|
+
if (!sameOrigin && !this.#allowedOrigins.has(url.origin)) {
|
|
102
|
+
throw new Error(`HTTP resource origin is not allowed: ${url.origin}`);
|
|
103
|
+
}
|
|
104
|
+
url.hash = "";
|
|
105
|
+
return url;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function combineSignals(first, second) {
|
|
109
|
+
const controller = new AbortController();
|
|
110
|
+
const abort = () => controller.abort();
|
|
111
|
+
if (first.aborted || second.aborted)
|
|
112
|
+
controller.abort();
|
|
113
|
+
else {
|
|
114
|
+
first.addEventListener("abort", abort, { once: true });
|
|
115
|
+
second.addEventListener("abort", abort, { once: true });
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
signal: controller.signal,
|
|
119
|
+
dispose() {
|
|
120
|
+
first.removeEventListener("abort", abort);
|
|
121
|
+
second.removeEventListener("abort", abort);
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function httpLocator(locator) {
|
|
126
|
+
if (locator.type !== "http") {
|
|
127
|
+
throw new Error(`HTTP provider cannot resolve: ${locator.type}`);
|
|
128
|
+
}
|
|
129
|
+
return locator;
|
|
130
|
+
}
|
|
131
|
+
function normalizeOrigin(value) {
|
|
132
|
+
const url = new URL(value);
|
|
133
|
+
if (url.protocol !== "https:") {
|
|
134
|
+
throw new Error(`Allowed resource origin must use HTTPS: ${value}`);
|
|
135
|
+
}
|
|
136
|
+
return url.origin;
|
|
137
|
+
}
|
|
138
|
+
function isPrivateHostname(hostname) {
|
|
139
|
+
const value = hostname.replace(/^\[|\]$/gu, "").toLowerCase();
|
|
140
|
+
if (value === "localhost" ||
|
|
141
|
+
value === "::1" ||
|
|
142
|
+
value.endsWith(".localhost") ||
|
|
143
|
+
value.endsWith(".local")) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const parts = value.split(".").map(Number);
|
|
147
|
+
if (parts.length !== 4 || parts.some((part) => !Number.isInteger(part))) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
const [a = -1, b = -1] = parts;
|
|
151
|
+
return (a === 10 ||
|
|
152
|
+
a === 127 ||
|
|
153
|
+
(a === 169 && b === 254) ||
|
|
154
|
+
(a === 172 && b >= 16 && b <= 31) ||
|
|
155
|
+
(a === 192 && b === 168));
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=http-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-provider.js","sourceRoot":"","sources":["../../src/providers/http-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MemoryResourceLocator, ResourceLocator } from "@skenora/contracts";
|
|
2
|
+
import type { ResourceDescriptor, ResourceProvider, ResourceRequestContext, ResourceResponse, ResourceSearchPage, ResourceSearchQuery } from "../types.js";
|
|
3
|
+
export interface MemoryResourceEntry {
|
|
4
|
+
blob: Blob;
|
|
5
|
+
descriptor: Omit<ResourceDescriptor, "source">;
|
|
6
|
+
}
|
|
7
|
+
export declare class MemoryResourceProvider implements ResourceProvider {
|
|
8
|
+
#private;
|
|
9
|
+
readonly type = "memory";
|
|
10
|
+
constructor(entries?: Readonly<Record<string, MemoryResourceEntry>>);
|
|
11
|
+
set(key: string, entry: MemoryResourceEntry): void;
|
|
12
|
+
delete(key: string): boolean;
|
|
13
|
+
canonicalize(locator: ResourceLocator): string;
|
|
14
|
+
open(locator: ResourceLocator, context: ResourceRequestContext): Promise<ResourceResponse>;
|
|
15
|
+
resolveRelative(base: ResourceLocator, relativeUri: string): MemoryResourceLocator;
|
|
16
|
+
search(query: ResourceSearchQuery, context: ResourceRequestContext): Promise<ResourceSearchPage>;
|
|
17
|
+
describe(locator: ResourceLocator, context: ResourceRequestContext): Promise<ResourceDescriptor>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=memory-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-provider.d.ts","sourceRoot":"","sources":["../../src/providers/memory-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;CAChD;AAED,qBAAa,sBAAuB,YAAW,gBAAgB;;IAC7D,QAAQ,CAAC,IAAI,YAAY;gBAGb,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAM;IAIvE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAQlD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM;IAIxC,IAAI,CACR,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IAc5B,eAAe,CACb,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM,GAClB,qBAAqB;IAyBlB,MAAM,CACV,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,kBAAkB,CAAC;IA4BxB,QAAQ,CACZ,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,kBAAkB,CAAC;CAO/B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
export class MemoryResourceProvider {
|
|
2
|
+
type = "memory";
|
|
3
|
+
#entries = new Map();
|
|
4
|
+
constructor(entries = {}) {
|
|
5
|
+
for (const [key, entry] of Object.entries(entries))
|
|
6
|
+
this.set(key, entry);
|
|
7
|
+
}
|
|
8
|
+
set(key, entry) {
|
|
9
|
+
const normalized = normalizeKey(key);
|
|
10
|
+
this.#entries.set(normalized, {
|
|
11
|
+
blob: entry.blob,
|
|
12
|
+
descriptor: structuredClone(entry.descriptor),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
delete(key) {
|
|
16
|
+
return this.#entries.delete(normalizeKey(key));
|
|
17
|
+
}
|
|
18
|
+
canonicalize(locator) {
|
|
19
|
+
return normalizeKey(memoryLocator(locator).key);
|
|
20
|
+
}
|
|
21
|
+
async open(locator, context) {
|
|
22
|
+
throwIfAborted(context.signal);
|
|
23
|
+
const key = normalizeKey(memoryLocator(locator).key);
|
|
24
|
+
const entry = this.#entries.get(key);
|
|
25
|
+
if (!entry)
|
|
26
|
+
throw new Error(`Memory resource not found: ${key}`);
|
|
27
|
+
return {
|
|
28
|
+
blob: entry.blob,
|
|
29
|
+
name: key.split("/").at(-1) ?? entry.descriptor.label,
|
|
30
|
+
...(entry.descriptor.mediaType
|
|
31
|
+
? { mediaType: entry.descriptor.mediaType }
|
|
32
|
+
: {}),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
resolveRelative(base, relativeUri) {
|
|
36
|
+
const baseKey = memoryLocator(base).key;
|
|
37
|
+
const relative = decodeRelativeUri(relativeUri);
|
|
38
|
+
if (/^[a-z][a-z\d+.-]*:/iu.test(relative) || relative.startsWith("/")) {
|
|
39
|
+
throw new Error(`Memory resource reference must be relative: ${relativeUri}`);
|
|
40
|
+
}
|
|
41
|
+
const segments = baseKey.split("/").slice(0, -1);
|
|
42
|
+
for (const segment of relative.split("/")) {
|
|
43
|
+
if (!segment || segment === ".")
|
|
44
|
+
continue;
|
|
45
|
+
if (segment === "..") {
|
|
46
|
+
if (segments.length === 0) {
|
|
47
|
+
throw new Error(`Memory resource reference escapes its root: ${relativeUri}`);
|
|
48
|
+
}
|
|
49
|
+
segments.pop();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
segments.push(segment);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return { type: "memory", key: normalizeKey(segments.join("/")) };
|
|
56
|
+
}
|
|
57
|
+
async search(query, context) {
|
|
58
|
+
throwIfAborted(context.signal);
|
|
59
|
+
const text = query.query?.trim().toLowerCase() ?? "";
|
|
60
|
+
const tags = query.tags?.map((tag) => tag.toLowerCase()) ?? [];
|
|
61
|
+
const items = [...this.#entries.entries()]
|
|
62
|
+
.flatMap(([key, entry]) => {
|
|
63
|
+
const descriptor = entry.descriptor;
|
|
64
|
+
if (query.kind && descriptor.kind !== query.kind)
|
|
65
|
+
return [];
|
|
66
|
+
const haystack = [
|
|
67
|
+
descriptor.label,
|
|
68
|
+
descriptor.description ?? "",
|
|
69
|
+
...(descriptor.tags ?? []),
|
|
70
|
+
]
|
|
71
|
+
.join(" ")
|
|
72
|
+
.toLowerCase();
|
|
73
|
+
if (text &&
|
|
74
|
+
!text.split(/\s+/u).every((term) => haystack.includes(term))) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
if (!tags.every((tag) => haystack.includes(tag)))
|
|
78
|
+
return [];
|
|
79
|
+
return [withSource(key, descriptor)];
|
|
80
|
+
})
|
|
81
|
+
.slice(0, query.limit ?? 20);
|
|
82
|
+
return { items };
|
|
83
|
+
}
|
|
84
|
+
async describe(locator, context) {
|
|
85
|
+
throwIfAborted(context.signal);
|
|
86
|
+
const key = normalizeKey(memoryLocator(locator).key);
|
|
87
|
+
const entry = this.#entries.get(key);
|
|
88
|
+
if (!entry)
|
|
89
|
+
throw new Error(`Memory resource not found: ${key}`);
|
|
90
|
+
return withSource(key, entry.descriptor);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function decodeRelativeUri(uri) {
|
|
94
|
+
const path = uri.split(/[?#]/u, 1)[0] ?? uri;
|
|
95
|
+
try {
|
|
96
|
+
return decodeURIComponent(path);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return path;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function withSource(key, descriptor) {
|
|
103
|
+
return {
|
|
104
|
+
...structuredClone(descriptor),
|
|
105
|
+
source: { type: "memory", key },
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function memoryLocator(locator) {
|
|
109
|
+
if (locator.type !== "memory") {
|
|
110
|
+
throw new Error(`Memory provider cannot resolve: ${locator.type}`);
|
|
111
|
+
}
|
|
112
|
+
return locator;
|
|
113
|
+
}
|
|
114
|
+
function normalizeKey(key) {
|
|
115
|
+
const normalized = key.replaceAll("\\", "/").replace(/^\.\//u, "");
|
|
116
|
+
if (!normalized ||
|
|
117
|
+
normalized.startsWith("/") ||
|
|
118
|
+
normalized.includes("\0") ||
|
|
119
|
+
normalized
|
|
120
|
+
.split("/")
|
|
121
|
+
.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
122
|
+
throw new Error(`Memory resource key is invalid: ${key}`);
|
|
123
|
+
}
|
|
124
|
+
return normalized;
|
|
125
|
+
}
|
|
126
|
+
function throwIfAborted(signal) {
|
|
127
|
+
if (signal.aborted) {
|
|
128
|
+
throw new DOMException("Memory resource request was aborted", "AbortError");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=memory-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-provider.js","sourceRoot":"","sources":["../../src/providers/memory-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ResourceLocator, WorkspaceResourceLocator } from "@skenora/contracts";
|
|
2
|
+
import { type WorkspaceSource } from "@skenora/workspace";
|
|
3
|
+
import type { ResourceDescriptor, ResourceProvider, ResourceRequestContext, ResourceResponse, ResourceSearchPage, ResourceSearchQuery } from "../types.js";
|
|
4
|
+
export declare class WorkspaceResourceProvider implements ResourceProvider {
|
|
5
|
+
readonly type = "workspace";
|
|
6
|
+
readonly source: WorkspaceSource;
|
|
7
|
+
constructor(source: WorkspaceSource);
|
|
8
|
+
canonicalize(locator: ResourceLocator): string;
|
|
9
|
+
open(locator: ResourceLocator, context: ResourceRequestContext): Promise<ResourceResponse>;
|
|
10
|
+
resolveRelative(base: ResourceLocator, relativeUri: string): WorkspaceResourceLocator;
|
|
11
|
+
search(query: ResourceSearchQuery, context: ResourceRequestContext): Promise<ResourceSearchPage>;
|
|
12
|
+
describe(locator: ResourceLocator, context: ResourceRequestContext): Promise<ResourceDescriptor>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=workspace-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-provider.d.ts","sourceRoot":"","sources":["../../src/providers/workspace-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,wBAAwB,EACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAElB,qBAAa,yBAA0B,YAAW,gBAAgB;IAChE,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBAErB,MAAM,EAAE,eAAe;IAInC,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM;IAIxC,IAAI,CACR,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IAY5B,eAAe,CACb,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM,GAClB,wBAAwB;IAUrB,MAAM,CACV,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,kBAAkB,CAAC;IA6CxB,QAAQ,CACZ,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,kBAAkB,CAAC;CAoB/B"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { inferAssetKind, normalizeWorkspacePath, resolveWorkspaceRelativePath, } from "@skenora/workspace";
|
|
2
|
+
export class WorkspaceResourceProvider {
|
|
3
|
+
type = "workspace";
|
|
4
|
+
source;
|
|
5
|
+
constructor(source) {
|
|
6
|
+
this.source = source;
|
|
7
|
+
}
|
|
8
|
+
canonicalize(locator) {
|
|
9
|
+
return normalizeWorkspacePath(workspaceLocator(locator).path);
|
|
10
|
+
}
|
|
11
|
+
async open(locator, context) {
|
|
12
|
+
throwIfAborted(context.signal);
|
|
13
|
+
const path = normalizeWorkspacePath(workspaceLocator(locator).path);
|
|
14
|
+
const file = await this.source.read(path);
|
|
15
|
+
throwIfAborted(context.signal);
|
|
16
|
+
return {
|
|
17
|
+
blob: file,
|
|
18
|
+
name: file.name || path.split("/").at(-1) || path,
|
|
19
|
+
...(file.type ? { mediaType: file.type } : {}),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
resolveRelative(base, relativeUri) {
|
|
23
|
+
return {
|
|
24
|
+
type: "workspace",
|
|
25
|
+
path: resolveWorkspaceRelativePath(workspaceLocator(base).path, decodeRelativeUri(relativeUri)),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async search(query, context) {
|
|
29
|
+
throwIfAborted(context.signal);
|
|
30
|
+
const text = query.query?.trim().toLowerCase() ?? "";
|
|
31
|
+
const tags = query.tags?.map((tag) => tag.toLowerCase()) ?? [];
|
|
32
|
+
const offset = parseCursor(query.cursor);
|
|
33
|
+
const limit = query.limit ?? 20;
|
|
34
|
+
const entries = (await this.source.list()).filter((entry) => {
|
|
35
|
+
if (entry.kind !== "file")
|
|
36
|
+
return false;
|
|
37
|
+
const kind = inferAssetKind(entry.path);
|
|
38
|
+
if (!kind || (query.kind && kind !== query.kind))
|
|
39
|
+
return false;
|
|
40
|
+
const haystack = entry.path.toLowerCase();
|
|
41
|
+
return ((!text ||
|
|
42
|
+
text.split(/\s+/u).every((term) => haystack.includes(term))) &&
|
|
43
|
+
tags.every((tag) => haystack.includes(tag)));
|
|
44
|
+
});
|
|
45
|
+
throwIfAborted(context.signal);
|
|
46
|
+
const slice = entries.slice(offset, offset + limit);
|
|
47
|
+
const items = slice.flatMap((entry) => {
|
|
48
|
+
const kind = inferAssetKind(entry.path);
|
|
49
|
+
if (!kind)
|
|
50
|
+
return [];
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
id: `workspace:${entry.path}`,
|
|
54
|
+
label: entry.name,
|
|
55
|
+
kind,
|
|
56
|
+
source: { type: "workspace", path: entry.path },
|
|
57
|
+
tags: entry.path.split("/").slice(0, -1),
|
|
58
|
+
technical: {
|
|
59
|
+
format: extensionOf(entry.path),
|
|
60
|
+
...(entry.size === undefined ? {} : { size: entry.size }),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
});
|
|
65
|
+
const nextOffset = offset + slice.length;
|
|
66
|
+
return {
|
|
67
|
+
items,
|
|
68
|
+
...(nextOffset < entries.length
|
|
69
|
+
? { nextCursor: String(nextOffset) }
|
|
70
|
+
: {}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async describe(locator, context) {
|
|
74
|
+
throwIfAborted(context.signal);
|
|
75
|
+
const path = normalizeWorkspacePath(workspaceLocator(locator).path);
|
|
76
|
+
const kind = inferAssetKind(path);
|
|
77
|
+
if (!(await this.source.has(path)) || !kind) {
|
|
78
|
+
throw new Error(`Workspace resource not found or unsupported: ${path}`);
|
|
79
|
+
}
|
|
80
|
+
const file = await this.source.read(path);
|
|
81
|
+
return {
|
|
82
|
+
id: `workspace:${path}`,
|
|
83
|
+
label: file.name || path.split("/").at(-1) || path,
|
|
84
|
+
kind,
|
|
85
|
+
source: { type: "workspace", path },
|
|
86
|
+
tags: path.split("/").slice(0, -1),
|
|
87
|
+
technical: {
|
|
88
|
+
format: extensionOf(path),
|
|
89
|
+
size: file.size,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function workspaceLocator(locator) {
|
|
95
|
+
if (locator.type !== "workspace") {
|
|
96
|
+
throw new Error(`Workspace provider cannot resolve: ${locator.type}`);
|
|
97
|
+
}
|
|
98
|
+
return locator;
|
|
99
|
+
}
|
|
100
|
+
function decodeRelativeUri(uri) {
|
|
101
|
+
const path = uri.split(/[?#]/u, 1)[0] ?? uri;
|
|
102
|
+
try {
|
|
103
|
+
return decodeURIComponent(path);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return path;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function extensionOf(path) {
|
|
110
|
+
return path.split(".").at(-1)?.toLowerCase() ?? "";
|
|
111
|
+
}
|
|
112
|
+
function parseCursor(cursor) {
|
|
113
|
+
if (cursor === undefined)
|
|
114
|
+
return 0;
|
|
115
|
+
const value = Number(cursor);
|
|
116
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
117
|
+
throw new Error("Workspace resource cursor is invalid");
|
|
118
|
+
}
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
function throwIfAborted(signal) {
|
|
122
|
+
if (signal.aborted) {
|
|
123
|
+
throw new DOMException("Workspace resource request was aborted", "AbortError");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=workspace-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-provider.js","sourceRoot":"","sources":["../../src/providers/workspace-provider.ts"],"names":[],"mappings":"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"}
|