wiki-plugin-shoppe 0.0.27 → 0.0.29

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server/server.js +24 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-shoppe",
3
- "version": "0.0.27",
3
+ "version": "0.0.29",
4
4
  "description": "Multi-tenant digital goods shoppe for federated wiki, powered by Sanora",
5
5
  "keywords": [
6
6
  "wiki",
package/server/server.js CHANGED
@@ -2,6 +2,7 @@
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const crypto = require('crypto');
5
+ const { execSync } = require('child_process');
5
6
  const fetch = require('node-fetch');
6
7
  const multer = require('multer');
7
8
  const FormData = require('form-data');
@@ -672,9 +673,15 @@ async function lucilleUploadVideo(tenant, title, fileBuffer, filename, lucilleUr
672
673
  // ============================================================
673
674
 
674
675
  async function processArchive(zipPath) {
675
- const zip = new AdmZip(zipPath);
676
676
  const tmpDir = path.join(TMP_DIR, `extract-${Date.now()}`);
677
- zip.extractAllTo(tmpDir, true);
677
+ fs.mkdirSync(tmpDir, { recursive: true });
678
+ // Use system unzip to stream-extract without loading entire archive into RAM.
679
+ // AdmZip loads the whole zip into memory upfront, which OOM-kills Node on large archives.
680
+ try {
681
+ execSync(`unzip -o "${zipPath}" -d "${tmpDir}"`, { stdio: 'pipe' });
682
+ } catch (err) {
683
+ throw new Error(`Failed to extract archive: ${err.stderr ? err.stderr.toString().trim() : err.message}`);
684
+ }
678
685
 
679
686
  try {
680
687
  // Find manifest.json — handle zips wrapped in a top-level folder and
@@ -1222,8 +1229,14 @@ async function processArchive(zipPath) {
1222
1229
  // ============================================================
1223
1230
 
1224
1231
  async function getShoppeGoods(tenant) {
1225
- const resp = await fetch(`${getSanoraUrl()}/products/${tenant.uuid}`);
1226
- const products = await resp.json();
1232
+ let products = {};
1233
+ try {
1234
+ const resp = await fetch(`${getSanoraUrl()}/products/${tenant.uuid}`, { timeout: 15000 });
1235
+ if (resp.ok) products = await resp.json();
1236
+ else console.warn(`[shoppe] getShoppeGoods: Sanora returned ${resp.status} for ${tenant.uuid}`);
1237
+ } catch (err) {
1238
+ console.warn(`[shoppe] getShoppeGoods: Sanora unreachable — ${err.message}`);
1239
+ }
1227
1240
  const redirects = tenant.redirects || {};
1228
1241
 
1229
1242
  const goods = { books: [], music: [], posts: [], albums: [], products: [], videos: [], appointments: [], subscriptions: [] };
@@ -1422,8 +1435,13 @@ function checkOwnerSignature(req, tenant, maxAgeMs = 5 * 60 * 1000) {
1422
1435
  // Returns an array of { product, orders } objects.
1423
1436
  async function getAllOrders(tenant) {
1424
1437
  const sanoraUrl = getSanoraUrl();
1425
- const productsResp = await fetch(`${sanoraUrl}/products/${tenant.uuid}`);
1426
- const products = await productsResp.json();
1438
+ let products = {};
1439
+ try {
1440
+ const productsResp = await fetch(`${sanoraUrl}/products/${tenant.uuid}`, { timeout: 15000 });
1441
+ if (productsResp.ok) products = await productsResp.json();
1442
+ } catch (err) {
1443
+ console.warn(`[shoppe] getAllOrders: Sanora unreachable — ${err.message}`);
1444
+ }
1427
1445
 
1428
1446
  sessionless.getKeys = () => tenant.keys;
1429
1447