@tinycloudlabs/sdk-services 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/base/BaseService.d.ts +151 -0
- package/dist/base/BaseService.d.ts.map +1 -0
- package/dist/base/BaseService.js +221 -0
- package/dist/base/BaseService.js.map +1 -0
- package/dist/base/index.d.ts +6 -0
- package/dist/base/index.d.ts.map +1 -0
- package/dist/base/index.js +6 -0
- package/dist/base/index.js.map +1 -0
- package/dist/base/types.d.ts +36 -0
- package/dist/base/types.d.ts.map +1 -0
- package/dist/base/types.js +7 -0
- package/dist/base/types.js.map +1 -0
- package/dist/context.d.ts +142 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +218 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +43 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +111 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/kv/IKVService.d.ts +148 -0
- package/dist/kv/IKVService.d.ts.map +1 -0
- package/dist/kv/IKVService.js +8 -0
- package/dist/kv/IKVService.js.map +1 -0
- package/dist/kv/KVService.d.ts +153 -0
- package/dist/kv/KVService.d.ts.map +1 -0
- package/dist/kv/KVService.js +337 -0
- package/dist/kv/KVService.js.map +1 -0
- package/dist/kv/PrefixedKVService.d.ts +246 -0
- package/dist/kv/PrefixedKVService.d.ts.map +1 -0
- package/dist/kv/PrefixedKVService.js +145 -0
- package/dist/kv/PrefixedKVService.js.map +1 -0
- package/dist/kv/index.d.ts +10 -0
- package/dist/kv/index.d.ts.map +1 -0
- package/dist/kv/index.js +12 -0
- package/dist/kv/index.js.map +1 -0
- package/dist/kv/types.d.ts +204 -0
- package/dist/kv/types.d.ts.map +1 -0
- package/dist/kv/types.js +16 -0
- package/dist/kv/types.js.map +1 -0
- package/dist/types.d.ts +259 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +72 -0
- package/dist/types.js.map +1 -0
- package/dist/types.schema.d.ts +652 -0
- package/dist/types.schema.d.ts.map +1 -0
- package/dist/types.schema.js +342 -0
- package/dist/types.schema.js.map +1 -0
- package/dist/types.schema.test.d.ts +5 -0
- package/dist/types.schema.test.d.ts.map +1 -0
- package/dist/types.schema.test.js +677 -0
- package/dist/types.schema.test.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KVService - Key-Value storage service implementation.
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic KV service that works with both web-sdk and node-sdk.
|
|
5
|
+
* Uses dependency injection via IServiceContext for platform dependencies.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseService } from "../base/BaseService";
|
|
8
|
+
import { Result } from "../types";
|
|
9
|
+
import { IKVService } from "./IKVService";
|
|
10
|
+
import { IPrefixedKVService } from "./PrefixedKVService";
|
|
11
|
+
import { KVServiceConfig, KVGetOptions, KVPutOptions, KVListOptions, KVDeleteOptions, KVHeadOptions, KVResponse, KVListResponse } from "./types";
|
|
12
|
+
/**
|
|
13
|
+
* KV service implementation.
|
|
14
|
+
*
|
|
15
|
+
* Provides key-value storage operations using TinyCloud's KV API.
|
|
16
|
+
* Uses the Result type pattern for explicit error handling.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Register with SDK
|
|
21
|
+
* const sdk = new TinyCloud({
|
|
22
|
+
* services: { kv: KVService },
|
|
23
|
+
* serviceConfigs: { kv: { prefix: 'myapp' } },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Use the service
|
|
27
|
+
* const result = await sdk.kv.get('settings');
|
|
28
|
+
* if (result.ok) {
|
|
29
|
+
* console.log(result.data.data);
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class KVService extends BaseService implements IKVService {
|
|
34
|
+
/**
|
|
35
|
+
* Service identifier for registration.
|
|
36
|
+
*/
|
|
37
|
+
static readonly serviceName = "kv";
|
|
38
|
+
/**
|
|
39
|
+
* Service configuration.
|
|
40
|
+
*/
|
|
41
|
+
protected _config: KVServiceConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new KVService instance.
|
|
44
|
+
*
|
|
45
|
+
* @param config - Service configuration
|
|
46
|
+
*/
|
|
47
|
+
constructor(config?: KVServiceConfig);
|
|
48
|
+
/**
|
|
49
|
+
* Get the service configuration.
|
|
50
|
+
*/
|
|
51
|
+
get config(): KVServiceConfig;
|
|
52
|
+
/**
|
|
53
|
+
* Get the full path with optional prefix.
|
|
54
|
+
*
|
|
55
|
+
* @param key - The key
|
|
56
|
+
* @param prefixOverride - Optional prefix override
|
|
57
|
+
* @returns The full path
|
|
58
|
+
*/
|
|
59
|
+
private getFullPath;
|
|
60
|
+
/**
|
|
61
|
+
* Get the host URL.
|
|
62
|
+
*/
|
|
63
|
+
private get host();
|
|
64
|
+
/**
|
|
65
|
+
* Execute an invoke operation.
|
|
66
|
+
*
|
|
67
|
+
* @param path - Resource path
|
|
68
|
+
* @param action - KV action
|
|
69
|
+
* @param body - Optional request body
|
|
70
|
+
* @param signal - Optional abort signal
|
|
71
|
+
* @returns Fetch response
|
|
72
|
+
*/
|
|
73
|
+
private invokeOperation;
|
|
74
|
+
/**
|
|
75
|
+
* Create KVResponseHeaders from fetch response headers.
|
|
76
|
+
*
|
|
77
|
+
* @param headers - Fetch response headers
|
|
78
|
+
* @returns KVResponseHeaders object
|
|
79
|
+
*/
|
|
80
|
+
private createResponseHeaders;
|
|
81
|
+
/**
|
|
82
|
+
* Parse response body based on content type.
|
|
83
|
+
*
|
|
84
|
+
* @param response - Fetch response
|
|
85
|
+
* @param raw - Whether to return raw text
|
|
86
|
+
* @returns Parsed data
|
|
87
|
+
*/
|
|
88
|
+
private parseResponse;
|
|
89
|
+
/**
|
|
90
|
+
* Get a value by key.
|
|
91
|
+
*/
|
|
92
|
+
get<T = unknown>(key: string, options?: KVGetOptions): Promise<Result<KVResponse<T>>>;
|
|
93
|
+
/**
|
|
94
|
+
* Store a value at a key.
|
|
95
|
+
*/
|
|
96
|
+
put(key: string, value: unknown, options?: KVPutOptions): Promise<Result<KVResponse<void>>>;
|
|
97
|
+
/**
|
|
98
|
+
* List keys with optional prefix filtering.
|
|
99
|
+
*/
|
|
100
|
+
list(options?: KVListOptions): Promise<Result<KVListResponse>>;
|
|
101
|
+
/**
|
|
102
|
+
* Delete a key.
|
|
103
|
+
*/
|
|
104
|
+
delete(key: string, options?: KVDeleteOptions): Promise<Result<void>>;
|
|
105
|
+
/**
|
|
106
|
+
* Get metadata for a key without retrieving the value.
|
|
107
|
+
*/
|
|
108
|
+
head(key: string, options?: KVHeadOptions): Promise<Result<KVResponse<void>>>;
|
|
109
|
+
/**
|
|
110
|
+
* Create a prefix-scoped view of this KV service.
|
|
111
|
+
*
|
|
112
|
+
* Returns a PrefixedKVService that automatically prefixes all
|
|
113
|
+
* key operations with the specified prefix. This enables apps
|
|
114
|
+
* to isolate their data within a shared space.
|
|
115
|
+
*
|
|
116
|
+
* @param prefix - The prefix to apply to all operations
|
|
117
|
+
* @returns A PrefixedKVService scoped to the prefix
|
|
118
|
+
*
|
|
119
|
+
* ## Prefix Conventions
|
|
120
|
+
*
|
|
121
|
+
* | Pattern | Use Case | Example |
|
|
122
|
+
* | -- | -- | -- |
|
|
123
|
+
* | `/app.{domain}/` | App-private data | `/app.photos.xyz/settings.json` |
|
|
124
|
+
* | `/{type}/` | Shared data type | `/photos/vacation.jpg` |
|
|
125
|
+
* | `/.{name}/` | Hidden/system data | `/.cache/thumbnails/` |
|
|
126
|
+
* | `/public/` | Explicitly shareable | `/public/profile.json` |
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const space = sdk.space('default');
|
|
131
|
+
*
|
|
132
|
+
* // Create prefix-scoped views
|
|
133
|
+
* const myApp = space.kv.withPrefix('/app.myapp.com');
|
|
134
|
+
* const sharedPhotos = space.kv.withPrefix('/photos');
|
|
135
|
+
*
|
|
136
|
+
* // Operations are automatically prefixed
|
|
137
|
+
* await myApp.put('settings.json', { theme: 'dark' });
|
|
138
|
+
* // -> Actually writes to: /app.myapp.com/settings.json
|
|
139
|
+
*
|
|
140
|
+
* await myApp.get('settings.json');
|
|
141
|
+
* // -> Actually reads from: /app.myapp.com/settings.json
|
|
142
|
+
*
|
|
143
|
+
* await sharedPhotos.list();
|
|
144
|
+
* // -> Lists: /photos/*
|
|
145
|
+
*
|
|
146
|
+
* // Nested prefixes
|
|
147
|
+
* const settings = myApp.withPrefix('/settings');
|
|
148
|
+
* await settings.get('theme.json'); // -> /app.myapp.com/settings/theme.json
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
withPrefix(prefix: string): IPrefixedKVService;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=KVService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KVService.d.ts","sourceRoot":"","sources":["../../src/kv/KVService.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,MAAM,EAMP,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAqB,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EACL,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EACf,aAAa,EACb,UAAU,EACV,cAAc,EAGf,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,SAAU,SAAQ,WAAY,YAAW,UAAU;IAC9D;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,WAAW,QAAQ;IAEnC;;OAEG;IACH,UAAkB,OAAO,EAAE,eAAe,CAAC;IAE3C;;;;OAIG;gBACS,MAAM,GAAE,eAAoB;IAKxC;;OAEG;IACH,IAAI,MAAM,IAAI,eAAe,CAE5B;IAED;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACH,OAAO,KAAK,IAAI,GAEf;IAED;;;;;;;;OAQG;YACW,eAAe;IAsB7B;;;;;OAKG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;;;;;OAMG;YACW,aAAa;IA+B3B;;OAEG;IACG,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAiDjC;;OAEG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IA8CpC;;OAEG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAsDpE;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IA6C3E;;OAEG;IACG,IAAI,CACR,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAgDpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB;CAG/C"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KVService - Key-Value storage service implementation.
|
|
3
|
+
*
|
|
4
|
+
* Platform-agnostic KV service that works with both web-sdk and node-sdk.
|
|
5
|
+
* Uses dependency injection via IServiceContext for platform dependencies.
|
|
6
|
+
*/
|
|
7
|
+
import { BaseService } from "../base/BaseService";
|
|
8
|
+
import { ok, err, ErrorCodes, serviceError, } from "../types";
|
|
9
|
+
import { authRequiredError, wrapError } from "../errors";
|
|
10
|
+
import { PrefixedKVService } from "./PrefixedKVService";
|
|
11
|
+
import { KVAction, } from "./types";
|
|
12
|
+
/**
|
|
13
|
+
* KV service implementation.
|
|
14
|
+
*
|
|
15
|
+
* Provides key-value storage operations using TinyCloud's KV API.
|
|
16
|
+
* Uses the Result type pattern for explicit error handling.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Register with SDK
|
|
21
|
+
* const sdk = new TinyCloud({
|
|
22
|
+
* services: { kv: KVService },
|
|
23
|
+
* serviceConfigs: { kv: { prefix: 'myapp' } },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Use the service
|
|
27
|
+
* const result = await sdk.kv.get('settings');
|
|
28
|
+
* if (result.ok) {
|
|
29
|
+
* console.log(result.data.data);
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class KVService extends BaseService {
|
|
34
|
+
/**
|
|
35
|
+
* Create a new KVService instance.
|
|
36
|
+
*
|
|
37
|
+
* @param config - Service configuration
|
|
38
|
+
*/
|
|
39
|
+
constructor(config = {}) {
|
|
40
|
+
super();
|
|
41
|
+
this._config = config;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the service configuration.
|
|
45
|
+
*/
|
|
46
|
+
get config() {
|
|
47
|
+
return this._config;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get the full path with optional prefix.
|
|
51
|
+
*
|
|
52
|
+
* @param key - The key
|
|
53
|
+
* @param prefixOverride - Optional prefix override
|
|
54
|
+
* @returns The full path
|
|
55
|
+
*/
|
|
56
|
+
getFullPath(key, prefixOverride) {
|
|
57
|
+
const prefix = prefixOverride ?? this._config.prefix ?? "";
|
|
58
|
+
return prefix ? `${prefix}/${key}` : key;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get the host URL.
|
|
62
|
+
*/
|
|
63
|
+
get host() {
|
|
64
|
+
return this.context.hosts[0];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Execute an invoke operation.
|
|
68
|
+
*
|
|
69
|
+
* @param path - Resource path
|
|
70
|
+
* @param action - KV action
|
|
71
|
+
* @param body - Optional request body
|
|
72
|
+
* @param signal - Optional abort signal
|
|
73
|
+
* @returns Fetch response
|
|
74
|
+
*/
|
|
75
|
+
async invokeOperation(path, action, body, signal) {
|
|
76
|
+
const session = this.context.session;
|
|
77
|
+
const headers = this.context.invoke(session, "kv", path, action);
|
|
78
|
+
return this.context.fetch(`${this.host}/invoke`, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
headers,
|
|
81
|
+
body,
|
|
82
|
+
signal: this.combineSignals(signal),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create KVResponseHeaders from fetch response headers.
|
|
87
|
+
*
|
|
88
|
+
* @param headers - Fetch response headers
|
|
89
|
+
* @returns KVResponseHeaders object
|
|
90
|
+
*/
|
|
91
|
+
createResponseHeaders(headers) {
|
|
92
|
+
return {
|
|
93
|
+
etag: headers.get("etag") ?? undefined,
|
|
94
|
+
contentType: headers.get("content-type") ?? undefined,
|
|
95
|
+
lastModified: headers.get("last-modified") ?? undefined,
|
|
96
|
+
contentLength: headers.get("content-length")
|
|
97
|
+
? parseInt(headers.get("content-length"), 10)
|
|
98
|
+
: undefined,
|
|
99
|
+
get: (name) => headers.get(name),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Parse response body based on content type.
|
|
104
|
+
*
|
|
105
|
+
* @param response - Fetch response
|
|
106
|
+
* @param raw - Whether to return raw text
|
|
107
|
+
* @returns Parsed data
|
|
108
|
+
*/
|
|
109
|
+
async parseResponse(response, raw = false) {
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (raw) {
|
|
114
|
+
return (await response.text());
|
|
115
|
+
}
|
|
116
|
+
const contentType = response.headers.get("content-type");
|
|
117
|
+
if (contentType?.includes("application/json")) {
|
|
118
|
+
return (await response.json());
|
|
119
|
+
}
|
|
120
|
+
else if (contentType?.startsWith("text/")) {
|
|
121
|
+
return (await response.text());
|
|
122
|
+
}
|
|
123
|
+
// No content-type header - try to parse as JSON, fall back to text
|
|
124
|
+
const text = await response.text();
|
|
125
|
+
if (!text) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
return JSON.parse(text);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return text;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get a value by key.
|
|
137
|
+
*/
|
|
138
|
+
async get(key, options) {
|
|
139
|
+
return this.withTelemetry("get", key, async () => {
|
|
140
|
+
if (!this.requireAuth()) {
|
|
141
|
+
return err(authRequiredError("kv"));
|
|
142
|
+
}
|
|
143
|
+
const path = this.getFullPath(key, options?.prefix);
|
|
144
|
+
try {
|
|
145
|
+
const response = await this.invokeOperation(path, KVAction.GET, undefined, options?.signal);
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
if (response.status === 404) {
|
|
148
|
+
return err(serviceError(ErrorCodes.KV_NOT_FOUND, `Key not found: ${key}`, "kv"));
|
|
149
|
+
}
|
|
150
|
+
const errorText = await response.text();
|
|
151
|
+
return err(serviceError(ErrorCodes.NETWORK_ERROR, `Failed to get key "${key}": ${response.status} - ${errorText}`, "kv", { meta: { status: response.status, statusText: response.statusText } }));
|
|
152
|
+
}
|
|
153
|
+
const data = await this.parseResponse(response, options?.raw);
|
|
154
|
+
return ok({
|
|
155
|
+
data: data,
|
|
156
|
+
headers: this.createResponseHeaders(response.headers),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
return err(wrapError("kv", error));
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Store a value at a key.
|
|
166
|
+
*/
|
|
167
|
+
async put(key, value, options) {
|
|
168
|
+
return this.withTelemetry("put", key, async () => {
|
|
169
|
+
if (!this.requireAuth()) {
|
|
170
|
+
return err(authRequiredError("kv"));
|
|
171
|
+
}
|
|
172
|
+
const path = this.getFullPath(key, options?.prefix);
|
|
173
|
+
// Serialize value to string
|
|
174
|
+
let body;
|
|
175
|
+
if (typeof value === "string") {
|
|
176
|
+
body = value;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
body = JSON.stringify(value);
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const response = await this.invokeOperation(path, KVAction.PUT, body, options?.signal);
|
|
183
|
+
if (!response.ok) {
|
|
184
|
+
const errorText = await response.text();
|
|
185
|
+
return err(serviceError(ErrorCodes.KV_WRITE_FAILED, `Failed to put key "${key}": ${response.status} - ${errorText}`, "kv", { meta: { status: response.status, statusText: response.statusText } }));
|
|
186
|
+
}
|
|
187
|
+
return ok({
|
|
188
|
+
data: undefined,
|
|
189
|
+
headers: this.createResponseHeaders(response.headers),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
return err(wrapError("kv", error));
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* List keys with optional prefix filtering.
|
|
199
|
+
*/
|
|
200
|
+
async list(options) {
|
|
201
|
+
return this.withTelemetry("list", options?.prefix, async () => {
|
|
202
|
+
if (!this.requireAuth()) {
|
|
203
|
+
return err(authRequiredError("kv"));
|
|
204
|
+
}
|
|
205
|
+
// Build the path from prefix and optional path
|
|
206
|
+
let listPath = options?.prefix ?? this._config.prefix ?? "";
|
|
207
|
+
if (options?.path) {
|
|
208
|
+
listPath = listPath ? `${listPath}/${options.path}` : options.path;
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
const response = await this.invokeOperation(listPath, KVAction.LIST, undefined, options?.signal);
|
|
212
|
+
if (!response.ok) {
|
|
213
|
+
const errorText = await response.text();
|
|
214
|
+
return err(serviceError(ErrorCodes.NETWORK_ERROR, `Failed to list keys: ${response.status} - ${errorText}`, "kv", { meta: { status: response.status, statusText: response.statusText } }));
|
|
215
|
+
}
|
|
216
|
+
let keys = await this.parseResponse(response, options?.raw);
|
|
217
|
+
keys = keys ?? [];
|
|
218
|
+
// Optionally remove prefix from keys
|
|
219
|
+
if (options?.removePrefix && listPath) {
|
|
220
|
+
const prefixWithSlash = listPath.endsWith("/")
|
|
221
|
+
? listPath
|
|
222
|
+
: `${listPath}/`;
|
|
223
|
+
keys = keys.map((key) => key.startsWith(prefixWithSlash)
|
|
224
|
+
? key.slice(prefixWithSlash.length)
|
|
225
|
+
: key);
|
|
226
|
+
}
|
|
227
|
+
return ok({ keys });
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
return err(wrapError("kv", error));
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Delete a key.
|
|
236
|
+
*/
|
|
237
|
+
async delete(key, options) {
|
|
238
|
+
return this.withTelemetry("delete", key, async () => {
|
|
239
|
+
if (!this.requireAuth()) {
|
|
240
|
+
return err(authRequiredError("kv"));
|
|
241
|
+
}
|
|
242
|
+
const path = this.getFullPath(key, options?.prefix);
|
|
243
|
+
try {
|
|
244
|
+
const response = await this.invokeOperation(path, KVAction.DELETE, undefined, options?.signal);
|
|
245
|
+
if (!response.ok) {
|
|
246
|
+
if (response.status === 404) {
|
|
247
|
+
return err(serviceError(ErrorCodes.KV_NOT_FOUND, `Key not found: ${key}`, "kv"));
|
|
248
|
+
}
|
|
249
|
+
const errorText = await response.text();
|
|
250
|
+
return err(serviceError(ErrorCodes.NETWORK_ERROR, `Failed to delete key "${key}": ${response.status} - ${errorText}`, "kv", { meta: { status: response.status, statusText: response.statusText } }));
|
|
251
|
+
}
|
|
252
|
+
return ok(undefined);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
return err(wrapError("kv", error));
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get metadata for a key without retrieving the value.
|
|
261
|
+
*/
|
|
262
|
+
async head(key, options) {
|
|
263
|
+
return this.withTelemetry("head", key, async () => {
|
|
264
|
+
if (!this.requireAuth()) {
|
|
265
|
+
return err(authRequiredError("kv"));
|
|
266
|
+
}
|
|
267
|
+
const path = this.getFullPath(key, options?.prefix);
|
|
268
|
+
try {
|
|
269
|
+
const response = await this.invokeOperation(path, KVAction.HEAD, undefined, options?.signal);
|
|
270
|
+
if (!response.ok) {
|
|
271
|
+
if (response.status === 404) {
|
|
272
|
+
return err(serviceError(ErrorCodes.KV_NOT_FOUND, `Key not found: ${key}`, "kv"));
|
|
273
|
+
}
|
|
274
|
+
const errorText = await response.text();
|
|
275
|
+
return err(serviceError(ErrorCodes.NETWORK_ERROR, `Failed to get metadata for key "${key}": ${response.status} - ${errorText}`, "kv", { meta: { status: response.status, statusText: response.statusText } }));
|
|
276
|
+
}
|
|
277
|
+
return ok({
|
|
278
|
+
data: undefined,
|
|
279
|
+
headers: this.createResponseHeaders(response.headers),
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
return err(wrapError("kv", error));
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Create a prefix-scoped view of this KV service.
|
|
289
|
+
*
|
|
290
|
+
* Returns a PrefixedKVService that automatically prefixes all
|
|
291
|
+
* key operations with the specified prefix. This enables apps
|
|
292
|
+
* to isolate their data within a shared space.
|
|
293
|
+
*
|
|
294
|
+
* @param prefix - The prefix to apply to all operations
|
|
295
|
+
* @returns A PrefixedKVService scoped to the prefix
|
|
296
|
+
*
|
|
297
|
+
* ## Prefix Conventions
|
|
298
|
+
*
|
|
299
|
+
* | Pattern | Use Case | Example |
|
|
300
|
+
* | -- | -- | -- |
|
|
301
|
+
* | `/app.{domain}/` | App-private data | `/app.photos.xyz/settings.json` |
|
|
302
|
+
* | `/{type}/` | Shared data type | `/photos/vacation.jpg` |
|
|
303
|
+
* | `/.{name}/` | Hidden/system data | `/.cache/thumbnails/` |
|
|
304
|
+
* | `/public/` | Explicitly shareable | `/public/profile.json` |
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* const space = sdk.space('default');
|
|
309
|
+
*
|
|
310
|
+
* // Create prefix-scoped views
|
|
311
|
+
* const myApp = space.kv.withPrefix('/app.myapp.com');
|
|
312
|
+
* const sharedPhotos = space.kv.withPrefix('/photos');
|
|
313
|
+
*
|
|
314
|
+
* // Operations are automatically prefixed
|
|
315
|
+
* await myApp.put('settings.json', { theme: 'dark' });
|
|
316
|
+
* // -> Actually writes to: /app.myapp.com/settings.json
|
|
317
|
+
*
|
|
318
|
+
* await myApp.get('settings.json');
|
|
319
|
+
* // -> Actually reads from: /app.myapp.com/settings.json
|
|
320
|
+
*
|
|
321
|
+
* await sharedPhotos.list();
|
|
322
|
+
* // -> Lists: /photos/*
|
|
323
|
+
*
|
|
324
|
+
* // Nested prefixes
|
|
325
|
+
* const settings = myApp.withPrefix('/settings');
|
|
326
|
+
* await settings.get('theme.json'); // -> /app.myapp.com/settings/theme.json
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
withPrefix(prefix) {
|
|
330
|
+
return new PrefixedKVService(this, prefix);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Service identifier for registration.
|
|
335
|
+
*/
|
|
336
|
+
KVService.serviceName = "kv";
|
|
337
|
+
//# sourceMappingURL=KVService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KVService.js","sourceRoot":"","sources":["../../src/kv/KVService.ts"],"names":[],"mappings":"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"}
|