ugly-app 0.1.758 → 0.1.760

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.
@@ -1,2 +1,2 @@
1
- export declare const CLI_VERSION = "0.1.758";
1
+ export declare const CLI_VERSION = "0.1.760";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.758";
2
+ export const CLI_VERSION = "0.1.760";
3
3
  //# sourceMappingURL=version.js.map
@@ -22,6 +22,9 @@ export interface StorageClient {
22
22
  uploadUrl: string;
23
23
  resultUrl: string;
24
24
  }>;
25
+ /** Delete an object. Idempotent — S3/R2 treat deleting a missing key as
26
+ * success, so callers can sweep expired keys without pre-checking. */
27
+ delete(bucket: 'public' | 'temp', key: string): Promise<void>;
25
28
  }
26
29
  export interface StorageConfig {
27
30
  accessKeyId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../src/server/Storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAYH,MAAM,WAAW,aAAa;IAC5B,GAAG,CACD,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACpD,YAAY,CACV,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAQD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAO5D;AA8DD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAErD;AAQD;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAMlC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AA4ED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAmBnD"}
1
+ {"version":3,"file":"Storage.d.ts","sourceRoot":"","sources":["../../src/server/Storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAYH,MAAM,WAAW,aAAa;IAC5B,GAAG,CACD,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACpD,YAAY,CACV,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD;2EACuE;IACvE,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAQD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAO5D;AA8DD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAErD;AAQD;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED,wBAAgB,WAAW,IAAI,IAAI,CAMlC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAuFD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAuBnD"}
@@ -127,6 +127,11 @@ async function moveToPublicRaw(tempKey, destKey) {
127
127
  await client.send(new DeleteObjectCommand({ Bucket: cfg.tempBucket, Key: tempKey }));
128
128
  return urlFor('public', destKey, cfg);
129
129
  }
130
+ async function deleteRaw(bucket, key) {
131
+ const { client, cfg } = getClient();
132
+ const targetBucket = bucket === 'temp' ? cfg.tempBucket : cfg.bucket;
133
+ await client.send(new DeleteObjectCommand({ Bucket: targetBucket, Key: key }));
134
+ }
130
135
  async function presignedPutRaw(bucket, key) {
131
136
  const { client, cfg } = getClient();
132
137
  const targetBucket = bucket === 'temp' ? cfg.tempBucket : cfg.bucket;
@@ -159,6 +164,9 @@ export function createStorageClient() {
159
164
  async presignedPut(bucket, key) {
160
165
  return presignedPutRaw(bucket, prefixKey(key));
161
166
  },
167
+ async delete(bucket, key) {
168
+ return deleteRaw(bucket, prefixKey(key));
169
+ },
162
170
  };
163
171
  }
164
172
  //# sourceMappingURL=Storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Storage.js","sourceRoot":"","sources":["../../src/server/Storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,GACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkC7D,6EAA6E;AAE7E,IAAI,OAAO,GAAoB,IAAI,CAAC;AACpC,IAAI,OAAO,GAAkB,EAAE,CAAC;AAChC,IAAI,cAAc,GAAG,EAAE,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;AACtC,CAAC;AAaD,SAAS,aAAa;IACpB,MAAM,WAAW,GACf,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACzD,MAAM,eAAe,GACnB,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAChE,MAAM,aAAa,GACjB,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC;IAEnE,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,6DAA6D,CAChE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW;QACX,eAAe;QACf,MAAM;QACN,QAAQ;QACR,aAAa;QACb,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM;QACxC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,aAAa;QACjD,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,IAAI;KAC3D,CAAC;AACJ,CAAC;AAED,IAAI,SAAS,GAA0B,IAAI,CAAC;AAE5C,SAAS,SAAS;IAChB,IAAI,OAAO,IAAI,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;IACrE,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,OAAO,GAAG,IAAI,QAAQ,CAAC;QACrB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,MAAM;QACd,WAAW,EAAE;YACX,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,eAAe,EAAE,GAAG,CAAC,eAAe;SACrC;QACD,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IACH,SAAS,GAAG,GAAG,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC;AAED,6EAA6E;AAE7E,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,cAAc,GAAG,MAAM,CAAC;AAC1B,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3D,CAAC;AAED,6EAA6E;AAE7E;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,SAAS,EAAE,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,GAAG,IAAI,CAAC;QACf,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,KAAK,IAAI,CAAC;AAC1B,CAAC;AAED,6EAA6E;AAE7E,SAAS,OAAO,CAAC,IAAY,EAAE,IAAY;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1C,OAAO,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,MAAM,CACb,MAAyB,EACzB,GAAW,EACX,GAAmB;IAEnB,MAAM,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;IACrE,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,6EAA6E;AAE7E,KAAK,UAAU,MAAM,CACnB,MAAyB,EACzB,GAAW,EACX,IAAY,EACZ,WAAmB;IAEnB,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACrE,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,gBAAgB,CAAC;QACnB,MAAM,EAAE,YAAY;QACpB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,WAAW;KACzB,CAAC,CACH,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,OAAe,EACf,OAAe;IAEf,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,iBAAiB,CAAC;QACpB,UAAU,EAAE,GAAG,GAAG,CAAC,UAAU,IAAI,OAAO,EAAE;QAC1C,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,OAAO;KACb,CAAC,CACH,CAAC;IACF,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAClE,CAAC;IACF,OAAO,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,MAAc,EACd,GAAW;IAEX,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACrE,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC;QACnC,MAAM,EAAE,YAAY;QACpB,GAAG,EAAE,GAAG;KACT,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE;QACpD,SAAS,EAAE,GAAG,CAAC,oBAAoB;KACpC,CAAC,CAAC;IACH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,6EAA6E;AAE7E;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW;YACtC,OAAO,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QAC3D,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO;YACjC,OAAO,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QAED,GAAG,CAAC,MAAM,EAAE,GAAG;YACb,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG;YAC5B,OAAO,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Storage.js","sourceRoot":"","sources":["../../src/server/Storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,QAAQ,GACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAqC7D,6EAA6E;AAE7E,IAAI,OAAO,GAAoB,IAAI,CAAC;AACpC,IAAI,OAAO,GAAkB,EAAE,CAAC;AAChC,IAAI,cAAc,GAAG,EAAE,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;AACtC,CAAC;AAaD,SAAS,aAAa;IACpB,MAAM,WAAW,GACf,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACzD,MAAM,eAAe,GACnB,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAChE,MAAM,aAAa,GACjB,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,EAAE,CAAC;IAEnE,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,6DAA6D,CAChE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,WAAW;QACX,eAAe;QACf,MAAM;QACN,QAAQ;QACR,aAAa;QACb,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,MAAM;QACxC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,aAAa;QACjD,oBAAoB,EAAE,OAAO,CAAC,oBAAoB,IAAI,IAAI;KAC3D,CAAC;AACJ,CAAC;AAED,IAAI,SAAS,GAA0B,IAAI,CAAC;AAE5C,SAAS,SAAS;IAChB,IAAI,OAAO,IAAI,SAAS;QAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;IACrE,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,OAAO,GAAG,IAAI,QAAQ,CAAC;QACrB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,MAAM;QACd,WAAW,EAAE;YACX,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,eAAe,EAAE,GAAG,CAAC,eAAe;SACrC;QACD,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IACH,SAAS,GAAG,GAAG,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAClC,CAAC;AAED,6EAA6E;AAE7E,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,cAAc,GAAG,MAAM,CAAC;AAC1B,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3D,CAAC;AAED,6EAA6E;AAE7E;;;;GAIG;AACH,MAAM,UAAU,WAAW;IACzB,SAAS,EAAE,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,GAAG,IAAI,CAAC;QACf,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,KAAK,IAAI,CAAC;AAC1B,CAAC;AAED,6EAA6E;AAE7E,SAAS,OAAO,CAAC,IAAY,EAAE,IAAY;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1C,OAAO,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,MAAM,CACb,MAAyB,EACzB,GAAW,EACX,GAAmB;IAEnB,MAAM,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;IACrE,OAAO,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,6EAA6E;AAE7E,KAAK,UAAU,MAAM,CACnB,MAAyB,EACzB,GAAW,EACX,IAAY,EACZ,WAAmB;IAEnB,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACrE,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,gBAAgB,CAAC;QACnB,MAAM,EAAE,YAAY;QACpB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,WAAW;KACzB,CAAC,CACH,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,OAAe,EACf,OAAe;IAEf,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,iBAAiB,CAAC;QACpB,UAAU,EAAE,GAAG,GAAG,CAAC,UAAU,IAAI,OAAO,EAAE;QAC1C,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,OAAO;KACb,CAAC,CACH,CAAC;IACF,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAClE,CAAC;IACF,OAAO,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,MAAyB,EACzB,GAAW;IAEX,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACrE,MAAM,MAAM,CAAC,IAAI,CACf,IAAI,mBAAmB,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAC5D,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,MAAc,EACd,GAAW;IAEX,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACrE,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC;QACnC,MAAM,EAAE,YAAY;QACpB,GAAG,EAAE,GAAG;KACT,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE;QACpD,SAAS,EAAE,GAAG,CAAC,oBAAoB;KACpC,CAAC,CAAC;IACH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,6EAA6E;AAE7E;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW;YACtC,OAAO,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QAC3D,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO;YACjC,OAAO,eAAe,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACjE,CAAC;QAED,GAAG,CAAC,MAAM,EAAE,GAAG;YACb,MAAM,EAAE,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG;YAC5B,OAAO,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG;YACtB,OAAO,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/adapter/node/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAKV,aAAa,EAGd,MAAM,aAAa,CAAC;AAsIrB,eAAO,MAAM,WAAW,EAAE,aAMzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/adapter/node/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAKV,aAAa,EAGd,MAAM,aAAa,CAAC;AAuIrB,eAAO,MAAM,WAAW,EAAE,aAMzB,CAAC"}
@@ -83,6 +83,7 @@ function getNodeStorage() {
83
83
  presignedPut: client.presignedPut.bind(client),
84
84
  moveToPublic: client.moveToPublic.bind(client),
85
85
  url: client.url.bind(client),
86
+ delete: client.delete.bind(client),
86
87
  };
87
88
  return _storageInstance;
88
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/adapter/node/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/adapter/node/index.ts"],"names":[],"mappings":"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"}
@@ -114,6 +114,13 @@ export interface StorageAdapter {
114
114
  }>;
115
115
  moveToPublic(tempKey: string, destKey: string): Promise<string>;
116
116
  url(bucket: StorageBucket, key: string): string;
117
+ /**
118
+ * Delete an object. Idempotent (deleting a missing key is a no-op success),
119
+ * so callers can sweep expired keys without pre-checking. Optional for
120
+ * back-compat — feature-detect via the presence of the method; both the
121
+ * Node (S3) and Workers (R2 binding) adapters implement it.
122
+ */
123
+ delete?(bucket: StorageBucket, key: string): Promise<void>;
117
124
  }
118
125
  /**
119
126
  * Cron + queue layer. Node adapter wires both to `setInterval` loops
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/adapter/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/server/adapter/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAKnD;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,GAC9B,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhB;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAChE;AAKD;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,QAAQ,IAClC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAO/B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAE9D;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;OAIG;IACH,SAAS,CACP,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,GACrC,MAAM,IAAI,CAAC;CACf;AAKD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,CACD,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,EACvC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;;;OAMG;IACH,YAAY,CAAC,CACX,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAErD,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAEhD;;;;;OAKG;IACH,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAKD;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,YAAY,CACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC3B,IAAI,CAAC;IAER,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,EAC7C,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3B,IAAI,CAAC;IAER,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAKD;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/server/adapter/workers/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAOjE,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,EACZ,aAAa,EAAE,MAAM,GACpB,cAAc,CAqDhB"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/server/adapter/workers/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,aAAa,CAAC;AAOjE,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,QAAQ,EACZ,aAAa,EAAE,MAAM,GACpB,cAAc,CA0DhB"}
@@ -53,6 +53,10 @@ export function createWorkersStorage(r2, publicUrlBase) {
53
53
  url(which, key) {
54
54
  return `${publicUrlBase}/${prefixed(which, key)}`;
55
55
  },
56
+ async delete(which, key) {
57
+ // R2 delete is idempotent — a missing key resolves without error.
58
+ await r2.delete(prefixed(which, key));
59
+ },
56
60
  };
57
61
  }
58
62
  //# sourceMappingURL=storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/server/adapter/workers/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,MAAM,UAAU,GAAkC;IAChD,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,OAAO;CACd,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAClC,EAAY,EACZ,aAAqB;IAErB,MAAM,QAAQ,GAAG,CAAC,KAAoB,EAAE,GAAW,EAAU,EAAE,CAC7D,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC;IAE/B,OAAO;QACL,KAAK,CAAC,GAAG,CACP,KAAoB,EACpB,GAAW,EACX,IAAuC,EACvC,WAAmB;YAEnB,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACvC,iEAAiE;YACjE,2DAA2D;YAC3D,MAAM,EAAE,GACN,IAAI,YAAY,WAAW;gBACzB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAChB,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAClB,CAAC;YACxB,MAAM,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE;gBAC1B,YAAY,EAAE,EAAE,WAAW,EAAE;aAC9B,CAAC,CAAC;YACH,OAAO,GAAG,aAAa,IAAI,SAAS,EAAE,CAAC;QACzC,CAAC;QAED,iEAAiE;QACjE,+DAA+D;QAC/D,+DAA+D;QAC/D,kEAAkE;QAClE,+DAA+D;QAC/D,kEAAkE;QAClE,8DAA8D;QAE9D,KAAK,CAAC,YAAY,CAAC,OAAe,EAAE,OAAe;YACjD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,aAAa,CAAC,CAAC;YAC/E,CAAC;YACD,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE;gBAC1B,YAAY,EAAE,GAAG,CAAC,YAAY;aAC/B,CAAC,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,OAAO,GAAG,aAAa,IAAI,GAAG,EAAE,CAAC;QACnC,CAAC;QAED,GAAG,CAAC,KAAoB,EAAE,GAAW;YACnC,OAAO,GAAG,aAAa,IAAI,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;QACpD,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../src/server/adapter/workers/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,MAAM,UAAU,GAAkC;IAChD,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,OAAO;CACd,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAClC,EAAY,EACZ,aAAqB;IAErB,MAAM,QAAQ,GAAG,CAAC,KAAoB,EAAE,GAAW,EAAU,EAAE,CAC7D,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC;IAE/B,OAAO;QACL,KAAK,CAAC,GAAG,CACP,KAAoB,EACpB,GAAW,EACX,IAAuC,EACvC,WAAmB;YAEnB,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACvC,iEAAiE;YACjE,2DAA2D;YAC3D,MAAM,EAAE,GACN,IAAI,YAAY,WAAW;gBACzB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAChB,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAClB,CAAC;YACxB,MAAM,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE;gBAC1B,YAAY,EAAE,EAAE,WAAW,EAAE;aAC9B,CAAC,CAAC;YACH,OAAO,GAAG,aAAa,IAAI,SAAS,EAAE,CAAC;QACzC,CAAC;QAED,iEAAiE;QACjE,+DAA+D;QAC/D,+DAA+D;QAC/D,kEAAkE;QAClE,+DAA+D;QAC/D,kEAAkE;QAClE,8DAA8D;QAE9D,KAAK,CAAC,YAAY,CAAC,OAAe,EAAE,OAAe;YACjD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,aAAa,CAAC,CAAC;YAC/E,CAAC;YACD,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE;gBAC1B,YAAY,EAAE,GAAG,CAAC,YAAY;aAC/B,CAAC,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,OAAO,GAAG,aAAa,IAAI,GAAG,EAAE,CAAC;QACnC,CAAC;QAED,GAAG,CAAC,KAAoB,EAAE,GAAW;YACnC,OAAO,GAAG,aAAa,IAAI,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;QACpD,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAoB,EAAE,GAAW;YAC5C,kEAAkE;YAClE,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Single source of truth for the btree expression indexes a collection declares
3
- * via `indexes: [{ fields: { <field>: 1 } }]`.
3
+ * via `indexes: [{ fields: { <field>: 1 | -1, ... } }]`.
4
4
  *
5
5
  * The default `idx_<c>_data` GIN index covers JSONB containment (`data @> …`),
6
6
  * but it CANNOT serve the scalar lookups the query layer actually emits
@@ -9,12 +9,22 @@
9
9
  * sequential-scans — invisible on a small table, a hang once it grows past the
10
10
  * 30s statement_timeout.
11
11
  *
12
+ * Single-field AND composite (multi-field) indexes are emitted. A composite
13
+ * `{ fields: { a: 1, b: -1 } }` produces ONE btree over
14
+ * `((data->>'a'), (data->>'b') DESC)` — which serves a multi-field equality
15
+ * filter AND a matching `ORDER BY` in a single index seek. (A bitmap-AND of
16
+ * single-field indexes can satisfy the filter, but never the ordering.) Field
17
+ * order and per-field direction (1 = ASC, -1 = DESC) are preserved from the
18
+ * declaration; the `PostgresIndexes` coverage checker already credits every
19
+ * field of a composite expression index, so declaring one silences the
20
+ * per-field unindexed warning for all of its fields.
21
+ *
12
22
  * Pure string-builder (no pg/pool imports) so it's safe to share across the Node
13
23
  * schema sync (`PostgresSchema.ensureTable`), the Workers `/_init` route, and the
14
24
  * migration generator (`schemaGen`). Statements are idempotent (IF NOT EXISTS) so
15
25
  * every call site can run them on every deploy.
16
26
  */
17
27
  import type { IndexDef } from '../shared/DB.js';
18
- /** Raw `CREATE [UNIQUE] INDEX` SQL for each declared single-field index. */
28
+ /** Raw `CREATE [UNIQUE] INDEX` SQL for each declared (single- or multi-field) index. */
19
29
  export declare function fieldIndexStatements(collection: string, indexes?: IndexDef[]): string[];
20
30
  //# sourceMappingURL=schemaIndexes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schemaIndexes.d.ts","sourceRoot":"","sources":["../../src/server/schemaIndexes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ,EAAE,GACnB,MAAM,EAAE,CAmBV"}
1
+ {"version":3,"file":"schemaIndexes.d.ts","sourceRoot":"","sources":["../../src/server/schemaIndexes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,QAAQ,EAAE,GACnB,MAAM,EAAE,CAwBV"}
@@ -1,23 +1,28 @@
1
1
  const VALID_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
2
- /** Raw `CREATE [UNIQUE] INDEX` SQL for each declared single-field index. */
2
+ /** Raw `CREATE [UNIQUE] INDEX` SQL for each declared (single- or multi-field) index. */
3
3
  export function fieldIndexStatements(collection, indexes) {
4
4
  if (!VALID_NAME.test(collection))
5
5
  return [];
6
6
  const out = [];
7
7
  for (const idx of indexes ?? []) {
8
- const fields = Object.keys(idx.fields);
9
- // Single-field expression indexes only — matches the query layer, which
10
- // filters one JSONB field at a time. (Composite indexes aren't emitted.)
11
- if (fields.length !== 1)
8
+ const entries = Object.entries(idx.fields);
9
+ if (entries.length === 0)
12
10
  continue;
13
- const field = fields[0];
14
- if (!VALID_NAME.test(field))
11
+ // Reject the WHOLE index if any field name is unsafe — the names are
12
+ // interpolated straight into DDL, so there must be no injection surface.
13
+ if (!entries.every(([field]) => VALID_NAME.test(field)))
15
14
  continue;
16
15
  const unique = idx.unique ? 'UNIQUE ' : '';
17
- const name = idx.unique
18
- ? `idx_${collection}_${field}_unique`
19
- : `idx_${collection}_${field}`;
20
- out.push(`CREATE ${unique}INDEX IF NOT EXISTS "${name}" ON "${collection}" ((data->>'${field}'))`);
16
+ // `idx_<collection>_<f1>_<f2>_…` (+ `_unique`). Field order is significant —
17
+ // it matches the composite btree's leading-column order.
18
+ const base = `idx_${collection}_${entries.map(([field]) => field).join('_')}`;
19
+ const name = idx.unique ? `${base}_unique` : base;
20
+ // Each field is its own parenthesised expression; `-1` appends DESC so a
21
+ // filter+ORDER BY read is served entirely by the index.
22
+ const cols = entries
23
+ .map(([field, dir]) => `(data->>'${field}')${dir === -1 ? ' DESC' : ''}`)
24
+ .join(', ');
25
+ out.push(`CREATE ${unique}INDEX IF NOT EXISTS "${name}" ON "${collection}" (${cols})`);
21
26
  }
22
27
  return out;
23
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"schemaIndexes.js","sourceRoot":"","sources":["../../src/server/schemaIndexes.ts"],"names":[],"mappings":"AAkBA,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C,4EAA4E;AAC5E,MAAM,UAAU,oBAAoB,CAClC,UAAkB,EAClB,OAAoB;IAEpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvC,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM;YACrB,CAAC,CAAC,OAAO,UAAU,IAAI,KAAK,SAAS;YACrC,CAAC,CAAC,OAAO,UAAU,IAAI,KAAK,EAAE,CAAC;QACjC,GAAG,CAAC,IAAI,CACN,UAAU,MAAM,wBAAwB,IAAI,SAAS,UAAU,eAAe,KAAK,KAAK,CACzF,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"schemaIndexes.js","sourceRoot":"","sources":["../../src/server/schemaIndexes.ts"],"names":[],"mappings":"AA4BA,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAE9C,wFAAwF;AACxF,MAAM,UAAU,oBAAoB,CAClC,UAAkB,EAClB,OAAoB;IAEpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,qEAAqE;QACrE,yEAAyE;QACzE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAAE,SAAS;QAClE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,6EAA6E;QAC7E,yDAAyD;QACzD,MAAM,IAAI,GAAG,OAAO,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QAClD,yEAAyE;QACzE,wDAAwD;QACxD,MAAM,IAAI,GAAG,OAAO;aACjB,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,YAAY,KAAK,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;aACxE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,GAAG,CAAC,IAAI,CACN,UAAU,MAAM,wBAAwB,IAAI,SAAS,UAAU,MAAM,IAAI,GAAG,CAC7E,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ugly-app",
3
- "version": "0.1.758",
3
+ "version": "0.1.760",
4
4
  "type": "module",
5
5
  "comment:files": "Allowlist what ships to npm. dist = runtime; src = sourcemap targets (dist/*.js.map reference ../../src/); templates = CLI scaffold. Everything else at repo root (.pgdata local Postgres, coverage, assets/icons sources, test/, test-results/) is excluded by omission. The !negations strip the scaffold's installed deps + cruft (templates/node_modules is 200MB+ and must never ship). package.json/README/LICENSE ship automatically.",
6
6
  "files": [
@@ -1,2 +1,2 @@
1
1
  // Auto-generated by prebuild — do not edit manually
2
- export const CLI_VERSION = "0.1.758";
2
+ export const CLI_VERSION = "0.1.760";
@@ -38,6 +38,9 @@ export interface StorageClient {
38
38
  bucket: 'temp',
39
39
  key: string,
40
40
  ): Promise<{ uploadUrl: string; resultUrl: string }>;
41
+ /** Delete an object. Idempotent — S3/R2 treat deleting a missing key as
42
+ * success, so callers can sweep expired keys without pre-checking. */
43
+ delete(bucket: 'public' | 'temp', key: string): Promise<void>;
41
44
  }
42
45
 
43
46
  export interface StorageConfig {
@@ -221,6 +224,17 @@ async function moveToPublicRaw(
221
224
  return urlFor('public', destKey, cfg);
222
225
  }
223
226
 
227
+ async function deleteRaw(
228
+ bucket: 'public' | 'temp',
229
+ key: string,
230
+ ): Promise<void> {
231
+ const { client, cfg } = getClient();
232
+ const targetBucket = bucket === 'temp' ? cfg.tempBucket : cfg.bucket;
233
+ await client.send(
234
+ new DeleteObjectCommand({ Bucket: targetBucket, Key: key }),
235
+ );
236
+ }
237
+
224
238
  async function presignedPutRaw(
225
239
  bucket: 'temp',
226
240
  key: string,
@@ -261,5 +275,9 @@ export function createStorageClient(): StorageClient {
261
275
  async presignedPut(bucket, key) {
262
276
  return presignedPutRaw(bucket, prefixKey(key));
263
277
  },
278
+
279
+ async delete(bucket, key) {
280
+ return deleteRaw(bucket, prefixKey(key));
281
+ },
264
282
  };
265
283
  }
@@ -111,6 +111,7 @@ function getNodeStorage(): StorageAdapter {
111
111
  presignedPut: client.presignedPut.bind(client),
112
112
  moveToPublic: client.moveToPublic.bind(client),
113
113
  url: client.url.bind(client),
114
+ delete: client.delete.bind(client),
114
115
  };
115
116
  return _storageInstance;
116
117
  }
@@ -144,6 +144,14 @@ export interface StorageAdapter {
144
144
  moveToPublic(tempKey: string, destKey: string): Promise<string>;
145
145
 
146
146
  url(bucket: StorageBucket, key: string): string;
147
+
148
+ /**
149
+ * Delete an object. Idempotent (deleting a missing key is a no-op success),
150
+ * so callers can sweep expired keys without pre-checking. Optional for
151
+ * back-compat — feature-detect via the presence of the method; both the
152
+ * Node (S3) and Workers (R2 binding) adapters implement it.
153
+ */
154
+ delete?(bucket: StorageBucket, key: string): Promise<void>;
147
155
  }
148
156
 
149
157
  // ──────────────────────────────────────────────────────────────────────
@@ -76,5 +76,10 @@ export function createWorkersStorage(
76
76
  url(which: StorageBucket, key: string): string {
77
77
  return `${publicUrlBase}/${prefixed(which, key)}`;
78
78
  },
79
+
80
+ async delete(which: StorageBucket, key: string): Promise<void> {
81
+ // R2 delete is idempotent — a missing key resolves without error.
82
+ await r2.delete(prefixed(which, key));
83
+ },
79
84
  };
80
85
  }
@@ -28,17 +28,46 @@ describe('fieldIndexStatements', () => {
28
28
  expect(sql[1]).toContain(`((data->>'provider'))`);
29
29
  });
30
30
 
31
- it('skips composite (multi-field) indexes single-field only', () => {
32
- expect(fieldIndexStatements('x', [{ fields: { a: 1, b: 1 } }])).toEqual([]);
31
+ it('emits ONE composite btree over all fields (order preserved)', () => {
32
+ const sql = fieldIndexStatements('codingSession', [
33
+ { fields: { userId: 1, projectId: 1, kind: 1 } },
34
+ ]);
35
+ expect(sql).toEqual([
36
+ `CREATE INDEX IF NOT EXISTS "idx_codingSession_userId_projectId_kind" ` +
37
+ `ON "codingSession" ((data->>'userId'), (data->>'projectId'), (data->>'kind'))`,
38
+ ]);
39
+ });
40
+
41
+ it('appends DESC for a -1 field so filter+ORDER BY is index-served', () => {
42
+ const sql = fieldIndexStatements('codingSession', [
43
+ { fields: { userId: 1, updated: -1 } },
44
+ ]);
45
+ expect(sql).toEqual([
46
+ `CREATE INDEX IF NOT EXISTS "idx_codingSession_userId_updated" ` +
47
+ `ON "codingSession" ((data->>'userId'), (data->>'updated') DESC)`,
48
+ ]);
49
+ });
50
+
51
+ it('emits a UNIQUE composite index (with _unique suffix)', () => {
52
+ const sql = fieldIndexStatements('member', [
53
+ { fields: { orgId: 1, userId: 1 }, unique: true },
54
+ ]);
55
+ expect(sql).toEqual([
56
+ `CREATE UNIQUE INDEX IF NOT EXISTS "idx_member_orgId_userId_unique" ` +
57
+ `ON "member" ((data->>'orgId'), (data->>'userId'))`,
58
+ ]);
33
59
  });
34
60
 
35
61
  it('returns [] for no/empty indexes', () => {
36
62
  expect(fieldIndexStatements('x')).toEqual([]);
37
63
  expect(fieldIndexStatements('x', [])).toEqual([]);
64
+ expect(fieldIndexStatements('x', [{ fields: {} }])).toEqual([]);
38
65
  });
39
66
 
40
67
  it('refuses unsafe collection/field names (no SQL injection surface)', () => {
41
68
  expect(fieldIndexStatements('bad-name', [{ fields: { userId: 1 } }])).toEqual([]);
42
69
  expect(fieldIndexStatements('ok', [{ fields: { 'a; DROP TABLE x': 1 } }])).toEqual([]);
70
+ // one bad field poisons the whole composite index (no partial emit)
71
+ expect(fieldIndexStatements('ok', [{ fields: { userId: 1, 'a; DROP': 1 } }])).toEqual([]);
43
72
  });
44
73
  });
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Single source of truth for the btree expression indexes a collection declares
3
- * via `indexes: [{ fields: { <field>: 1 } }]`.
3
+ * via `indexes: [{ fields: { <field>: 1 | -1, ... } }]`.
4
4
  *
5
5
  * The default `idx_<c>_data` GIN index covers JSONB containment (`data @> …`),
6
6
  * but it CANNOT serve the scalar lookups the query layer actually emits
@@ -9,6 +9,16 @@
9
9
  * sequential-scans — invisible on a small table, a hang once it grows past the
10
10
  * 30s statement_timeout.
11
11
  *
12
+ * Single-field AND composite (multi-field) indexes are emitted. A composite
13
+ * `{ fields: { a: 1, b: -1 } }` produces ONE btree over
14
+ * `((data->>'a'), (data->>'b') DESC)` — which serves a multi-field equality
15
+ * filter AND a matching `ORDER BY` in a single index seek. (A bitmap-AND of
16
+ * single-field indexes can satisfy the filter, but never the ordering.) Field
17
+ * order and per-field direction (1 = ASC, -1 = DESC) are preserved from the
18
+ * declaration; the `PostgresIndexes` coverage checker already credits every
19
+ * field of a composite expression index, so declaring one silences the
20
+ * per-field unindexed warning for all of its fields.
21
+ *
12
22
  * Pure string-builder (no pg/pool imports) so it's safe to share across the Node
13
23
  * schema sync (`PostgresSchema.ensureTable`), the Workers `/_init` route, and the
14
24
  * migration generator (`schemaGen`). Statements are idempotent (IF NOT EXISTS) so
@@ -18,7 +28,7 @@ import type { IndexDef } from '../shared/DB.js';
18
28
 
19
29
  const VALID_NAME = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
20
30
 
21
- /** Raw `CREATE [UNIQUE] INDEX` SQL for each declared single-field index. */
31
+ /** Raw `CREATE [UNIQUE] INDEX` SQL for each declared (single- or multi-field) index. */
22
32
  export function fieldIndexStatements(
23
33
  collection: string,
24
34
  indexes?: IndexDef[],
@@ -26,18 +36,23 @@ export function fieldIndexStatements(
26
36
  if (!VALID_NAME.test(collection)) return [];
27
37
  const out: string[] = [];
28
38
  for (const idx of indexes ?? []) {
29
- const fields = Object.keys(idx.fields);
30
- // Single-field expression indexes only — matches the query layer, which
31
- // filters one JSONB field at a time. (Composite indexes aren't emitted.)
32
- if (fields.length !== 1) continue;
33
- const field = fields[0];
34
- if (!VALID_NAME.test(field)) continue;
39
+ const entries = Object.entries(idx.fields);
40
+ if (entries.length === 0) continue;
41
+ // Reject the WHOLE index if any field name is unsafe the names are
42
+ // interpolated straight into DDL, so there must be no injection surface.
43
+ if (!entries.every(([field]) => VALID_NAME.test(field))) continue;
35
44
  const unique = idx.unique ? 'UNIQUE ' : '';
36
- const name = idx.unique
37
- ? `idx_${collection}_${field}_unique`
38
- : `idx_${collection}_${field}`;
45
+ // `idx_<collection>_<f1>_<f2>_…` (+ `_unique`). Field order is significant —
46
+ // it matches the composite btree's leading-column order.
47
+ const base = `idx_${collection}_${entries.map(([field]) => field).join('_')}`;
48
+ const name = idx.unique ? `${base}_unique` : base;
49
+ // Each field is its own parenthesised expression; `-1` appends DESC so a
50
+ // filter+ORDER BY read is served entirely by the index.
51
+ const cols = entries
52
+ .map(([field, dir]) => `(data->>'${field}')${dir === -1 ? ' DESC' : ''}`)
53
+ .join(', ');
39
54
  out.push(
40
- `CREATE ${unique}INDEX IF NOT EXISTS "${name}" ON "${collection}" ((data->>'${field}'))`,
55
+ `CREATE ${unique}INDEX IF NOT EXISTS "${name}" ON "${collection}" (${cols})`,
41
56
  );
42
57
  }
43
58
  return out;