@takosjp/yurucommu-core 4.1.5 → 4.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takosjp/yurucommu-core",
3
- "version": "4.1.5",
3
+ "version": "4.1.7",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takosjp/yurucommu-api",
3
- "version": "4.1.5",
3
+ "version": "4.1.7",
4
4
  "description": "Typed client SDK and public API contract for yurucommu-server clients.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -319,12 +319,15 @@ async function handleCloudflareCache(
319
319
  cacheKey: string,
320
320
  config: CacheConfig,
321
321
  ): Promise<Response | void> {
322
- const cache = caches.default;
323
322
  const url = new URL(c.req.url);
324
323
  const fullCacheKey = new Request(`${url.origin}/_cache${cacheKey}`);
325
324
 
325
+ let cache: Cache;
326
326
  let cachedResponse: Response | undefined;
327
327
  try {
328
+ // Some runtimes expose CacheStorage but have no backing cache configured;
329
+ // accessing the default getter can fail before match() is reached.
330
+ cache = caches.default;
328
331
  cachedResponse = await cache.match(fullCacheKey);
329
332
  } catch (error) {
330
333
  if (isDefaultCacheUnavailable(error)) {
@@ -395,7 +398,7 @@ function isDefaultCacheUnavailable(error: unknown): boolean {
395
398
  : typeof error === "string"
396
399
  ? error
397
400
  : "";
398
- return /not permitted to access the default cache|default cache.*(?:not|un)available|Cache API.*not available/i.test(
401
+ return /not permitted to access the default cache|default cache.*(?:not|un)available|Cache API.*not available|^No Cache was configured\.?$/i.test(
399
402
  message,
400
403
  );
401
404
  }
@@ -83,7 +83,7 @@ export interface EdgeSqlBinding {
83
83
  /** All-or-none. 1..100 statements, ordered, one Host round trip. */
84
84
  transaction(
85
85
  statements: readonly EdgeSqlStatement[],
86
- ): Promise<readonly EdgeSqlResult[]>;
86
+ ): Promise<{ readonly results: readonly EdgeSqlResult[] }>;
87
87
  }
88
88
 
89
89
  export interface EdgeKvPutOptions {
@@ -158,6 +158,11 @@ export function createEdgeSqlDatabase(binding: EdgeSqlBinding) {
158
158
  await one(prepare(sql, params), method);
159
159
 
160
160
  const batchCallback: AsyncBatchRemoteCallback = async (batch) => {
161
+ if (batch.length < 1) {
162
+ throw new EdgeSqlShapeError(
163
+ "edge.sql: a transaction requires at least one statement",
164
+ );
165
+ }
161
166
  if (batch.length > EDGE_SQL_MAX_STATEMENTS) {
162
167
  throw new EdgeSqlShapeError(
163
168
  `edge.sql: a batch of ${batch.length} statements exceeds the facade ` +
@@ -165,9 +170,26 @@ export function createEdgeSqlDatabase(binding: EdgeSqlBinding) {
165
170
  );
166
171
  }
167
172
  const prepared = batch.map((entry) => prepare(entry.sql, entry.params));
168
- const results = await binding.transaction(
173
+ const transaction = await binding.transaction(
169
174
  prepared.map((entry) => ({ sql: entry.sql, params: entry.params })),
170
175
  );
176
+ const keys =
177
+ typeof transaction === "object" &&
178
+ transaction !== null &&
179
+ !Array.isArray(transaction)
180
+ ? Object.keys(transaction)
181
+ : [];
182
+ if (
183
+ keys.length !== 1 ||
184
+ keys[0] !== "results" ||
185
+ !Array.isArray(transaction?.results)
186
+ ) {
187
+ throw new ProxyColumnMismatchError(
188
+ `edge.sql: transaction returned a malformed result envelope for ` +
189
+ `${prepared.length} statements`,
190
+ );
191
+ }
192
+ const { results } = transaction;
171
193
  if (results.length !== prepared.length) {
172
194
  throw new ProxyColumnMismatchError(
173
195
  `edge.sql: transaction returned ${results.length} results for ` +