Files
johndoe6345789 9a40d3f6ea refactor: move root codegen/ and pastebin/ into frontends/
- codegen/packages/spark-tools → frontends/codegen/packages/spark-tools
- root pastebin/ was subset of frontends/pastebin/, removed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 23:03:11 +00:00

178 lines
6.6 KiB
JavaScript

const KvEventType = {
SPARK_KV_UPDATED: 'sparkKvUpdated',
SPARK_KV_DELETED: 'sparkKvDeleted',
};
// This function allows us to send messages from the Spark back to the Workbench application.
// Specifically, we want to send updates about KV operations, to allow the Workbench
// to update its UI accordingly.
const sendEventToWorkbench = (message) => {
if (import.meta.env.DEV) {
window.parent.postMessage(message, '*');
}
};
class KVClient {
/**
* Retrieves a list of all keys in the KV store.
* @returns A list of all keys in the KV store, or an empty array if there are no keys.
*/
async getKeys() {
// Fetching the root URL will return all keys in the KV store.
const response = await fetch(BASE_KV_SERVICE_URL, {
method: 'GET',
});
if (!response.ok) {
const errorMessage = `Failed to fetch KV keys: ${response.statusText}`;
return Promise.reject(new Error(errorMessage));
}
let json;
try {
json = await response.json();
}
catch (error) {
const errorMessage = 'Failed to parse KV keys response';
return Promise.reject(new Error(errorMessage));
}
if (!Array.isArray(json)) {
const errorMessage = 'KV keys response is not an array';
return Promise.reject(new Error(errorMessage));
}
return json;
}
/**
* Retrieves all key-value pairs from the KV store.
* @returns An object containing all key-value pairs, or an empty object if there are no keys.
*
* TODO: replace with batch request
*/
async getAll() {
const keys = await this.getKeys();
const result = {};
// Fetch all values concurrently
const values = await Promise.all(keys.map(key => this.getKey(key)));
// Build the result object
keys.forEach((key, index) => {
const value = values[index];
if (value !== undefined) {
result[key] = value;
}
});
return result;
}
/**
* Retrieves the value associated with the given key from the KV store.
* @param key The key to retrieve.
* @param collectionName Optional collection name to include as a URL parameter.
* @returns The value associated with the key, or undefined if not found.
*/
async getKey(key, collectionName) {
let url = `${BASE_KV_SERVICE_URL}/${encodeURIComponent(key)}`;
if (collectionName) {
url += `?collection=${encodeURIComponent(collectionName)}`;
}
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': `text/plain`,
},
});
if (!response.ok) {
const errorMessage = `Failed to fetch KV key: ${response.statusText}`;
if (response.status === 404) {
// If the key does not exist, return undefined
return undefined;
}
// For other errors, reject with an error message
return Promise.reject(new Error(errorMessage));
}
const responseText = await response.text();
// Extract the value from the response text.
// Important to remember that even a simple string should be returned to us as a JSON-encoded value,
// meaning that the parse should succeed.
try {
return JSON.parse(responseText);
}
catch (error) {
const errorMessage = `Failed to parse KV key response`;
return Promise.reject(new Error(errorMessage));
}
}
/**
* Retrieves the value associated with the given key from the KV store, while also setting it if it does not exist.
* @param key The key to retrieve.
* @param value The value to set if the key does not exist.
* @returns The value associated with the key, whether it was retrieved or newly set.
*/
async getOrSetKey(key, value) {
const existingValue = await this.getKey(key);
if (existingValue !== undefined) {
return existingValue;
}
const response = await fetch(`${BASE_KV_SERVICE_URL}/${encodeURIComponent(key)}`, {
method: 'POST',
headers: {
'Content-Type': `text/plain`,
'X-Spark-Initial': 'true',
},
body: JSON.stringify(value),
});
if (!response.ok) {
const errorMessage = `Failed to set default value for key: ${response.statusText}`;
return Promise.reject(new Error(errorMessage));
}
sendEventToWorkbench({
type: KvEventType.SPARK_KV_UPDATED,
payload: { key },
});
return value;
}
/**
* Sets the value for the given key in the KV store.
* @param key The key to set.
* @param value The value to associate with the key.
* @param collectionName Optional collection name to include as a URL parameter.
* @returns A promise that resolves when the operation is complete.
*/
async setKey(key, value, collectionName) {
let url = `${BASE_KV_SERVICE_URL}/${encodeURIComponent(key)}`;
if (collectionName) {
url += `?collection=${encodeURIComponent(collectionName)}`;
}
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': `text/plain`,
'X-Spark-Initial': 'false',
},
body: JSON.stringify(value),
});
if (!response.ok) {
const errorMessage = `Failed to set key: ${response.statusText}`;
return Promise.reject(new Error(errorMessage));
}
sendEventToWorkbench({
type: KvEventType.SPARK_KV_UPDATED,
payload: { key, value: JSON.stringify(value) },
});
}
/**
* Deletes the value associated with the given key from the KV store.
* @param key The key to delete from the KV store.
* @param collectionName Optional collection name to include as a URL parameter.
*/
async deleteKey(key, collectionName) {
let url = `${BASE_KV_SERVICE_URL}/${encodeURIComponent(key)}`;
if (collectionName) {
url += `?collection=${encodeURIComponent(collectionName)}`;
}
await fetch(url, { method: 'DELETE' });
sendEventToWorkbench({
type: KvEventType.SPARK_KV_DELETED,
payload: { key },
});
}
}
export { KVClient as K, KvEventType as a };
//# sourceMappingURL=kv-DBiZoNWq.js.map