@patch-adams/core 1.0.8 → 1.0.11

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/cli.cjs CHANGED
@@ -7,7 +7,8 @@ var path = require('path');
7
7
  var chalk = require('chalk');
8
8
  var ora = require('ora');
9
9
  var AdmZip = require('adm-zip');
10
- var yazl = require('yazl');
10
+ var archiver = require('archiver');
11
+ var stream = require('stream');
11
12
  var fastXmlParser = require('fast-xml-parser');
12
13
  var zod = require('zod');
13
14
  var url = require('url');
@@ -17,7 +18,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
18
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
18
19
  var ora__default = /*#__PURE__*/_interopDefault(ora);
19
20
  var AdmZip__default = /*#__PURE__*/_interopDefault(AdmZip);
20
- var yazl__default = /*#__PURE__*/_interopDefault(yazl);
21
+ var archiver__default = /*#__PURE__*/_interopDefault(archiver);
21
22
 
22
23
  var __defProp = Object.defineProperty;
23
24
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -595,7 +596,9 @@ var ManifestUpdater = class {
595
596
  const parsed = this.parser.parse(xmlContent);
596
597
  this.addFilesToManifest(parsed, paths);
597
598
  const xmlDeclaration = this.extractXmlDeclaration(xmlContent);
598
- const updatedXml = xmlDeclaration + this.builder.build(parsed);
599
+ let builtXml = this.builder.build(parsed);
600
+ builtXml = builtXml.replace(/<\?xml[^?]*\?>\s*/g, "");
601
+ const updatedXml = xmlDeclaration + builtXml;
599
602
  zip.updateFile("imsmanifest.xml", Buffer.from(updatedXml, "utf-8"));
600
603
  return ["imsmanifest.xml"];
601
604
  } catch (error) {
@@ -762,7 +765,7 @@ var Patcher = class {
762
765
  const modifiedManifests = this.manifestUpdater.update(zip, result.format, manifestPaths);
763
766
  result.filesModified.push(...modifiedManifests);
764
767
  }
765
- const outputBuffer = await this.writeZipWithYazl(zip);
768
+ const outputBuffer = zip.toBuffer();
766
769
  result.success = true;
767
770
  return { buffer: outputBuffer, result };
768
771
  } catch (error) {
@@ -772,32 +775,39 @@ var Patcher = class {
772
775
  }
773
776
  }
774
777
  /**
775
- * Write ZIP using yazl for better compatibility
776
- * adm-zip's toBuffer() sets the data descriptor bit flag which causes
777
- * issues with some ZIP parsers. yazl produces standard ZIP output.
778
+ * Write ZIP using archiver for better compatibility
779
+ * adm-zip's toBuffer() produces ZIPs that some parsers don't handle well.
780
+ * archiver produces more standard ZIP output.
778
781
  */
779
- writeZipWithYazl(admZip) {
782
+ writeZipWithArchiver(admZip) {
780
783
  return new Promise((resolve3, reject) => {
781
- const zipFile = new yazl__default.default.ZipFile();
784
+ const archive = archiver__default.default("zip", {
785
+ zlib: { level: 9 }
786
+ // Maximum compression
787
+ });
788
+ const chunks = [];
789
+ const passThrough = new stream.PassThrough();
790
+ passThrough.on("data", (chunk) => chunks.push(chunk));
791
+ passThrough.on("end", () => resolve3(Buffer.concat(chunks)));
792
+ passThrough.on("error", reject);
793
+ archive.on("error", reject);
794
+ archive.pipe(passThrough);
782
795
  const entries = admZip.getEntries();
783
796
  for (const entry of entries) {
784
797
  const entryName = entry.entryName;
785
798
  const mtime = entry.header.time ? new Date(entry.header.time) : /* @__PURE__ */ new Date();
786
799
  if (entry.isDirectory) {
787
- zipFile.addEmptyDirectory(entryName, { mtime });
788
800
  continue;
789
801
  }
790
802
  const entryData = entry.getData();
791
- zipFile.addBuffer(entryData, entryName, {
792
- compress: true,
793
- mtime
803
+ const store = entry.header.method === 0;
804
+ archive.append(entryData, {
805
+ name: entryName,
806
+ date: mtime,
807
+ store
794
808
  });
795
809
  }
796
- const chunks = [];
797
- zipFile.outputStream.on("data", (chunk) => chunks.push(chunk));
798
- zipFile.outputStream.on("end", () => resolve3(Buffer.concat(chunks)));
799
- zipFile.outputStream.on("error", reject);
800
- zipFile.end();
810
+ archive.finalize();
801
811
  });
802
812
  }
803
813
  /**
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/detectors/format-detector.ts","../src/detectors/index.ts","../src/templates/css-before.ts","../src/templates/css-after.ts","../src/templates/js-before.ts","../src/templates/js-after.ts","../src/patcher/html-injector.ts","../src/patcher/manifest-updater.ts","../src/patcher/index.ts","../src/config/schema.ts","../src/config/defaults.ts","../src/config/loader.ts","../src/cli.ts"],"names":["XMLParser","XMLBuilder","AdmZip","resolve","yazl","z","existsSync","extname","readFileSync","pathToFileURL","Command","ora","writeFileSync","chalk","basename","FormatDetector"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAiBa,cAAA;AAjBb,IAAA,oBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,kCAAA,GAAA;AAiBO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,MAI1B,OAAO,GAAA,EAA4B;AAEjC,QAAA,IAAI,GAAA,CAAI,QAAA,CAAS,UAAU,CAAA,EAAG;AAC5B,UAAA,OAAO,MAAA;AAAA,QACT;AAGA,QAAA,IAAI,GAAA,CAAI,QAAA,CAAS,YAAY,CAAA,EAAG;AAC9B,UAAA,OAAO,MAAA;AAAA,QACT;AAGA,QAAA,MAAM,QAAA,GAAW,GAAA,CAAI,QAAA,CAAS,iBAAiB,CAAA;AAC/C,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,EAAQ,CAAE,SAAS,OAAO,CAAA;AACnD,UAAA,OAAO,IAAA,CAAK,mBAAmB,OAAO,CAAA;AAAA,QACxC;AAGA,QAAA,IAAI,IAAA,CAAK,YAAA,CAAa,GAAG,CAAA,EAAG;AAC1B,UAAA,OAAO,MAAA;AAAA,QACT;AAEA,QAAA,OAAO,SAAA;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,mBAAmB,OAAA,EAAgC;AAEzD,QAAA,IAAI,QAAQ,QAAA,CAAS,aAAa,KAAK,OAAA,CAAQ,QAAA,CAAS,SAAS,CAAA,EAAG;AAClE,UAAA,OAAO,aAAA;AAAA,QACT;AAGA,QAAA,IACE,OAAA,CAAQ,QAAA,CAAS,aAAa,CAAA,IAC9B,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,IAC3B,OAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,EAC7B;AACA,UAAA,OAAO,aAAA;AAAA,QACT;AAGA,QAAA,IAAI,QAAQ,QAAA,CAAS,MAAM,KAAK,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC1D,UAAA,OAAO,aAAA;AAAA,QACT;AAGA,QAAA,IACE,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA,IACtB,OAAA,CAAQ,QAAA,CAAS,gBAAgB,CAAA,IACjC,OAAA,CAAQ,QAAA,CAAS,kBAAkB,CAAA,EACnC;AACA,UAAA,OAAO,SAAA;AAAA,QACT;AAGA,QAAA,IAAI,OAAA,CAAQ,WAAA,EAAY,CAAE,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1C,UAAA,OAAO,MAAA;AAAA,QACT;AAGA,QAAA,OAAO,SAAA;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,aAAa,GAAA,EAAsB;AACzC,QAAA,MAAM,cAAA,GAAiB,CAAC,MAAA,EAAQ,KAAA,EAAO,QAAQ,MAAM,CAAA;AACrD,QAAA,MAAM,OAAA,GAAU,IAAI,UAAA,EAAW;AAE/B,QAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,UAAA,MAAM,IAAA,GAAO,KAAA,CAAM,SAAA,CAAU,WAAA,EAAY;AACzC,UAAA,IAAI,cAAA,CAAe,KAAK,CAAC,GAAA,KAAQ,KAAK,QAAA,CAAS,GAAG,CAAC,CAAA,EAAG;AACpD,YAAA,OAAO,IAAA;AAAA,UACT;AAAA,QACF;AAEA,QAAA,OAAO,KAAA;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,qBAAqB,MAAA,EAA+B;AAClD,QAAA,MAAM,KAAA,GAAuC;AAAA,UAC3C,OAAA,EAAS,WAAA;AAAA,UACT,aAAA,EAAe,wBAAA;AAAA,UACf,aAAA,EAAe,wBAAA;AAAA,UACf,IAAA,EAAM,MAAA;AAAA,UACN,IAAA,EAAM,gBAAA;AAAA,UACN,IAAA,EAAM,MAAA;AAAA,UACN,OAAA,EAAS;AAAA,SACX;AAEA,QAAA,OAAO,MAAM,MAAM,CAAA;AAAA,MACrB;AAAA,KACF;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACzHA,IAAA,iBAAA,GAAA,EAAA;AAAA,QAAA,CAAA,iBAAA,EAAA;AAAA,EAAA,cAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAAA,IAAA,cAAA,GAAA,KAAA,CAAA;AAAA,EAAA,wBAAA,GAAA;AAAA,IAAA,oBAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACiBO,SAAS,wBAAwB,OAAA,EAAmC;AACzE,EAAA,MAAM,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAW,cAAa,GAAI,OAAA;AAE1D,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA,KAAA,EAGF,SAAS,IAAI,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAA,EAOV,SAAS,CAAA;AAAA,oBAAA,EACT,SAAS,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAyB/B;AAKO,SAAS,sBAAsB,MAAA,EAA4C;AAChF,EAAA,OAAO;AAAA,IACL,WAAW,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAAA,IAC9D,SAAA,EAAW,GAAG,MAAA,CAAO,YAAA,CAAa,GAAG,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAAA,IAClE,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,cAAc,MAAA,CAAO;AAAA,GACvB;AACF;;;ACxDO,SAAS,uBAAuB,OAAA,EAAkC;AACvE,EAAA,MAAM,EAAE,SAAA,EAAW,SAAA,EAAW,OAAA,EAAQ,GAAI,OAAA;AAE1C,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,oBAAA,EAIa,SAAS,CAAA;AAAA,oBAAA,EACT,SAAS,CAAA;AAAA,gBAAA,EACb,OAAO,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAqEzB;AAKO,SAAS,qBAAqB,MAAA,EAA2C;AAC9E,EAAA,OAAO;AAAA,IACL,WAAW,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,CAAA,EAAI,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AAAA,IAC7D,SAAA,EAAW,GAAG,MAAA,CAAO,YAAA,CAAa,GAAG,CAAA,CAAA,EAAI,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AAAA,IACjE,OAAA,EAAS,OAAO,QAAA,CAAS;AAAA,GAC3B;AACF;;;ACnFO,SAAS,uBAAuB,OAAA,EAAkC;AACvE,EAAA,MAAM,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAW,cAAa,GAAI,OAAA;AAE1D,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,oBAAA,EAIa,SAAS,CAAA;AAAA,oBAAA,EACT,SAAS,CAAA;;AAAA;AAAA;AAAA;AAAA,gBAAA,EAKb,SAAS,CAAA;AAAA,mBAAA,EACN,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAyCjC;AAKO,SAAS,qBAAqB,MAAA,EAA2C;AAC9E,EAAA,OAAO;AAAA,IACL,WAAW,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,CAAA,EAAI,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AAAA,IAC7D,SAAA,EAAW,GAAG,MAAA,CAAO,YAAA,CAAa,EAAE,CAAA,CAAA,EAAI,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AAAA,IAChE,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,cAAc,MAAA,CAAO;AAAA,GACvB;AACF;;;ACpEO,SAAS,sBAAsB,OAAA,EAAiC;AACrE,EAAA,MAAM,EAAE,SAAA,EAAW,SAAA,EAAW,OAAA,EAAS,cAAa,GAAI,OAAA;AAExD,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA,oBAAA,EAIa,SAAS,CAAA;AAAA,oBAAA,EACT,SAAS,CAAA;AAAA,gBAAA,EACb,OAAO,CAAA;AAAA,uBAAA,EACA,YAAY,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AA0FrC;AAKO,SAAS,oBAAoB,MAAA,EAA0C;AAC5E,EAAA,OAAO;AAAA,IACL,WAAW,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,CAAA,EAAI,MAAA,CAAO,QAAQ,QAAQ,CAAA,CAAA;AAAA,IAC5D,SAAA,EAAW,GAAG,MAAA,CAAO,YAAA,CAAa,EAAE,CAAA,CAAA,EAAI,MAAA,CAAO,QAAQ,QAAQ,CAAA,CAAA;AAAA,IAC/D,OAAA,EAAS,OAAO,OAAA,CAAQ,OAAA;AAAA,IACxB,cAAc,MAAA,CAAO;AAAA,GACvB;AACF;;;AC1GO,IAAM,eAAN,MAAmB;AAAA,EAChB,MAAA;AAAA,EAER,YAAY,MAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAA,EAAsB;AAC3B,IAAA,IAAI,MAAA,GAAS,IAAA;AAGb,IAAA,MAAA,GAAS,IAAA,CAAK,eAAe,MAAM,CAAA;AAGnC,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS;AACjC,MAAA,MAAA,GAAS,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAAA,IACtC;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAA,EAAS;AAChC,MAAA,MAAA,GAAS,IAAA,CAAK,eAAe,MAAM,CAAA;AAAA,IACrC;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAA,EAAS;AAChC,MAAA,MAAA,GAAS,IAAA,CAAK,eAAe,MAAM,CAAA;AAAA,IACrC;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAS;AAC/B,MAAA,MAAA,GAAS,IAAA,CAAK,cAAc,MAAM,CAAA;AAAA,IACpC;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,IAAA,EAAsB;AAC3C,IAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAa,GAAI,IAAA,CAAK,MAAA;AACzC,IAAA,MAAM,OAAA,GAAU,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAG5C,IAAA,MAAM,cAAA,GAAiB,gBAAA;AACvB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,cAAc,CAAA;AAEvC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,UAAA,GAAa,MAAM,CAAC,CAAA;AAG1B,IAAA,IAAI,6BAAA,CAA8B,IAAA,CAAK,UAAU,CAAA,EAAG;AAElD,MAAA,OAAO,IAAA,CAAK,OAAA;AAAA,QACV,cAAA;AAAA,QACA,CAAC,QAAgB,KAAA,KAAkB;AACjC,UAAA,MAAM,WAAW,KAAA,CAAM,OAAA;AAAA,YACrB,+BAAA;AAAA,YACA,CAAC,UAAA,EAAoB,eAAA,KAA4B,CAAA,OAAA,EAAU,eAAe,IAAI,OAAO,CAAA,CAAA;AAAA,WACvF;AACA,UAAA,OAAO,QAAQ,QAAQ,CAAA,CAAA,CAAA;AAAA,QACzB;AAAA,OACF;AAAA,IACF,CAAA,MAAO;AAEL,MAAA,OAAO,KAAK,OAAA,CAAQ,cAAA,EAAgB,QAAQ,UAAU,CAAA,QAAA,EAAW,OAAO,CAAA,EAAA,CAAI,CAAA;AAAA,IAC9E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,IAAA,EAAsB;AAC5C,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAsB,IAAA,CAAK,MAAM,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,wBAAwB,OAAO,CAAA;AAG9C,IAAA,OAAO,IAAA,CAAK,QAAQ,gBAAA,EAAkB,CAAA;AAAA,EAAa,MAAM,CAAA,CAAE,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,IAAA,EAAsB;AAC3C,IAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,IAAA,CAAK,MAAM,CAAA;AAChD,IAAA,MAAM,MAAA,GAAS,uBAAuB,OAAO,CAAA;AAG7C,IAAA,MAAM,eAAA,GAAkB,kCAAA;AACxB,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,eAAe,CAAA,EAAG;AAElC,MAAA,MAAM,mBAAA,GAAsB,uBAAA;AAC5B,MAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,OAAA,CAAQ,eAAe,CAAA;AACnD,MAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,SAAA,CAAU,cAAc,CAAA;AACpD,MAAA,MAAM,QAAA,GAAW,cAAA,CAAe,KAAA,CAAM,mBAAmB,CAAA;AAEzD,MAAA,IAAI,QAAA,IAAY,QAAA,CAAS,KAAA,KAAU,MAAA,EAAW;AAC5C,QAAA,MAAM,YAAY,cAAA,GAAiB,QAAA,CAAS,KAAA,GAAQ,QAAA,CAAS,CAAC,CAAA,CAAE,MAAA;AAChE,QAAA,OAAO,IAAA,CAAK,MAAM,CAAA,EAAG,SAAS,IAAI,IAAA,GAAO,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AAAA,MACxE;AAAA,IACF;AAGA,IAAA,OAAO,IAAA,CAAK,QAAQ,gBAAA,EAAkB,CAAA;AAAA,EAAa,MAAM,CAAA,CAAE,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,IAAA,EAAsB;AAC3C,IAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,IAAA,CAAK,MAAM,CAAA;AAChD,IAAA,MAAM,MAAA,GAAS,uBAAuB,OAAO,CAAA;AAG7C,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,WAAA,EAAa,CAAA,EAAG,MAAM;AAAA,OAAA,CAAW,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,IAAA,EAAsB;AAC1C,IAAA,MAAM,OAAA,GAAU,mBAAA,CAAoB,IAAA,CAAK,MAAM,CAAA;AAC/C,IAAA,MAAM,MAAA,GAAS,sBAAsB,OAAO,CAAA;AAG5C,IAAA,MAAM,gBAAA,GAAmB,sCAAA;AACzB,IAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAA,EAAG;AAC/B,MAAA,OAAO,IAAA,CAAK,QAAQ,gBAAA,EAAkB,CAAA;AAAA,EAAO,MAAM,CAAA,CAAE,CAAA;AAAA,IACvD;AAGA,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,WAAA,EAAa,CAAA,EAAG,MAAM;AAAA,OAAA,CAAW,CAAA;AAAA,EACvD;AACF,CAAA;AClJO,IAAM,kBAAN,MAAsB;AAAA,EACnB,MAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EAER,YAAY,MAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,MAAA,GAAS,IAAIA,uBAAA,CAAU;AAAA,MAC1B,gBAAA,EAAkB,KAAA;AAAA,MAClB,mBAAA,EAAqB,IAAA;AAAA,MACrB,aAAA,EAAe,KAAA;AAAA,MACf,mBAAA,EAAqB,KAAA;AAAA,MACrB,UAAA,EAAY;AAAA,KACb,CAAA;AACD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAIC,wBAAA,CAAW;AAAA,MAC5B,gBAAA,EAAkB,KAAA;AAAA,MAClB,mBAAA,EAAqB,IAAA;AAAA,MACrB,MAAA,EAAQ,IAAA;AAAA,MACR,QAAA,EAAU,IAAA;AAAA,MACV,iBAAA,EAAmB;AAAA,KACpB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,CAAO,GAAA,EAAa,MAAA,EAAuB,KAAA,EAAgC;AACzE,IAAA,MAAM,WAAqB,EAAC;AAE5B,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,SAAA;AAAA,MACL,KAAK,aAAA;AAAA,MACL,KAAK,aAAA;AACH,QAAA,QAAA,CAAS,KAAK,GAAG,IAAA,CAAK,iBAAA,CAAkB,GAAA,EAAK,KAAK,CAAC,CAAA;AACnD,QAAA;AAAA,MAEF,KAAK,MAAA;AAEH,QAAA,QAAA,CAAS,KAAK,GAAG,IAAA,CAAK,iBAAA,CAAkB,GAAA,EAAK,KAAK,CAAC,CAAA;AACnD,QAAA;AAAA,MAEF,KAAK,MAAA;AAGH,QAAA;AAAA,MAEF,KAAK,MAAA;AAEH,QAAA,MAAM,YAAA,GAAe,GAAA,CAAI,QAAA,CAAS,iBAAiB,CAAA;AACnD,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,QAAA,CAAS,KAAK,GAAG,IAAA,CAAK,iBAAA,CAAkB,GAAA,EAAK,KAAK,CAAC,CAAA;AAAA,QACrD;AACA,QAAA;AAAA;AAGJ,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAA,CAAkB,KAAa,KAAA,EAAgC;AACrE,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,QAAA,CAAS,iBAAiB,CAAA;AAC5C,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,EAAC;AAAA,IACV;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,EAAQ,CAAE,SAAS,OAAO,CAAA;AACnD,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA;AAG3C,MAAA,IAAA,CAAK,kBAAA,CAAmB,QAAQ,KAAK,CAAA;AAGrC,MAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,qBAAA,CAAsB,UAAU,CAAA;AAC5D,MAAA,MAAM,UAAA,GAAa,cAAA,GAAiB,IAAA,CAAK,OAAA,CAAQ,MAAM,MAAM,CAAA;AAE7D,MAAA,GAAA,CAAI,WAAW,iBAAA,EAAmB,MAAA,CAAO,IAAA,CAAK,UAAA,EAAY,OAAO,CAAC,CAAA;AAElE,MAAA,OAAO,CAAC,iBAAiB,CAAA;AAAA,IAC3B,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,mDAAmD,KAAK,CAAA;AACtE,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,GAAA,EAAqB;AACjD,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,gBAAgB,CAAA;AACxC,IAAA,OAAO,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,GAAO,0CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,CAAmB,QAAiC,KAAA,EAA4B;AAEtF,IAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AACxB,IAAA,IAAI,CAAC,QAAA,EAAU;AAEf,IAAA,MAAM,YAAY,QAAA,CAAS,SAAA;AAC3B,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,IAAI,WAAW,SAAA,CAAU,QAAA;AACzB,IAAA,IAAI,CAAC,QAAA,EAAU;AAGf,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC3B,MAAA,QAAA,GAAW,SAAS,CAAC,CAAA;AAAA,IACvB;AAGA,IAAA,IAAI,CAAC,SAAS,IAAA,EAAM;AAClB,MAAA,QAAA,CAAS,OAAO,EAAC;AAAA,IACnB;AAEA,IAAA,IAAI,QAAQ,QAAA,CAAS,IAAA;AACrB,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,MAAA,KAAA,GAAQ,CAAC,KAA0C,CAAA;AACnD,MAAA,QAAA,CAAS,IAAA,GAAO,KAAA;AAAA,IAClB;AAGA,IAAA,MAAM,UAAA,GAAa;AAAA,MACjB,KAAA,CAAM,SAAA;AAAA,MACN,KAAA,CAAM,QAAA;AAAA,MACN,KAAA,CAAM,QAAA;AAAA,MACN,KAAA,CAAM;AAAA,KACR,CAAE,OAAO,OAAO,CAAA;AAEhB,IAAA,KAAA,MAAW,YAAY,UAAA,EAAY;AAEjC,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,QAAQ,MAAM,QAAQ,CAAA;AACzD,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,KAAA,CAAM,IAAA,CAAK,EAAE,QAAA,EAAU,QAAA,EAAU,CAAA;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAA8B;AAC5B,IAAA,MAAM,QAAuB,EAAC;AAE9B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS;AACjC,MAAA,KAAA,CAAM,SAAA,GAAY,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAG,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,QAAQ,CAAA,CAAA;AAAA,IAClG;AAEA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAA,EAAS;AAChC,MAAA,KAAA,CAAM,QAAA,GAAW,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,GAAG,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,CAAA;AAAA,IAChG;AAEA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAA,EAAS;AAChC,MAAA,KAAA,CAAM,QAAA,GAAW,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,EAAE,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,CAAA;AAAA,IAC/F;AAEA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAS;AAC/B,MAAA,KAAA,CAAM,OAAA,GAAU,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,EAAE,CAAA,CAAA,EAAI,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAAA;AAAA,IAC7F;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AACF,CAAA;;;ACjLA,oBAAA,EAAA;AAgCA,IAAM,kBAAA,GAAqB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAW3B,IAAM,iBAAA,GAAoB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAW1B,IAAM,iBAAA,GAAoB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAa1B,IAAM,gBAAA,GAAmB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAkBlB,IAAM,UAAN,MAAc;AAAA,EACX,MAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,cAAA;AAAA,EAER,YAAY,MAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,YAAA,CAAa,MAAM,CAAA;AAC3C,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,eAAA,CAAgB,MAAM,CAAA;AACjD,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAI,cAAA,EAAe;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAA,CACJ,WAAA,EACA,OAAA,GAAwB,EAAC,EACyB;AAClD,IAAA,MAAM,MAAA,GAAsB;AAAA,MAC1B,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ,SAAA;AAAA,MACR,iBAAA,EAAmB,SAAA;AAAA,MACnB,eAAe,EAAC;AAAA,MAChB,YAAY,EAAC;AAAA,MACb,QAAQ,EAAC;AAAA,MACT,UAAU;AAAC,KACb;AAEA,IAAA,IAAI;AAEF,MAAA,MAAM,GAAA,GAAM,IAAIC,uBAAA,CAAO,WAAW,CAAA;AAGlC,MAAA,MAAA,CAAO,MAAA,GAAS,IAAA,CAAK,cAAA,CAAe,MAAA,CAAO,GAAG,CAAA;AAC9C,MAAA,MAAA,CAAO,iBAAA,GAAoB,IAAA,CAAK,cAAA,CAAe,oBAAA,CAAqB,OAAO,MAAM,CAAA;AAEjF,MAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAC/B,QAAA,MAAA,CAAO,QAAA,CAAS,KAAK,uDAAuD,CAAA;AAAA,MAC9E;AAGA,MAAA,MAAM,cAAA,GAAiB,GAAA,CAAI,QAAA,CAAS,yBAAyB,CAAA;AAC7D,MAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,QAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,MACnG;AAEA,MAAA,MAAM,YAAA,GAAe,cAAA,CAAe,OAAA,EAAQ,CAAE,SAAS,OAAO,CAAA;AAC9D,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,YAAA,CAAa,MAAA,CAAO,YAAY,CAAA;AACzD,MAAA,GAAA,CAAI,WAAW,yBAAA,EAA2B,MAAA,CAAO,IAAA,CAAK,WAAA,EAAa,OAAO,CAAC,CAAA;AAC3E,MAAA,MAAA,CAAO,aAAA,CAAc,KAAK,yBAAyB,CAAA;AAGnD,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,gBAAA,CAAiB,GAAA,EAAK,OAAO,CAAA;AACrD,MAAA,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,GAAG,UAAU,CAAA;AAGpC,MAAA,IAAI,IAAA,CAAK,OAAO,eAAA,EAAiB;AAC/B,QAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,eAAA,CAAgB,YAAA,EAAa;AACxD,QAAA,MAAM,oBAAoB,IAAA,CAAK,eAAA,CAAgB,OAAO,GAAA,EAAK,MAAA,CAAO,QAAQ,aAAa,CAAA;AACvF,QAAA,MAAA,CAAO,aAAA,CAAc,IAAA,CAAK,GAAG,iBAAiB,CAAA;AAAA,MAChD;AAKA,MAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA;AAEpD,MAAA,MAAA,CAAO,OAAA,GAAU,IAAA;AACjB,MAAA,OAAO,EAAE,MAAA,EAAQ,YAAA,EAAc,MAAA,EAAO;AAAA,IACxC,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,MAAA,MAAA,CAAO,MAAA,CAAO,KAAK,OAAO,CAAA;AAC1B,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAiB,MAAA,EAAiC;AACxD,IAAA,OAAO,IAAI,OAAA,CAAQ,CAACC,QAAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,OAAA,GAAU,IAAIC,qBAAA,CAAK,OAAA,EAAQ;AACjC,MAAA,MAAM,OAAA,GAAU,OAAO,UAAA,EAAW;AAElC,MAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,QAAA,MAAM,YAAY,KAAA,CAAM,SAAA;AACxB,QAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,IAAA,GAAO,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA,mBAAI,IAAI,IAAA,EAAK;AAEzE,QAAA,IAAI,MAAM,WAAA,EAAa;AAErB,UAAA,OAAA,CAAQ,iBAAA,CAAkB,SAAA,EAAW,EAAE,KAAA,EAAO,CAAA;AAC9C,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,SAAA,GAAY,MAAM,OAAA,EAAQ;AAGhC,QAAA,OAAA,CAAQ,SAAA,CAAU,WAAW,SAAA,EAAW;AAAA,UACtC,QAAA,EAAU,IAAA;AAAA,UACV;AAAA,SACD,CAAA;AAAA,MACH;AAGA,MAAA,MAAM,SAAmB,EAAC;AAC1B,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAG,MAAA,EAAQ,CAAC,UAAkB,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACrE,MAAA,OAAA,CAAQ,YAAA,CAAa,GAAG,KAAA,EAAO,MAAMD,SAAQ,MAAA,CAAO,MAAA,CAAO,MAAM,CAAC,CAAC,CAAA;AACnE,MAAA,OAAA,CAAQ,YAAA,CAAa,EAAA,CAAG,OAAA,EAAS,MAAM,CAAA;AACvC,MAAA,OAAA,CAAQ,GAAA,EAAI;AAAA,IACd,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAA,CAAiB,KAAa,OAAA,EAAiC;AACrE,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,MAAM,SAAA,GAAY,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,aAAa,GAAG,CAAA,CAAA;AAC9D,IAAA,MAAM,QAAA,GAAW,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,aAAa,EAAE,CAAA,CAAA;AAG5D,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS;AACjC,MAAA,MAAM,OAAO,CAAA,EAAG,SAAS,IAAI,IAAA,CAAK,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAC3D,MAAA,MAAM,OAAA,GAAU,QAAQ,gBAAA,IAAoB,kBAAA;AAC5C,MAAA,GAAA,CAAI,QAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAA,EAAS;AAChC,MAAA,MAAM,OAAO,CAAA,EAAG,SAAS,IAAI,IAAA,CAAK,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AAC1D,MAAA,MAAM,OAAA,GAAU,QAAQ,eAAA,IAAmB,iBAAA;AAC3C,MAAA,GAAA,CAAI,QAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,OAAA,EAAS;AAChC,MAAA,MAAM,OAAO,CAAA,EAAG,QAAQ,IAAI,IAAA,CAAK,MAAA,CAAO,SAAS,QAAQ,CAAA,CAAA;AACzD,MAAA,MAAM,OAAA,GAAU,QAAQ,eAAA,IAAmB,iBAAA;AAC3C,MAAA,GAAA,CAAI,QAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAS;AAC/B,MAAA,MAAM,OAAO,CAAA,EAAG,QAAQ,IAAI,IAAA,CAAK,MAAA,CAAO,QAAQ,QAAQ,CAAA,CAAA;AACxD,MAAA,MAAM,OAAA,GAAU,QAAQ,cAAA,IAAkB,gBAAA;AAC1C,MAAA,GAAA,CAAI,QAAQ,IAAA,EAAM,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAC,CAAA;AAC/C,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAA8B;AAC5B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,MAAA,EAAiC;AACjD,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kCAAA,EAAqC,MAAA,CAAO,MAAM,CAAA,MAAA,CAAQ,CAAA;AACtE,IAAA,MAAM,EAAE,QAAQ,aAAA,EAAe,MAAA,KAAW,MAAM,IAAA,CAAK,MAAM,MAAM,CAAA;AACjE,IAAA,OAAA,CAAQ,IAAI,CAAA,uBAAA,CAAA,EAA2B,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC,CAAA;AACtE,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oBAAA,EAAuB,aAAA,CAAc,MAAM,CAAA,MAAA,CAAQ,CAAA;AAC/D,IAAA,OAAO,aAAA;AAAA,EACT;AACF,CAAA;AC1QO,IAAM,yBAAA,GAA4BE,MAAE,MAAA,CAAO;AAAA;AAAA,EAEhD,QAAA,EAAUA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAE1B,OAAA,EAASA,KAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI;AACnC,CAAC,CAAA;AAMM,IAAM,sBAAA,GAAyBA,MAAE,MAAA,CAAO;AAAA;AAAA,EAE7C,QAAA,EAAUA,KAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAE1B,OAAA,EAASA,KAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAEjC,OAAA,EAASA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAI,CAAA,CAAE,GAAA,CAAI,GAAK,CAAA,CAAE,OAAA,CAAQ,GAAI;AACvD,CAAC,CAAA;AAKM,IAAM,wBAAA,GAA2BA,MAAE,MAAA,CAAO;AAAA;AAAA,EAE/C,GAAA,EAAKA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,KAAK,CAAA;AAAA;AAAA,EAE7B,EAAA,EAAIA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,IAAI;AAC7B,CAAC,CAAA;AAKM,IAAM,sBAAA,GAAyBA,MAAE,MAAA,CAAO;AAAA;AAAA,EAE7C,YAAA,EAAcA,KAAA,CAAE,MAAA,EAAO,CAAE,GAAA,EAAI;AAAA;AAAA,EAG7B,SAAA,EAAWA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,YAAY,CAAA;AAAA;AAAA,EAG1C,YAAA,EAAcA,KAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,YAAY,CAAA;AAAA;AAAA,EAG7C,SAAA,EAAW,0BAA0B,OAAA,CAAQ;AAAA,IAC3C,QAAA,EAAU,YAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACV,CAAA;AAAA;AAAA,EAGD,QAAA,EAAU,uBAAuB,OAAA,CAAQ;AAAA,IACvC,QAAA,EAAU,WAAA;AAAA,IACV,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS;AAAA,GACV,CAAA;AAAA;AAAA,EAGD,QAAA,EAAU,0BAA0B,OAAA,CAAQ;AAAA,IAC1C,QAAA,EAAU,WAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACV,CAAA;AAAA;AAAA,EAGD,OAAA,EAAS,uBAAuB,OAAA,CAAQ;AAAA,IACtC,QAAA,EAAU,UAAA;AAAA,IACV,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS;AAAA,GACV,CAAA;AAAA;AAAA,EAGD,YAAA,EAAc,wBAAA,CAAyB,OAAA,CAAQ,EAAE,CAAA;AAAA;AAAA,EAGjD,eAAA,EAAiBA,KAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI;AAC3C,CAAC,CAAA;;;AC3EM,IAAM,aAAA,GAAkC;AAAA,EAC7C,YAAA,EAAc,wCAAA;AAAA,EAEd,SAAA,EAAW,YAAA;AAAA,EACX,YAAA,EAAc,YAAA;AAAA,EAEd,SAAA,EAAW;AAAA,IACT,QAAA,EAAU,YAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACX;AAAA,EAEA,QAAA,EAAU;AAAA,IACR,QAAA,EAAU,WAAA;AAAA,IACV,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS;AAAA,GACX;AAAA,EAEA,QAAA,EAAU;AAAA,IACR,QAAA,EAAU,WAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACX;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,UAAA;AAAA,IACV,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS;AAAA,GACX;AAAA,EAEA,YAAA,EAAc;AAAA,IACZ,GAAA,EAAK,KAAA;AAAA,IACL,EAAA,EAAI;AAAA,GACN;AAAA,EAEA,eAAA,EAAiB;AACnB,CAAA;AC7BA,eAAsB,WAAW,UAAA,EAA+C;AAC9E,EAAA,MAAM,YAAA,GAAeF,aAAQ,UAAU,CAAA;AAEvC,EAAA,IAAI,CAACG,aAAA,CAAW,YAAY,CAAA,EAAG;AAC7B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,YAAY,CAAA,CAAE,CAAA;AAAA,EACjE;AAEA,EAAA,MAAM,GAAA,GAAMC,YAAA,CAAQ,YAAY,CAAA,CAAE,WAAA,EAAY;AAC9C,EAAA,IAAI,SAAA;AAEJ,EAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,IAAA,MAAM,OAAA,GAAUC,eAAA,CAAa,YAAA,EAAc,OAAO,CAAA;AAClD,IAAA,SAAA,GAAY,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,EAChC,WAAW,GAAA,KAAQ,KAAA,IAAS,GAAA,KAAQ,KAAA,IAAS,QAAQ,MAAA,EAAQ;AAE3D,IAAA,MAAM,OAAA,GAAUC,iBAAA,CAAc,YAAY,CAAA,CAAE,IAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,MAAM,OAAO,OAAA,CAAA;AAC5B,IAAA,SAAA,GAAY,OAAO,OAAA,IAAW,MAAA;AAAA,EAChC,CAAA,MAAO;AACL,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mCAAA,EAAsC,GAAG,CAAA,8BAAA,CAAgC,CAAA;AAAA,EAC3F;AAGA,EAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,KAAA,CAAM,SAAS,CAAA;AACxD,EAAA,OAAO,SAAA;AACT;AAKO,SAAS,kBAAkB,OAAA,EAAsD;AACtF,EAAA,OAAO,uBAAuB,KAAA,CAAM;AAAA,IAClC,GAAG,aAAA;AAAA,IACH,GAAG;AAAA,GACJ,CAAA;AACH;AAKO,SAAS,sBAAA,GAAiC;AAC/C,EAAA,OAAO,CAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAqDT;;;AC9FA,IAAM,OAAA,GAAU,IAAIC,iBAAA,EAAQ;AAE5B,OAAA,CACG,KAAK,aAAa,CAAA,CAClB,YAAY,wEAAwE,CAAA,CACpF,QAAQ,OAAO,CAAA;AAElB,OAAA,CACG,QAAQ,eAAe,CAAA,CACvB,WAAA,CAAY,8BAA8B,EAC1C,MAAA,CAAO,qBAAA,EAAuB,iDAAiD,CAAA,CAC/E,OAAO,qBAAA,EAAuB,4DAA4D,CAAA,CAC1F,MAAA,CAAO,uBAAuB,sCAAsC,CAAA,CACpE,MAAA,CAAO,oBAAA,EAAsB,qCAAqC,CAAA,CAClE,MAAA,CAAO,oBAAA,EAAsB,qCAAqC,EAClE,MAAA,CAAO,mBAAA,EAAqB,oCAAoC,CAAA,CAChE,OAAO,eAAA,EAAiB,8BAA8B,EACtD,MAAA,CAAO,OAAO,OAAe,OAAA,KAAY;AACxC,EAAA,MAAM,OAAA,GAAUC,oBAAA,CAAI,0BAA0B,CAAA,CAAE,KAAA,EAAM;AAEtD,EAAA,IAAI;AAEF,IAAA,IAAI,MAAA;AACJ,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,IAAU,yBAAA;AAErC,IAAA,IAAIL,aAAAA,CAAWH,YAAAA,CAAQ,UAAU,CAAC,CAAA,EAAG;AACnC,MAAA,MAAA,GAAS,MAAM,WAAW,UAAU,CAAA;AACpC,MAAA,OAAA,CAAQ,IAAA,GAAO,sBAAA;AAAA,IACjB,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,GAAO,sCAAA;AACf,MAAA,MAAA,GAAS,iBAAA,CAAkB,EAAE,CAAA;AAAA,IAC/B;AAGA,IAAA,IAAI,OAAA,CAAQ,aAAa,KAAA,EAAO;AAC9B,MAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,eAAA,EAAiB,KAAA,EAAM;AAAA,IAC/C;AAGA,IAAA,MAAM,eAAA,GAAkB,sBAAA,CAAuB,KAAA,CAAM,MAAM,CAAA;AAE3D,IAAA,OAAA,CAAQ,IAAA,GAAO,uBAAA;AAGf,IAAA,MAAM,SAAA,GAAYA,aAAQ,KAAK,CAAA;AAC/B,IAAA,IAAI,CAACG,aAAAA,CAAW,SAAS,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAE,CAAA;AAAA,IACtD;AACA,IAAA,MAAM,WAAA,GAAcE,gBAAa,SAAS,CAAA;AAG1C,IAAA,MAAM,eAKF,EAAC;AAEL,IAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,MAAA,YAAA,CAAa,mBAAmBA,eAAAA,CAAaL,YAAAA,CAAQ,OAAA,CAAQ,SAAS,GAAG,OAAO,CAAA;AAAA,IAClF;AAEA,IAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,YAAA,CAAa,kBAAkBK,eAAAA,CAAaL,YAAAA,CAAQ,OAAA,CAAQ,QAAQ,GAAG,OAAO,CAAA;AAAA,IAChF;AAEA,IAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,YAAA,CAAa,kBAAkBK,eAAAA,CAAaL,YAAAA,CAAQ,OAAA,CAAQ,QAAQ,GAAG,OAAO,CAAA;AAAA,IAChF;AAEA,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,YAAA,CAAa,iBAAiBK,eAAAA,CAAaL,YAAAA,CAAQ,OAAA,CAAQ,OAAO,GAAG,OAAO,CAAA;AAAA,IAC9E;AAEA,IAAA,OAAA,CAAQ,IAAA,GAAO,qBAAA;AAGf,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,eAAe,CAAA;AAC3C,IAAA,MAAM,EAAE,QAAQ,MAAA,EAAO,GAAI,MAAM,OAAA,CAAQ,KAAA,CAAM,aAAa,YAAY,CAAA;AAGxE,IAAA,MAAM,aACJ,OAAA,CAAQ,MAAA,IAAU,SAAA,CAAU,OAAA,CAAQ,WAAW,cAAc,CAAA;AAE/D,IAAA,OAAA,CAAQ,IAAA,GAAO,wBAAA;AACf,IAAAS,gBAAA,CAAc,YAAY,MAAM,CAAA;AAEhC,IAAA,OAAA,CAAQ,OAAA,CAAQC,sBAAA,CAAM,KAAA,CAAM,oBAAoB,CAAC,CAAA;AAGjD,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,OAAA,CAAQ,IAAIA,sBAAA,CAAM,IAAA,CAAK,kBAAkB,CAAA,EAAG,OAAO,iBAAiB,CAAA;AACpE,IAAA,OAAA,CAAQ,IAAIA,sBAAA,CAAM,IAAA,CAAK,gBAAgB,CAAA,EAAG,gBAAgB,YAAY,CAAA;AACtE,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAEd,IAAA,IAAI,MAAA,CAAO,aAAA,CAAc,MAAA,GAAS,CAAA,EAAG;AACnC,MAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,iBAAiB,CAAC,CAAA;AACzC,MAAA,MAAA,CAAO,aAAA,CAAc,OAAA,CAAQ,CAAC,CAAA,KAAM,QAAQ,GAAA,CAAI,CAAA,EAAA,EAAKA,sBAAA,CAAM,IAAA,CAAK,QAAG,CAAC,CAAA,CAAA,EAAI,CAAC,EAAE,CAAC,CAAA;AAAA,IAC9E;AAEA,IAAA,IAAI,MAAA,CAAO,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG;AAChC,MAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,cAAc,CAAC,CAAA;AACtC,MAAA,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA,KAAM,QAAQ,GAAA,CAAI,CAAA,EAAA,EAAKA,sBAAA,CAAM,IAAA,CAAK,QAAG,CAAC,CAAA,CAAA,EAAI,CAAC,EAAE,CAAC,CAAA;AAAA,IAC3E;AAEA,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC9B,MAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,MAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,MAAA,CAAO,WAAW,CAAC,CAAA;AACrC,MAAA,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,KAAM,QAAQ,GAAA,CAAI,CAAA,EAAA,EAAKA,sBAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA,EAAI,CAAC,EAAE,CAAC,CAAA;AAAA,IAC3E;AAEA,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,KAAA,CAAM,SAAS,GAAG,UAAU,CAAA;AAAA,EAChD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,IAAA,CAAKA,sBAAA,CAAM,GAAA,CAAI,iBAAiB,CAAC,CAAA;AACzC,IAAA,OAAA,CAAQ,KAAA;AAAA,MACNA,sBAAA,CAAM,IAAI,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC;AAAA,KAClE;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CACG,OAAA,CAAQ,MAAM,CAAA,CACd,WAAA,CAAY,oCAAoC,CAAA,CAChD,MAAA,CAAO,qBAAA,EAAuB,gDAAgD,CAAA,CAC9E,MAAA,CAAO,CAAC,OAAA,KAAY;AACnB,EAAA,MAAM,UAAA,GAAaV,YAAAA,CAAQ,OAAA,CAAQ,MAAA,IAAU,yBAAyB,CAAA;AAEtE,EAAA,IAAIG,aAAAA,CAAW,UAAU,CAAA,EAAG;AAC1B,IAAA,OAAA,CAAQ,GAAA;AAAA,MACNO,sBAAA,CAAM,MAAA,CAAO,CAAA,mCAAA,EAAsC,UAAU,CAAA,CAAE;AAAA,KACjE;AACA,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,MAAA,CAAO,0CAA0C,CAAC,CAAA;AACpE,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,WAAW,sBAAA,EAAuB;AACxC,EAAAD,gBAAA,CAAc,YAAY,QAAQ,CAAA;AAClC,EAAA,OAAA,CAAQ,IAAIC,sBAAA,CAAM,KAAA,CAAM,CAAA,4BAAA,EAA+B,UAAU,EAAE,CAAC,CAAA;AACpE,EAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,EAAA,OAAA,CAAQ,IAAI,aAAa,CAAA;AACzB,EAAA,OAAA,CAAQ,GAAA,CAAI,aAAaA,sBAAA,CAAM,IAAA,CAAKC,cAAS,UAAU,CAAC,CAAC,CAAA,2BAAA,CAA6B,CAAA;AACtF,EAAA,OAAA,CAAQ,IAAI,CAAA,SAAA,EAAYD,sBAAA,CAAM,IAAA,CAAK,+BAA+B,CAAC,CAAA,kBAAA,CAAoB,CAAA;AACzF,CAAC,CAAA;AAEH,OAAA,CACG,OAAA,CAAQ,cAAc,CAAA,CACtB,WAAA,CAAY,iDAAiD,CAAA,CAC7D,MAAA,CAAO,OAAO,KAAA,KAAkB;AAC/B,EAAA,MAAM,OAAA,GAAUF,oBAAA,CAAI,sBAAsB,CAAA,CAAE,KAAA,EAAM;AAElD,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAYR,aAAQ,KAAK,CAAA;AAC/B,IAAA,IAAI,CAACG,aAAAA,CAAW,SAAS,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,SAAS,CAAA,CAAE,CAAA;AAAA,IACtD;AAEA,IAAA,MAAM,WAAA,GAAcE,gBAAa,SAAS,CAAA;AAC1C,IAAA,MAAMN,OAAAA,GAAAA,CAAU,MAAM,OAAO,SAAS,CAAA,EAAG,OAAA;AACzC,IAAA,MAAM,GAAA,GAAM,IAAIA,OAAAA,CAAO,WAAW,CAAA;AAElC,IAAA,MAAM,EAAE,cAAA,EAAAa,eAAAA,EAAe,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,cAAA,EAAA,EAAA,iBAAA,CAAA,CAAA;AACjC,IAAA,MAAM,QAAA,GAAW,IAAIA,eAAAA,EAAe;AACpC,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA;AAClC,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,oBAAA,CAAqB,MAAM,CAAA;AAEvD,IAAA,OAAA,CAAQ,QAAQ,kBAAkB,CAAA;AAElC,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,OAAA,CAAQ,GAAA,CAAIF,sBAAA,CAAM,IAAA,CAAK,OAAO,GAAG,SAAS,CAAA;AAC1C,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,SAAS,GAAG,UAAU,CAAA;AAC7C,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAGd,IAAA,MAAM,QAAA,GAAW;AAAA,MACf,yBAAA;AAAA,MACA,2BAAA;AAAA,MACA,iBAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAA,CAAQ,GAAA,CAAIA,sBAAA,CAAM,IAAA,CAAK,YAAY,CAAC,CAAA;AACpC,IAAA,KAAA,MAAW,QAAQ,QAAA,EAAU;AAC3B,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA,KAAM,IAAA;AACtC,MAAA,MAAM,IAAA,GAAO,SAASA,sBAAA,CAAM,KAAA,CAAM,QAAG,CAAA,GAAIA,sBAAA,CAAM,KAAK,QAAG,CAAA;AACvD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAAA,IACjC;AAGA,IAAA,MAAM,OAAA,GAAU,IAAI,UAAA,EAAW;AAC/B,IAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACd,IAAA,OAAA,CAAQ,IAAIA,sBAAA,CAAM,IAAA,CAAK,cAAc,CAAA,EAAG,QAAQ,MAAM,CAAA;AAAA,EACxD,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,IAAA,CAAKA,sBAAA,CAAM,GAAA,CAAI,iBAAiB,CAAC,CAAA;AACzC,IAAA,OAAA,CAAQ,KAAA;AAAA,MACNA,sBAAA,CAAM,IAAI,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC;AAAA,KAClE;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CAAQ,KAAA,EAAM","file":"cli.cjs","sourcesContent":["import type AdmZip from 'adm-zip';\n\n/**\n * Supported package formats\n */\nexport type PackageFormat =\n | 'scorm12'\n | 'scorm2004-3'\n | 'scorm2004-4'\n | 'cmi5'\n | 'xapi'\n | 'aicc'\n | 'unknown';\n\n/**\n * Detect the package format by examining manifest files\n */\nexport class FormatDetector {\n /**\n * Detect the package format from a ZIP file\n */\n detect(zip: AdmZip): PackageFormat {\n // Check for cmi5.xml first (most specific)\n if (zip.getEntry('cmi5.xml')) {\n return 'cmi5';\n }\n\n // Check for xAPI (tincan.xml)\n if (zip.getEntry('tincan.xml')) {\n return 'xapi';\n }\n\n // Check for SCORM via imsmanifest.xml\n const manifest = zip.getEntry('imsmanifest.xml');\n if (manifest) {\n const content = manifest.getData().toString('utf-8');\n return this.detectScormVersion(content);\n }\n\n // Check for AICC-specific files\n if (this.hasAiccFiles(zip)) {\n return 'aicc';\n }\n\n return 'unknown';\n }\n\n /**\n * Detect SCORM version from manifest content\n */\n private detectScormVersion(content: string): PackageFormat {\n // Check for SCORM 2004 4th Edition\n if (content.includes('4th Edition') || content.includes('CAM 1.4')) {\n return 'scorm2004-4';\n }\n\n // Check for SCORM 2004 3rd Edition\n if (\n content.includes('3rd Edition') ||\n content.includes('2004 3rd') ||\n content.includes('adlcp_v1p3')\n ) {\n return 'scorm2004-3';\n }\n\n // Check for SCORM 2004 (generic)\n if (content.includes('2004') && content.includes('adlseq')) {\n return 'scorm2004-3'; // Default to 3rd edition for generic 2004\n }\n\n // Check for SCORM 1.2\n if (\n content.includes('1.2') ||\n content.includes('adlcp_rootv1p2') ||\n content.includes('imscp_rootv1p1p2')\n ) {\n return 'scorm12';\n }\n\n // Check for AICC markers in manifest\n if (content.toLowerCase().includes('aicc')) {\n return 'aicc';\n }\n\n // Default to SCORM 1.2 if we have a manifest but can't determine version\n return 'scorm12';\n }\n\n /**\n * Check for AICC-specific files\n */\n private hasAiccFiles(zip: AdmZip): boolean {\n const aiccExtensions = ['.crs', '.au', '.des', '.cst'];\n const entries = zip.getEntries();\n\n for (const entry of entries) {\n const name = entry.entryName.toLowerCase();\n if (aiccExtensions.some((ext) => name.endsWith(ext))) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get a human-readable format name\n */\n getFormatDisplayName(format: PackageFormat): string {\n const names: Record<PackageFormat, string> = {\n scorm12: 'SCORM 1.2',\n 'scorm2004-3': 'SCORM 2004 3rd Edition',\n 'scorm2004-4': 'SCORM 2004 4th Edition',\n cmi5: 'cmi5',\n xapi: 'xAPI (Tin Can)',\n aicc: 'AICC',\n unknown: 'Unknown',\n };\n\n return names[format];\n }\n}\n","export { FormatDetector, type PackageFormat } from './format-detector.js';\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface CssBeforeOptions {\n remoteUrl: string;\n localPath: string;\n htmlClass: string;\n loadingClass: string;\n}\n\n/**\n * Generate the blocking CSS loader for the \"before\" slot\n * This loads at the start of <head> and blocks rendering until loaded\n *\n * Strategy:\n * 1. First, inline the critical CSS to hide content immediately\n * 2. Then load the remote CSS synchronously (or local fallback)\n */\nexport function generateCssBeforeLoader(options: CssBeforeOptions): string {\n const { remoteUrl, localPath, htmlClass, loadingClass } = options;\n\n return `<!-- === PATCH-ADAMS: CSS BEFORE (blocking) === -->\n<style data-pa=\"css-before-critical\">\n/* Critical: Hide content until ready */\nhtml.${htmlClass}.${loadingClass} body {\n visibility: hidden !important;\n}\n</style>\n<script data-pa=\"css-before-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n\n function loadCSSSync(url) {\n var link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n link.setAttribute('data-pa', 'css-before');\n document.head.appendChild(link);\n return link;\n }\n\n // Try remote first\n var link = loadCSSSync(REMOTE_URL);\n\n link.onerror = function() {\n console.warn('[Patch-Adams] CSS before failed to load from remote, using local fallback');\n document.head.removeChild(link);\n loadCSSSync(LOCAL_PATH);\n };\n\n link.onload = function() {\n console.log('[Patch-Adams] CSS before loaded from remote:', REMOTE_URL);\n };\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildCssBeforeOptions(config: PatchAdamsConfig): CssBeforeOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.cssBefore.filename}`,\n localPath: `${config.localFolders.css}/${config.cssBefore.filename}`,\n htmlClass: config.htmlClass,\n loadingClass: config.loadingClass,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface CssAfterOptions {\n remoteUrl: string;\n localPath: string;\n timeout: number;\n}\n\n/**\n * Generate the async CSS loader for the \"after\" slot\n * This loads at the end of <head> with remote-first, local fallback\n */\nexport function generateCssAfterLoader(options: CssAfterOptions): string {\n const { remoteUrl, localPath, timeout } = options;\n\n return `<!-- === PATCH-ADAMS: CSS AFTER (async with fallback) === -->\n<script data-pa=\"css-after-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n var TIMEOUT = ${timeout};\n\n function loadCSS(url, onSuccess, onError) {\n var link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n link.setAttribute('data-pa', 'css-after');\n\n link.onload = function() {\n if (onSuccess) onSuccess();\n };\n\n link.onerror = function() {\n if (onError) onError();\n };\n\n document.head.appendChild(link);\n return link;\n }\n\n function loadCSSWithFallback() {\n var loaded = false;\n var timeoutId;\n\n // Try remote first\n var remoteLink = loadCSS(\n REMOTE_URL,\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n console.log('[Patch-Adams] CSS after loaded from remote:', REMOTE_URL);\n },\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n loadLocalFallback();\n }\n );\n\n // Timeout fallback\n timeoutId = setTimeout(function() {\n if (loaded) return;\n loaded = true;\n console.warn('[Patch-Adams] CSS after timed out, using local fallback');\n if (remoteLink.parentNode) {\n document.head.removeChild(remoteLink);\n }\n loadLocalFallback();\n }, TIMEOUT);\n }\n\n function loadLocalFallback() {\n loadCSS(\n LOCAL_PATH,\n function() {\n console.log('[Patch-Adams] CSS after loaded from local fallback:', LOCAL_PATH);\n },\n function() {\n console.error('[Patch-Adams] CSS after failed to load from both remote and local');\n }\n );\n }\n\n // Execute immediately\n loadCSSWithFallback();\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildCssAfterOptions(config: PatchAdamsConfig): CssAfterOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.cssAfter.filename}`,\n localPath: `${config.localFolders.css}/${config.cssAfter.filename}`,\n timeout: config.cssAfter.timeout,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface JsBeforeOptions {\n remoteUrl: string;\n localPath: string;\n htmlClass: string;\n loadingClass: string;\n}\n\n/**\n * Generate the blocking JS loader for the \"before\" slot\n * This loads at the start of <head> and blocks rendering until loaded\n *\n * Use this for:\n * - Setting up global variables\n * - Intercepting Rise APIs before they initialize\n * - Preparing the environment\n */\nexport function generateJsBeforeLoader(options: JsBeforeOptions): string {\n const { remoteUrl, localPath, htmlClass, loadingClass } = options;\n\n return `<!-- === PATCH-ADAMS: JS BEFORE (blocking) === -->\n<script data-pa=\"js-before-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n\n // Initialize Patch-Adams global namespace\n window.PatchAdams = window.PatchAdams || {\n version: '1.0.0',\n htmlClass: '${htmlClass}',\n loadingClass: '${loadingClass}',\n loaded: {\n cssBefore: false,\n cssAfter: false,\n jsBefore: false,\n jsAfter: false\n }\n };\n\n function loadJSSync(url) {\n var script = document.createElement('script');\n script.src = url;\n script.setAttribute('data-pa', 'js-before');\n // Note: For truly blocking behavior, we use document.write\n // but that's fragile. Instead we'll handle errors gracefully.\n document.head.appendChild(script);\n return script;\n }\n\n // Try remote first\n var script = loadJSSync(REMOTE_URL);\n\n script.onerror = function() {\n console.warn('[Patch-Adams] JS before failed to load from remote, using local fallback');\n document.head.removeChild(script);\n var fallback = loadJSSync(LOCAL_PATH);\n fallback.onload = function() {\n window.PatchAdams.loaded.jsBefore = true;\n console.log('[Patch-Adams] JS before loaded from local fallback:', LOCAL_PATH);\n };\n fallback.onerror = function() {\n console.error('[Patch-Adams] JS before failed to load from both remote and local');\n };\n };\n\n script.onload = function() {\n window.PatchAdams.loaded.jsBefore = true;\n console.log('[Patch-Adams] JS before loaded from remote:', REMOTE_URL);\n };\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildJsBeforeOptions(config: PatchAdamsConfig): JsBeforeOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.jsBefore.filename}`,\n localPath: `${config.localFolders.js}/${config.jsBefore.filename}`,\n htmlClass: config.htmlClass,\n loadingClass: config.loadingClass,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface JsAfterOptions {\n remoteUrl: string;\n localPath: string;\n timeout: number;\n loadingClass: string;\n}\n\n/**\n * Generate the async JS loader for the \"after\" slot\n * This loads at the end of <body> with remote-first, local fallback\n *\n * This script is responsible for:\n * - Loading your override JS after Rise has initialized\n * - Removing the loading class to reveal the content\n */\nexport function generateJsAfterLoader(options: JsAfterOptions): string {\n const { remoteUrl, localPath, timeout, loadingClass } = options;\n\n return `<!-- === PATCH-ADAMS: JS AFTER (async with fallback) === -->\n<script data-pa=\"js-after-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n var TIMEOUT = ${timeout};\n var LOADING_CLASS = \"${loadingClass}\";\n\n function loadJS(url, onSuccess, onError) {\n var script = document.createElement('script');\n script.src = url;\n script.async = true;\n script.setAttribute('data-pa', 'js-after');\n\n script.onload = function() {\n if (onSuccess) onSuccess();\n };\n\n script.onerror = function() {\n if (onError) onError();\n };\n\n document.body.appendChild(script);\n return script;\n }\n\n function removeLoadingClass() {\n document.documentElement.classList.remove(LOADING_CLASS);\n if (window.PatchAdams) {\n window.PatchAdams.loaded.jsAfter = true;\n }\n console.log('[Patch-Adams] Loading complete, content revealed');\n }\n\n function loadJSWithFallback() {\n var loaded = false;\n var timeoutId;\n\n // Try remote first\n var remoteScript = loadJS(\n REMOTE_URL,\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n console.log('[Patch-Adams] JS after loaded from remote:', REMOTE_URL);\n // Give the script a moment to execute, then remove loading class\n setTimeout(removeLoadingClass, 50);\n },\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n loadLocalFallback();\n }\n );\n\n // Timeout fallback\n timeoutId = setTimeout(function() {\n if (loaded) return;\n loaded = true;\n console.warn('[Patch-Adams] JS after timed out, using local fallback');\n if (remoteScript.parentNode) {\n document.body.removeChild(remoteScript);\n }\n loadLocalFallback();\n }, TIMEOUT);\n }\n\n function loadLocalFallback() {\n loadJS(\n LOCAL_PATH,\n function() {\n console.log('[Patch-Adams] JS after loaded from local fallback:', LOCAL_PATH);\n setTimeout(removeLoadingClass, 50);\n },\n function() {\n console.error('[Patch-Adams] JS after failed to load from both remote and local');\n // Still remove loading class so content is visible even if JS fails\n removeLoadingClass();\n }\n );\n }\n\n // Execute after DOM is ready to ensure Rise has loaded\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', function() {\n // Small delay to ensure Rise has initialized\n setTimeout(loadJSWithFallback, 100);\n });\n } else {\n // DOM is already ready\n setTimeout(loadJSWithFallback, 100);\n }\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildJsAfterOptions(config: PatchAdamsConfig): JsAfterOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.jsAfter.filename}`,\n localPath: `${config.localFolders.js}/${config.jsAfter.filename}`,\n timeout: config.jsAfter.timeout,\n loadingClass: config.loadingClass,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\nimport {\n generateCssBeforeLoader,\n buildCssBeforeOptions,\n generateCssAfterLoader,\n buildCssAfterOptions,\n generateJsBeforeLoader,\n buildJsBeforeOptions,\n generateJsAfterLoader,\n buildJsAfterOptions,\n} from '../templates/index.js';\n\n/**\n * HTML Injector for patching Rise course index.html\n *\n * Injection points:\n * 1. CSS Before - Start of <head> (blocking)\n * 2. JS Before - Start of <head>, after CSS Before (blocking)\n * 3. CSS After - End of <head> (async with fallback)\n * 4. JS After - End of <body>, after __loadEntry() (async with fallback)\n *\n * Also adds classes to <html> tag for specificity\n */\nexport class HtmlInjector {\n private config: PatchAdamsConfig;\n\n constructor(config: PatchAdamsConfig) {\n this.config = config;\n }\n\n /**\n * Inject all loaders into HTML\n */\n inject(html: string): string {\n let result = html;\n\n // Step 1: Add classes to <html> tag\n result = this.addHtmlClasses(result);\n\n // Step 2: Inject CSS Before at start of <head>\n if (this.config.cssBefore.enabled) {\n result = this.injectCssBefore(result);\n }\n\n // Step 3: Inject JS Before at start of <head> (after CSS Before)\n if (this.config.jsBefore.enabled) {\n result = this.injectJsBefore(result);\n }\n\n // Step 4: Inject CSS After at end of <head>\n if (this.config.cssAfter.enabled) {\n result = this.injectCssAfter(result);\n }\n\n // Step 5: Inject JS After at end of <body>\n if (this.config.jsAfter.enabled) {\n result = this.injectJsAfter(result);\n }\n\n return result;\n }\n\n /**\n * Add pa-patched and pa-loading classes to <html> tag\n */\n private addHtmlClasses(html: string): string {\n const { htmlClass, loadingClass } = this.config;\n const classes = `${htmlClass} ${loadingClass}`;\n\n // Match <html> tag with or without existing class attribute\n const htmlTagPattern = /<html([^>]*)>/i;\n const match = html.match(htmlTagPattern);\n\n if (!match) {\n return html;\n }\n\n const attributes = match[1];\n\n // Check if class attribute exists\n if (/class\\s*=\\s*[\"'][^\"']*[\"']/i.test(attributes)) {\n // Append to existing class\n return html.replace(\n htmlTagPattern,\n (_match: string, attrs: string) => {\n const newAttrs = attrs.replace(\n /class\\s*=\\s*[\"']([^\"']*)[\"']/i,\n (_fullMatch: string, existingClasses: string) => `class=\"${existingClasses} ${classes}\"`\n );\n return `<html${newAttrs}>`;\n }\n );\n } else {\n // Add class attribute\n return html.replace(htmlTagPattern, `<html${attributes} class=\"${classes}\">`);\n }\n }\n\n /**\n * Inject CSS Before loader at start of <head>\n */\n private injectCssBefore(html: string): string {\n const options = buildCssBeforeOptions(this.config);\n const loader = generateCssBeforeLoader(options);\n\n // Insert right after <head> tag\n return html.replace(/<head([^>]*)>/i, `<head$1>\\n${loader}`);\n }\n\n /**\n * Inject JS Before loader at start of <head> (after CSS Before if present)\n */\n private injectJsBefore(html: string): string {\n const options = buildJsBeforeOptions(this.config);\n const loader = generateJsBeforeLoader(options);\n\n // Look for the CSS Before marker to insert after it\n const cssBeforeMarker = '<!-- === PATCH-ADAMS: CSS BEFORE';\n if (html.includes(cssBeforeMarker)) {\n // Find end of CSS Before block and insert after\n const cssBeforeEndPattern = /<\\/script>\\s*(?=\\n|<)/;\n const cssBeforeStart = html.indexOf(cssBeforeMarker);\n const afterCssBefore = html.substring(cssBeforeStart);\n const endMatch = afterCssBefore.match(cssBeforeEndPattern);\n\n if (endMatch && endMatch.index !== undefined) {\n const insertPos = cssBeforeStart + endMatch.index + endMatch[0].length;\n return html.slice(0, insertPos) + '\\n' + loader + html.slice(insertPos);\n }\n }\n\n // Fallback: insert after <head> tag\n return html.replace(/<head([^>]*)>/i, `<head$1>\\n${loader}`);\n }\n\n /**\n * Inject CSS After loader at end of <head>\n */\n private injectCssAfter(html: string): string {\n const options = buildCssAfterOptions(this.config);\n const loader = generateCssAfterLoader(options);\n\n // Insert before </head>\n return html.replace(/<\\/head>/i, `${loader}\\n</head>`);\n }\n\n /**\n * Inject JS After loader at end of <body> (after __loadEntry)\n */\n private injectJsAfter(html: string): string {\n const options = buildJsAfterOptions(this.config);\n const loader = generateJsAfterLoader(options);\n\n // Try to find __loadEntry() call and insert after it\n const loadEntryPattern = /(<script>__loadEntry\\(\\)<\\/script>)/i;\n if (loadEntryPattern.test(html)) {\n return html.replace(loadEntryPattern, `$1\\n${loader}`);\n }\n\n // Fallback: insert before </body>\n return html.replace(/<\\/body>/i, `${loader}\\n</body>`);\n }\n}\n","import type AdmZip from 'adm-zip';\nimport { XMLParser, XMLBuilder } from 'fast-xml-parser';\nimport type { PatchAdamsConfig } from '../config/schema.js';\nimport type { PackageFormat } from '../detectors/format-detector.js';\n\nexport interface ManifestPaths {\n cssBefore?: string;\n cssAfter?: string;\n jsBefore?: string;\n jsAfter?: string;\n}\n\n/**\n * Update manifest files to include injected assets\n * This ensures SCORM compliance for strict LMS systems\n */\nexport class ManifestUpdater {\n private config: PatchAdamsConfig;\n private parser: XMLParser;\n private builder: XMLBuilder;\n\n constructor(config: PatchAdamsConfig) {\n this.config = config;\n this.parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n preserveOrder: false,\n parseAttributeValue: false,\n trimValues: true,\n });\n this.builder = new XMLBuilder({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n format: true,\n indentBy: ' ',\n suppressEmptyNode: true,\n });\n }\n\n /**\n * Update manifest files based on package format\n */\n update(zip: AdmZip, format: PackageFormat, paths: ManifestPaths): string[] {\n const modified: string[] = [];\n\n switch (format) {\n case 'scorm12':\n case 'scorm2004-3':\n case 'scorm2004-4':\n modified.push(...this.updateImsManifest(zip, paths));\n break;\n\n case 'cmi5':\n // cmi5 packages also typically have an imsmanifest.xml\n modified.push(...this.updateImsManifest(zip, paths));\n break;\n\n case 'xapi':\n // xAPI/tincan.xml doesn't have file manifests\n // Files are loaded directly by HTML\n break;\n\n case 'aicc':\n // AICC may have imsmanifest.xml\n const aiccManifest = zip.getEntry('imsmanifest.xml');\n if (aiccManifest) {\n modified.push(...this.updateImsManifest(zip, paths));\n }\n break;\n }\n\n return modified;\n }\n\n /**\n * Update imsmanifest.xml to include new file references\n */\n private updateImsManifest(zip: AdmZip, paths: ManifestPaths): string[] {\n const entry = zip.getEntry('imsmanifest.xml');\n if (!entry) {\n return [];\n }\n\n try {\n const xmlContent = entry.getData().toString('utf-8');\n const parsed = this.parser.parse(xmlContent);\n\n // Find resources and add file entries\n this.addFilesToManifest(parsed, paths);\n\n // Rebuild XML with declaration\n const xmlDeclaration = this.extractXmlDeclaration(xmlContent);\n const updatedXml = xmlDeclaration + this.builder.build(parsed);\n\n zip.updateFile('imsmanifest.xml', Buffer.from(updatedXml, 'utf-8'));\n\n return ['imsmanifest.xml'];\n } catch (error) {\n console.error('[Patch-Adams] Failed to update imsmanifest.xml:', error);\n return [];\n }\n }\n\n /**\n * Extract XML declaration from original content\n */\n private extractXmlDeclaration(xml: string): string {\n const match = xml.match(/<\\?xml[^?]*\\?>/);\n return match ? match[0] + '\\n' : '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n }\n\n /**\n * Add file entries to the manifest\n */\n private addFilesToManifest(parsed: Record<string, unknown>, paths: ManifestPaths): void {\n // Navigate to find the resource element\n const manifest = parsed.manifest as Record<string, unknown> | undefined;\n if (!manifest) return;\n\n const resources = manifest.resources as Record<string, unknown> | undefined;\n if (!resources) return;\n\n let resource = resources.resource as Record<string, unknown> | Record<string, unknown>[] | undefined;\n if (!resource) return;\n\n // Handle single resource or array\n if (Array.isArray(resource)) {\n resource = resource[0];\n }\n\n // Ensure file array exists\n if (!resource.file) {\n resource.file = [];\n }\n\n let files = resource.file as Array<Record<string, string>>;\n if (!Array.isArray(files)) {\n files = [files as unknown as Record<string, string>];\n resource.file = files;\n }\n\n // Add new file entries\n const filesToAdd = [\n paths.cssBefore,\n paths.cssAfter,\n paths.jsBefore,\n paths.jsAfter,\n ].filter(Boolean) as string[];\n\n for (const filePath of filesToAdd) {\n // Check if already exists\n const exists = files.some((f) => f['@_href'] === filePath);\n if (!exists) {\n files.push({ '@_href': filePath });\n }\n }\n }\n\n /**\n * Get the file paths that will be added to the package\n */\n getFilePaths(): ManifestPaths {\n const paths: ManifestPaths = {};\n\n if (this.config.cssBefore.enabled) {\n paths.cssBefore = `scormcontent/${this.config.localFolders.css}/${this.config.cssBefore.filename}`;\n }\n\n if (this.config.cssAfter.enabled) {\n paths.cssAfter = `scormcontent/${this.config.localFolders.css}/${this.config.cssAfter.filename}`;\n }\n\n if (this.config.jsBefore.enabled) {\n paths.jsBefore = `scormcontent/${this.config.localFolders.js}/${this.config.jsBefore.filename}`;\n }\n\n if (this.config.jsAfter.enabled) {\n paths.jsAfter = `scormcontent/${this.config.localFolders.js}/${this.config.jsAfter.filename}`;\n }\n\n return paths;\n }\n}\n","import AdmZip from 'adm-zip';\nimport yazl from 'yazl';\nimport type { PatchAdamsConfig } from '../config/schema.js';\nimport { HtmlInjector } from './html-injector.js';\nimport { ManifestUpdater } from './manifest-updater.js';\nimport { FormatDetector, type PackageFormat } from '../detectors/format-detector.js';\n\n/**\n * Result of a patch operation\n */\nexport interface PatchResult {\n success: boolean;\n format: PackageFormat;\n formatDisplayName: string;\n filesModified: string[];\n filesAdded: string[];\n errors: string[];\n warnings: string[];\n}\n\n/**\n * Options for patching\n */\nexport interface PatchOptions {\n /** Content for CSS before (local fallback) */\n cssBeforeContent?: string;\n /** Content for CSS after (local fallback) */\n cssAfterContent?: string;\n /** Content for JS before (local fallback) */\n jsBeforeContent?: string;\n /** Content for JS after (local fallback) */\n jsAfterContent?: string;\n}\n\n/**\n * Default fallback file contents\n */\nconst DEFAULT_CSS_BEFORE = `/* Patch-Adams: CSS Before (blocking)\n * This file loads at the start of <head> and blocks rendering.\n * Use it to hide content and prevent flash of unstyled content.\n *\n * Example:\n * html.pa-patched.pa-loading body {\n * visibility: hidden !important;\n * }\n */\n`;\n\nconst DEFAULT_CSS_AFTER = `/* Patch-Adams: CSS After (async)\n * This file loads at the end of <head> with remote fallback.\n * Use it for style overrides that take precedence over Rise styles.\n *\n * Example:\n * html.pa-patched .blocks-text {\n * font-family: 'Your Font', sans-serif !important;\n * }\n */\n`;\n\nconst DEFAULT_JS_BEFORE = `// Patch-Adams: JS Before (blocking)\n// This file loads at the start of <head> and blocks rendering.\n// Use it for setup, API interception, and preparing globals.\n//\n// Example:\n// window.PatchAdams.customConfig = {\n// theme: 'dark',\n// analytics: true\n// };\n\nconsole.log('[Patch-Adams] JS Before loaded');\n`;\n\nconst DEFAULT_JS_AFTER = `// Patch-Adams: JS After (async)\n// This file loads at the end of <body> with remote fallback.\n// Use it for DOM manipulation after Rise has initialized.\n//\n// IMPORTANT: This script should NOT remove the loading class.\n// The loader script handles that automatically after this script loads.\n//\n// Example:\n// document.querySelectorAll('.blocks-text').forEach(function(el) {\n// // Your modifications here\n// });\n\nconsole.log('[Patch-Adams] JS After loaded');\n`;\n\n/**\n * Main Patcher class for patching Rise course packages\n */\nexport class Patcher {\n private config: PatchAdamsConfig;\n private htmlInjector: HtmlInjector;\n private manifestUpdater: ManifestUpdater;\n private formatDetector: FormatDetector;\n\n constructor(config: PatchAdamsConfig) {\n this.config = config;\n this.htmlInjector = new HtmlInjector(config);\n this.manifestUpdater = new ManifestUpdater(config);\n this.formatDetector = new FormatDetector();\n }\n\n /**\n * Patch a Rise course ZIP file\n * @param inputBuffer - Input ZIP file as Buffer\n * @param options - Additional patching options\n * @returns Patched ZIP file as Buffer and result details\n */\n async patch(\n inputBuffer: Buffer,\n options: PatchOptions = {}\n ): Promise<{ buffer: Buffer; result: PatchResult }> {\n const result: PatchResult = {\n success: false,\n format: 'unknown',\n formatDisplayName: 'Unknown',\n filesModified: [],\n filesAdded: [],\n errors: [],\n warnings: [],\n };\n\n try {\n // 1. Open ZIP with adm-zip for reading\n const zip = new AdmZip(inputBuffer);\n\n // 2. Detect package format\n result.format = this.formatDetector.detect(zip);\n result.formatDisplayName = this.formatDetector.getFormatDisplayName(result.format);\n\n if (result.format === 'unknown') {\n result.warnings.push('Could not determine package format, proceeding anyway');\n }\n\n // 3. Find and patch index.html\n const indexHtmlEntry = zip.getEntry('scormcontent/index.html');\n if (!indexHtmlEntry) {\n throw new Error('Could not find scormcontent/index.html in package. Is this a valid Rise export?');\n }\n\n const originalHtml = indexHtmlEntry.getData().toString('utf-8');\n const patchedHtml = this.htmlInjector.inject(originalHtml);\n zip.updateFile('scormcontent/index.html', Buffer.from(patchedHtml, 'utf-8'));\n result.filesModified.push('scormcontent/index.html');\n\n // 4. Add local fallback files\n const addedFiles = this.addFallbackFiles(zip, options);\n result.filesAdded.push(...addedFiles);\n\n // 5. Update manifest files\n if (this.config.updateManifests) {\n const manifestPaths = this.manifestUpdater.getFilePaths();\n const modifiedManifests = this.manifestUpdater.update(zip, result.format, manifestPaths);\n result.filesModified.push(...modifiedManifests);\n }\n\n // 6. Write output using yazl for better ZIP compatibility\n // adm-zip's toBuffer() uses data descriptors (bit 3 flag) which some\n // parsers don't handle well. yazl produces more standard ZIP output.\n const outputBuffer = await this.writeZipWithYazl(zip);\n\n result.success = true;\n return { buffer: outputBuffer, result };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n result.errors.push(message);\n throw error;\n }\n }\n\n /**\n * Write ZIP using yazl for better compatibility\n * adm-zip's toBuffer() sets the data descriptor bit flag which causes\n * issues with some ZIP parsers. yazl produces standard ZIP output.\n */\n private writeZipWithYazl(admZip: AdmZip): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const zipFile = new yazl.ZipFile();\n const entries = admZip.getEntries();\n\n for (const entry of entries) {\n const entryName = entry.entryName;\n const mtime = entry.header.time ? new Date(entry.header.time) : new Date();\n\n if (entry.isDirectory) {\n // Explicitly add directory entries for compatibility\n zipFile.addEmptyDirectory(entryName, { mtime });\n continue;\n }\n\n const entryData = entry.getData();\n\n // Add file with compression\n zipFile.addBuffer(entryData, entryName, {\n compress: true,\n mtime,\n });\n }\n\n // Finalize and collect output\n const chunks: Buffer[] = [];\n zipFile.outputStream.on('data', (chunk: Buffer) => chunks.push(chunk));\n zipFile.outputStream.on('end', () => resolve(Buffer.concat(chunks)));\n zipFile.outputStream.on('error', reject);\n zipFile.end();\n });\n }\n\n /**\n * Add local fallback files to the ZIP\n */\n private addFallbackFiles(zip: AdmZip, options: PatchOptions): string[] {\n const added: string[] = [];\n const cssFolder = `scormcontent/${this.config.localFolders.css}`;\n const jsFolder = `scormcontent/${this.config.localFolders.js}`;\n\n // CSS Before\n if (this.config.cssBefore.enabled) {\n const path = `${cssFolder}/${this.config.cssBefore.filename}`;\n const content = options.cssBeforeContent ?? DEFAULT_CSS_BEFORE;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n // CSS After\n if (this.config.cssAfter.enabled) {\n const path = `${cssFolder}/${this.config.cssAfter.filename}`;\n const content = options.cssAfterContent ?? DEFAULT_CSS_AFTER;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n // JS Before\n if (this.config.jsBefore.enabled) {\n const path = `${jsFolder}/${this.config.jsBefore.filename}`;\n const content = options.jsBeforeContent ?? DEFAULT_JS_BEFORE;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n // JS After\n if (this.config.jsAfter.enabled) {\n const path = `${jsFolder}/${this.config.jsAfter.filename}`;\n const content = options.jsAfterContent ?? DEFAULT_JS_AFTER;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n return added;\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): PatchAdamsConfig {\n return this.config;\n }\n\n /**\n * Convenience method to patch a buffer and return only the patched buffer.\n * Used by package-uploader integration.\n * @param buffer - Input ZIP file as Buffer\n * @returns Patched ZIP file as Buffer\n */\n async patchBuffer(buffer: Buffer): Promise<Buffer> {\n console.log(`[Patcher] patchBuffer called with ${buffer.length} bytes`);\n const { buffer: patchedBuffer, result } = await this.patch(buffer);\n console.log(`[Patcher] Patch result:`, JSON.stringify(result, null, 2));\n console.log(`[Patcher] Returning ${patchedBuffer.length} bytes`);\n return patchedBuffer;\n }\n}\n\nexport { HtmlInjector } from './html-injector.js';\nexport { ManifestUpdater, type ManifestPaths } from './manifest-updater.js';\n","import { z } from 'zod';\n\n/**\n * Configuration for a blocking asset (CSS before, JS before)\n * These load synchronously and block page rendering\n */\nexport const BlockingAssetConfigSchema = z.object({\n /** Filename for the asset */\n filename: z.string().min(1),\n /** Whether this asset is enabled */\n enabled: z.boolean().default(true),\n});\n\n/**\n * Configuration for an async asset (CSS after, JS after)\n * These load asynchronously with remote-first, local fallback\n */\nexport const AsyncAssetConfigSchema = z.object({\n /** Filename for the asset */\n filename: z.string().min(1),\n /** Whether this asset is enabled */\n enabled: z.boolean().default(true),\n /** Timeout in milliseconds for remote loading before falling back to local */\n timeout: z.number().min(1000).max(30000).default(5000),\n});\n\n/**\n * Local folder configuration for fallback files\n */\nexport const LocalFoldersConfigSchema = z.object({\n /** Folder name for CSS files within scormcontent */\n css: z.string().default('css'),\n /** Folder name for JS files within scormcontent */\n js: z.string().default('js'),\n});\n\n/**\n * Main configuration schema for Patch-Adams\n */\nexport const PatchAdamsConfigSchema = z.object({\n /** Remote domain for assets (e.g., \"https://cdn.example.com/rise-overrides\") */\n remoteDomain: z.string().url(),\n\n /** CSS class added to <html> tag for specificity (default: \"pa-patched\") */\n htmlClass: z.string().default('pa-patched'),\n\n /** CSS class added during loading, removed when ready (default: \"pa-loading\") */\n loadingClass: z.string().default('pa-loading'),\n\n /** CSS loaded at start of <head> - blocking, prevents FOUC */\n cssBefore: BlockingAssetConfigSchema.default({\n filename: 'before.css',\n enabled: true,\n }),\n\n /** CSS loaded at end of <head> - async with fallback, for overrides */\n cssAfter: AsyncAssetConfigSchema.default({\n filename: 'after.css',\n enabled: true,\n timeout: 5000,\n }),\n\n /** JS loaded at start of <head> - blocking, for setup/interception */\n jsBefore: BlockingAssetConfigSchema.default({\n filename: 'before.js',\n enabled: true,\n }),\n\n /** JS loaded at end of <body> - async with fallback, removes loading class */\n jsAfter: AsyncAssetConfigSchema.default({\n filename: 'after.js',\n enabled: true,\n timeout: 5000,\n }),\n\n /** Local folder names for fallback files */\n localFolders: LocalFoldersConfigSchema.default({}),\n\n /** Whether to update manifest files (imsmanifest.xml, etc.) for SCORM compliance */\n updateManifests: z.boolean().default(true),\n});\n\nexport type PatchAdamsConfig = z.infer<typeof PatchAdamsConfigSchema>;\nexport type BlockingAssetConfig = z.infer<typeof BlockingAssetConfigSchema>;\nexport type AsyncAssetConfig = z.infer<typeof AsyncAssetConfigSchema>;\nexport type LocalFoldersConfig = z.infer<typeof LocalFoldersConfigSchema>;\n","import type { PatchAdamsConfig } from './schema.js';\n\n/**\n * Default configuration values for Patch-Adams\n */\nexport const defaultConfig: PatchAdamsConfig = {\n remoteDomain: 'https://cdn.example.com/rise-overrides',\n\n htmlClass: 'pa-patched',\n loadingClass: 'pa-loading',\n\n cssBefore: {\n filename: 'before.css',\n enabled: true,\n },\n\n cssAfter: {\n filename: 'after.css',\n enabled: true,\n timeout: 5000,\n },\n\n jsBefore: {\n filename: 'before.js',\n enabled: true,\n },\n\n jsAfter: {\n filename: 'after.js',\n enabled: true,\n timeout: 5000,\n },\n\n localFolders: {\n css: 'css',\n js: 'js',\n },\n\n updateManifests: true,\n};\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve, extname } from 'path';\nimport { pathToFileURL } from 'url';\nimport { PatchAdamsConfigSchema, type PatchAdamsConfig } from './schema.js';\nimport { defaultConfig } from './defaults.js';\n\n/**\n * Load and validate a Patch-Adams configuration file\n * Supports .ts, .js, and .json files\n */\nexport async function loadConfig(configPath: string): Promise<PatchAdamsConfig> {\n const absolutePath = resolve(configPath);\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Configuration file not found: ${absolutePath}`);\n }\n\n const ext = extname(absolutePath).toLowerCase();\n let rawConfig: unknown;\n\n if (ext === '.json') {\n const content = readFileSync(absolutePath, 'utf-8');\n rawConfig = JSON.parse(content);\n } else if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n // Dynamic import for ESM modules\n const fileUrl = pathToFileURL(absolutePath).href;\n const module = await import(fileUrl);\n rawConfig = module.default ?? module;\n } else {\n throw new Error(`Unsupported config file extension: ${ext}. Use .ts, .js, .mjs, or .json`);\n }\n\n // Validate and return\n const validated = PatchAdamsConfigSchema.parse(rawConfig);\n return validated;\n}\n\n/**\n * Create a merged config with defaults\n */\nexport function mergeWithDefaults(partial: Partial<PatchAdamsConfig>): PatchAdamsConfig {\n return PatchAdamsConfigSchema.parse({\n ...defaultConfig,\n ...partial,\n });\n}\n\n/**\n * Generate a configuration file template\n */\nexport function generateConfigTemplate(): string {\n return `import type { PatchAdamsConfig } from '@patch-adams/core';\n\nconst config: PatchAdamsConfig = {\n // Remote domain where your CSS/JS files are hosted\n remoteDomain: 'https://cdn.example.com/rise-overrides',\n\n // HTML classes for specificity and loading state\n htmlClass: 'pa-patched', // Always present on <html>\n loadingClass: 'pa-loading', // Removed when assets are loaded\n\n // CSS loaded at start of <head> - BLOCKING\n // Use this to hide content and prevent flash of unstyled content\n cssBefore: {\n filename: 'before.css',\n enabled: true,\n },\n\n // CSS loaded at end of <head> - ASYNC with fallback\n // Use this for style overrides\n cssAfter: {\n filename: 'after.css',\n enabled: true,\n timeout: 5000, // ms before falling back to local\n },\n\n // JS loaded at start of <head> - BLOCKING\n // Use this for setup, API interception, globals\n jsBefore: {\n filename: 'before.js',\n enabled: true,\n },\n\n // JS loaded at end of <body> - ASYNC with fallback\n // Use this for DOM manipulation after Rise loads\n // This should remove the loadingClass when done\n jsAfter: {\n filename: 'after.js',\n enabled: true,\n timeout: 5000, // ms before falling back to local\n },\n\n // Folder names for local fallback files within scormcontent/\n localFolders: {\n css: 'css',\n js: 'js',\n },\n\n // Update manifest files for SCORM compliance\n updateManifests: true,\n};\n\nexport default config;\n`;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { resolve, basename } from 'path';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { Patcher } from './patcher/index.js';\nimport { loadConfig, generateConfigTemplate, mergeWithDefaults } from './config/index.js';\nimport { PatchAdamsConfigSchema } from './config/schema.js';\n\nconst program = new Command();\n\nprogram\n .name('patch-adams')\n .description('Patch Rise course packages to inject remote CSS/JS with local fallback')\n .version('1.0.0');\n\nprogram\n .command('patch <input>')\n .description('Patch a Rise course ZIP file')\n .option('-o, --output <path>', 'Output file path (default: <input>-patched.zip)')\n .option('-c, --config <path>', 'Configuration file path (default: ./patch-adams.config.ts)')\n .option('--css-before <path>', 'Local CSS file for \"before\" fallback')\n .option('--css-after <path>', 'Local CSS file for \"after\" fallback')\n .option('--js-before <path>', 'Local JS file for \"before\" fallback')\n .option('--js-after <path>', 'Local JS file for \"after\" fallback')\n .option('--no-manifest', 'Skip updating manifest files')\n .action(async (input: string, options) => {\n const spinner = ora('Loading configuration...').start();\n\n try {\n // Load config\n let config;\n const configPath = options.config || './patch-adams.config.ts';\n\n if (existsSync(resolve(configPath))) {\n config = await loadConfig(configPath);\n spinner.text = 'Configuration loaded';\n } else {\n spinner.text = 'No config file found, using defaults';\n config = mergeWithDefaults({});\n }\n\n // Override manifest update setting\n if (options.manifest === false) {\n config = { ...config, updateManifests: false };\n }\n\n // Validate config\n const validatedConfig = PatchAdamsConfigSchema.parse(config);\n\n spinner.text = 'Reading input file...';\n\n // Read input ZIP\n const inputPath = resolve(input);\n if (!existsSync(inputPath)) {\n throw new Error(`Input file not found: ${inputPath}`);\n }\n const inputBuffer = readFileSync(inputPath);\n\n // Read optional CSS/JS files\n const patchOptions: {\n cssBeforeContent?: string;\n cssAfterContent?: string;\n jsBeforeContent?: string;\n jsAfterContent?: string;\n } = {};\n\n if (options.cssBefore) {\n patchOptions.cssBeforeContent = readFileSync(resolve(options.cssBefore), 'utf-8');\n }\n\n if (options.cssAfter) {\n patchOptions.cssAfterContent = readFileSync(resolve(options.cssAfter), 'utf-8');\n }\n\n if (options.jsBefore) {\n patchOptions.jsBeforeContent = readFileSync(resolve(options.jsBefore), 'utf-8');\n }\n\n if (options.jsAfter) {\n patchOptions.jsAfterContent = readFileSync(resolve(options.jsAfter), 'utf-8');\n }\n\n spinner.text = 'Patching package...';\n\n // Patch\n const patcher = new Patcher(validatedConfig);\n const { buffer, result } = await patcher.patch(inputBuffer, patchOptions);\n\n // Determine output path\n const outputPath =\n options.output || inputPath.replace(/\\.zip$/i, '-patched.zip');\n\n spinner.text = 'Writing output file...';\n writeFileSync(outputPath, buffer);\n\n spinner.succeed(chalk.green('Patching complete!'));\n\n // Display results\n console.log('');\n console.log(chalk.blue('Format detected:'), result.formatDisplayName);\n console.log(chalk.blue('Remote domain:'), validatedConfig.remoteDomain);\n console.log('');\n\n if (result.filesModified.length > 0) {\n console.log(chalk.blue('Files modified:'));\n result.filesModified.forEach((f) => console.log(` ${chalk.gray('•')} ${f}`));\n }\n\n if (result.filesAdded.length > 0) {\n console.log(chalk.blue('Files added:'));\n result.filesAdded.forEach((f) => console.log(` ${chalk.gray('•')} ${f}`));\n }\n\n if (result.warnings.length > 0) {\n console.log('');\n console.log(chalk.yellow('Warnings:'));\n result.warnings.forEach((w) => console.log(` ${chalk.yellow('!')} ${w}`));\n }\n\n console.log('');\n console.log(chalk.green('Output:'), outputPath);\n } catch (error) {\n spinner.fail(chalk.red('Patching failed'));\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n\nprogram\n .command('init')\n .description('Create a sample configuration file')\n .option('-o, --output <path>', 'Output path (default: ./patch-adams.config.ts)')\n .action((options) => {\n const outputPath = resolve(options.output || './patch-adams.config.ts');\n\n if (existsSync(outputPath)) {\n console.log(\n chalk.yellow(`Configuration file already exists: ${outputPath}`)\n );\n console.log(chalk.yellow('Use --output to specify a different path'));\n process.exit(1);\n }\n\n const template = generateConfigTemplate();\n writeFileSync(outputPath, template);\n console.log(chalk.green(`Configuration file created: ${outputPath}`));\n console.log('');\n console.log('Next steps:');\n console.log(` 1. Edit ${chalk.cyan(basename(outputPath))} to configure your settings`);\n console.log(` 2. Run ${chalk.cyan('patch-adams patch <input.zip>')} to patch a course`);\n });\n\nprogram\n .command('info <input>')\n .description('Display information about a Rise course package')\n .action(async (input: string) => {\n const spinner = ora('Analyzing package...').start();\n\n try {\n const inputPath = resolve(input);\n if (!existsSync(inputPath)) {\n throw new Error(`Input file not found: ${inputPath}`);\n }\n\n const inputBuffer = readFileSync(inputPath);\n const AdmZip = (await import('adm-zip')).default;\n const zip = new AdmZip(inputBuffer);\n\n const { FormatDetector } = await import('./detectors/index.js');\n const detector = new FormatDetector();\n const format = detector.detect(zip);\n const formatName = detector.getFormatDisplayName(format);\n\n spinner.succeed('Package analyzed');\n\n console.log('');\n console.log(chalk.blue('File:'), inputPath);\n console.log(chalk.blue('Format:'), formatName);\n console.log('');\n\n // Check for key files\n const keyFiles = [\n 'scormcontent/index.html',\n 'scormdriver/indexAPI.html',\n 'imsmanifest.xml',\n 'cmi5.xml',\n 'tincan.xml',\n ];\n\n console.log(chalk.blue('Key files:'));\n for (const file of keyFiles) {\n const exists = zip.getEntry(file) !== null;\n const icon = exists ? chalk.green('✓') : chalk.gray('○');\n console.log(` ${icon} ${file}`);\n }\n\n // Count total files\n const entries = zip.getEntries();\n console.log('');\n console.log(chalk.blue('Total files:'), entries.length);\n } catch (error) {\n spinner.fail(chalk.red('Analysis failed'));\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../src/detectors/format-detector.ts","../src/detectors/index.ts","../src/templates/css-before.ts","../src/templates/css-after.ts","../src/templates/js-before.ts","../src/templates/js-after.ts","../src/patcher/html-injector.ts","../src/patcher/manifest-updater.ts","../src/patcher/index.ts","../src/config/schema.ts","../src/config/defaults.ts","../src/config/loader.ts","../src/cli.ts"],"names":["XMLParser","XMLBuilder","AdmZip","resolve","archiver","PassThrough","z","existsSync","extname","readFileSync","pathToFileURL","Command","ora","writeFileSync","chalk","basename","FormatDetector"],"mappings":"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","file":"cli.cjs","sourcesContent":["import type AdmZip from 'adm-zip';\n\n/**\n * Supported package formats\n */\nexport type PackageFormat =\n | 'scorm12'\n | 'scorm2004-3'\n | 'scorm2004-4'\n | 'cmi5'\n | 'xapi'\n | 'aicc'\n | 'unknown';\n\n/**\n * Detect the package format by examining manifest files\n */\nexport class FormatDetector {\n /**\n * Detect the package format from a ZIP file\n */\n detect(zip: AdmZip): PackageFormat {\n // Check for cmi5.xml first (most specific)\n if (zip.getEntry('cmi5.xml')) {\n return 'cmi5';\n }\n\n // Check for xAPI (tincan.xml)\n if (zip.getEntry('tincan.xml')) {\n return 'xapi';\n }\n\n // Check for SCORM via imsmanifest.xml\n const manifest = zip.getEntry('imsmanifest.xml');\n if (manifest) {\n const content = manifest.getData().toString('utf-8');\n return this.detectScormVersion(content);\n }\n\n // Check for AICC-specific files\n if (this.hasAiccFiles(zip)) {\n return 'aicc';\n }\n\n return 'unknown';\n }\n\n /**\n * Detect SCORM version from manifest content\n */\n private detectScormVersion(content: string): PackageFormat {\n // Check for SCORM 2004 4th Edition\n if (content.includes('4th Edition') || content.includes('CAM 1.4')) {\n return 'scorm2004-4';\n }\n\n // Check for SCORM 2004 3rd Edition\n if (\n content.includes('3rd Edition') ||\n content.includes('2004 3rd') ||\n content.includes('adlcp_v1p3')\n ) {\n return 'scorm2004-3';\n }\n\n // Check for SCORM 2004 (generic)\n if (content.includes('2004') && content.includes('adlseq')) {\n return 'scorm2004-3'; // Default to 3rd edition for generic 2004\n }\n\n // Check for SCORM 1.2\n if (\n content.includes('1.2') ||\n content.includes('adlcp_rootv1p2') ||\n content.includes('imscp_rootv1p1p2')\n ) {\n return 'scorm12';\n }\n\n // Check for AICC markers in manifest\n if (content.toLowerCase().includes('aicc')) {\n return 'aicc';\n }\n\n // Default to SCORM 1.2 if we have a manifest but can't determine version\n return 'scorm12';\n }\n\n /**\n * Check for AICC-specific files\n */\n private hasAiccFiles(zip: AdmZip): boolean {\n const aiccExtensions = ['.crs', '.au', '.des', '.cst'];\n const entries = zip.getEntries();\n\n for (const entry of entries) {\n const name = entry.entryName.toLowerCase();\n if (aiccExtensions.some((ext) => name.endsWith(ext))) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get a human-readable format name\n */\n getFormatDisplayName(format: PackageFormat): string {\n const names: Record<PackageFormat, string> = {\n scorm12: 'SCORM 1.2',\n 'scorm2004-3': 'SCORM 2004 3rd Edition',\n 'scorm2004-4': 'SCORM 2004 4th Edition',\n cmi5: 'cmi5',\n xapi: 'xAPI (Tin Can)',\n aicc: 'AICC',\n unknown: 'Unknown',\n };\n\n return names[format];\n }\n}\n","export { FormatDetector, type PackageFormat } from './format-detector.js';\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface CssBeforeOptions {\n remoteUrl: string;\n localPath: string;\n htmlClass: string;\n loadingClass: string;\n}\n\n/**\n * Generate the blocking CSS loader for the \"before\" slot\n * This loads at the start of <head> and blocks rendering until loaded\n *\n * Strategy:\n * 1. First, inline the critical CSS to hide content immediately\n * 2. Then load the remote CSS synchronously (or local fallback)\n */\nexport function generateCssBeforeLoader(options: CssBeforeOptions): string {\n const { remoteUrl, localPath, htmlClass, loadingClass } = options;\n\n return `<!-- === PATCH-ADAMS: CSS BEFORE (blocking) === -->\n<style data-pa=\"css-before-critical\">\n/* Critical: Hide content until ready */\nhtml.${htmlClass}.${loadingClass} body {\n visibility: hidden !important;\n}\n</style>\n<script data-pa=\"css-before-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n\n function loadCSSSync(url) {\n var link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n link.setAttribute('data-pa', 'css-before');\n document.head.appendChild(link);\n return link;\n }\n\n // Try remote first\n var link = loadCSSSync(REMOTE_URL);\n\n link.onerror = function() {\n console.warn('[Patch-Adams] CSS before failed to load from remote, using local fallback');\n document.head.removeChild(link);\n loadCSSSync(LOCAL_PATH);\n };\n\n link.onload = function() {\n console.log('[Patch-Adams] CSS before loaded from remote:', REMOTE_URL);\n };\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildCssBeforeOptions(config: PatchAdamsConfig): CssBeforeOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.cssBefore.filename}`,\n localPath: `${config.localFolders.css}/${config.cssBefore.filename}`,\n htmlClass: config.htmlClass,\n loadingClass: config.loadingClass,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface CssAfterOptions {\n remoteUrl: string;\n localPath: string;\n timeout: number;\n}\n\n/**\n * Generate the async CSS loader for the \"after\" slot\n * This loads at the end of <head> with remote-first, local fallback\n */\nexport function generateCssAfterLoader(options: CssAfterOptions): string {\n const { remoteUrl, localPath, timeout } = options;\n\n return `<!-- === PATCH-ADAMS: CSS AFTER (async with fallback) === -->\n<script data-pa=\"css-after-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n var TIMEOUT = ${timeout};\n\n function loadCSS(url, onSuccess, onError) {\n var link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n link.setAttribute('data-pa', 'css-after');\n\n link.onload = function() {\n if (onSuccess) onSuccess();\n };\n\n link.onerror = function() {\n if (onError) onError();\n };\n\n document.head.appendChild(link);\n return link;\n }\n\n function loadCSSWithFallback() {\n var loaded = false;\n var timeoutId;\n\n // Try remote first\n var remoteLink = loadCSS(\n REMOTE_URL,\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n console.log('[Patch-Adams] CSS after loaded from remote:', REMOTE_URL);\n },\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n loadLocalFallback();\n }\n );\n\n // Timeout fallback\n timeoutId = setTimeout(function() {\n if (loaded) return;\n loaded = true;\n console.warn('[Patch-Adams] CSS after timed out, using local fallback');\n if (remoteLink.parentNode) {\n document.head.removeChild(remoteLink);\n }\n loadLocalFallback();\n }, TIMEOUT);\n }\n\n function loadLocalFallback() {\n loadCSS(\n LOCAL_PATH,\n function() {\n console.log('[Patch-Adams] CSS after loaded from local fallback:', LOCAL_PATH);\n },\n function() {\n console.error('[Patch-Adams] CSS after failed to load from both remote and local');\n }\n );\n }\n\n // Execute immediately\n loadCSSWithFallback();\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildCssAfterOptions(config: PatchAdamsConfig): CssAfterOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.cssAfter.filename}`,\n localPath: `${config.localFolders.css}/${config.cssAfter.filename}`,\n timeout: config.cssAfter.timeout,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface JsBeforeOptions {\n remoteUrl: string;\n localPath: string;\n htmlClass: string;\n loadingClass: string;\n}\n\n/**\n * Generate the blocking JS loader for the \"before\" slot\n * This loads at the start of <head> and blocks rendering until loaded\n *\n * Use this for:\n * - Setting up global variables\n * - Intercepting Rise APIs before they initialize\n * - Preparing the environment\n */\nexport function generateJsBeforeLoader(options: JsBeforeOptions): string {\n const { remoteUrl, localPath, htmlClass, loadingClass } = options;\n\n return `<!-- === PATCH-ADAMS: JS BEFORE (blocking) === -->\n<script data-pa=\"js-before-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n\n // Initialize Patch-Adams global namespace\n window.PatchAdams = window.PatchAdams || {\n version: '1.0.0',\n htmlClass: '${htmlClass}',\n loadingClass: '${loadingClass}',\n loaded: {\n cssBefore: false,\n cssAfter: false,\n jsBefore: false,\n jsAfter: false\n }\n };\n\n function loadJSSync(url) {\n var script = document.createElement('script');\n script.src = url;\n script.setAttribute('data-pa', 'js-before');\n // Note: For truly blocking behavior, we use document.write\n // but that's fragile. Instead we'll handle errors gracefully.\n document.head.appendChild(script);\n return script;\n }\n\n // Try remote first\n var script = loadJSSync(REMOTE_URL);\n\n script.onerror = function() {\n console.warn('[Patch-Adams] JS before failed to load from remote, using local fallback');\n document.head.removeChild(script);\n var fallback = loadJSSync(LOCAL_PATH);\n fallback.onload = function() {\n window.PatchAdams.loaded.jsBefore = true;\n console.log('[Patch-Adams] JS before loaded from local fallback:', LOCAL_PATH);\n };\n fallback.onerror = function() {\n console.error('[Patch-Adams] JS before failed to load from both remote and local');\n };\n };\n\n script.onload = function() {\n window.PatchAdams.loaded.jsBefore = true;\n console.log('[Patch-Adams] JS before loaded from remote:', REMOTE_URL);\n };\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildJsBeforeOptions(config: PatchAdamsConfig): JsBeforeOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.jsBefore.filename}`,\n localPath: `${config.localFolders.js}/${config.jsBefore.filename}`,\n htmlClass: config.htmlClass,\n loadingClass: config.loadingClass,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\n\nexport interface JsAfterOptions {\n remoteUrl: string;\n localPath: string;\n timeout: number;\n loadingClass: string;\n}\n\n/**\n * Generate the async JS loader for the \"after\" slot\n * This loads at the end of <body> with remote-first, local fallback\n *\n * This script is responsible for:\n * - Loading your override JS after Rise has initialized\n * - Removing the loading class to reveal the content\n */\nexport function generateJsAfterLoader(options: JsAfterOptions): string {\n const { remoteUrl, localPath, timeout, loadingClass } = options;\n\n return `<!-- === PATCH-ADAMS: JS AFTER (async with fallback) === -->\n<script data-pa=\"js-after-loader\">\n(function() {\n 'use strict';\n var REMOTE_URL = \"${remoteUrl}\";\n var LOCAL_PATH = \"${localPath}\";\n var TIMEOUT = ${timeout};\n var LOADING_CLASS = \"${loadingClass}\";\n\n function loadJS(url, onSuccess, onError) {\n var script = document.createElement('script');\n script.src = url;\n script.async = true;\n script.setAttribute('data-pa', 'js-after');\n\n script.onload = function() {\n if (onSuccess) onSuccess();\n };\n\n script.onerror = function() {\n if (onError) onError();\n };\n\n document.body.appendChild(script);\n return script;\n }\n\n function removeLoadingClass() {\n document.documentElement.classList.remove(LOADING_CLASS);\n if (window.PatchAdams) {\n window.PatchAdams.loaded.jsAfter = true;\n }\n console.log('[Patch-Adams] Loading complete, content revealed');\n }\n\n function loadJSWithFallback() {\n var loaded = false;\n var timeoutId;\n\n // Try remote first\n var remoteScript = loadJS(\n REMOTE_URL,\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n console.log('[Patch-Adams] JS after loaded from remote:', REMOTE_URL);\n // Give the script a moment to execute, then remove loading class\n setTimeout(removeLoadingClass, 50);\n },\n function() {\n if (loaded) return;\n loaded = true;\n clearTimeout(timeoutId);\n loadLocalFallback();\n }\n );\n\n // Timeout fallback\n timeoutId = setTimeout(function() {\n if (loaded) return;\n loaded = true;\n console.warn('[Patch-Adams] JS after timed out, using local fallback');\n if (remoteScript.parentNode) {\n document.body.removeChild(remoteScript);\n }\n loadLocalFallback();\n }, TIMEOUT);\n }\n\n function loadLocalFallback() {\n loadJS(\n LOCAL_PATH,\n function() {\n console.log('[Patch-Adams] JS after loaded from local fallback:', LOCAL_PATH);\n setTimeout(removeLoadingClass, 50);\n },\n function() {\n console.error('[Patch-Adams] JS after failed to load from both remote and local');\n // Still remove loading class so content is visible even if JS fails\n removeLoadingClass();\n }\n );\n }\n\n // Execute after DOM is ready to ensure Rise has loaded\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', function() {\n // Small delay to ensure Rise has initialized\n setTimeout(loadJSWithFallback, 100);\n });\n } else {\n // DOM is already ready\n setTimeout(loadJSWithFallback, 100);\n }\n})();\n</script>`;\n}\n\n/**\n * Build options from config\n */\nexport function buildJsAfterOptions(config: PatchAdamsConfig): JsAfterOptions {\n return {\n remoteUrl: `${config.remoteDomain}/${config.jsAfter.filename}`,\n localPath: `${config.localFolders.js}/${config.jsAfter.filename}`,\n timeout: config.jsAfter.timeout,\n loadingClass: config.loadingClass,\n };\n}\n","import type { PatchAdamsConfig } from '../config/schema.js';\nimport {\n generateCssBeforeLoader,\n buildCssBeforeOptions,\n generateCssAfterLoader,\n buildCssAfterOptions,\n generateJsBeforeLoader,\n buildJsBeforeOptions,\n generateJsAfterLoader,\n buildJsAfterOptions,\n} from '../templates/index.js';\n\n/**\n * HTML Injector for patching Rise course index.html\n *\n * Injection points:\n * 1. CSS Before - Start of <head> (blocking)\n * 2. JS Before - Start of <head>, after CSS Before (blocking)\n * 3. CSS After - End of <head> (async with fallback)\n * 4. JS After - End of <body>, after __loadEntry() (async with fallback)\n *\n * Also adds classes to <html> tag for specificity\n */\nexport class HtmlInjector {\n private config: PatchAdamsConfig;\n\n constructor(config: PatchAdamsConfig) {\n this.config = config;\n }\n\n /**\n * Inject all loaders into HTML\n */\n inject(html: string): string {\n let result = html;\n\n // Step 1: Add classes to <html> tag\n result = this.addHtmlClasses(result);\n\n // Step 2: Inject CSS Before at start of <head>\n if (this.config.cssBefore.enabled) {\n result = this.injectCssBefore(result);\n }\n\n // Step 3: Inject JS Before at start of <head> (after CSS Before)\n if (this.config.jsBefore.enabled) {\n result = this.injectJsBefore(result);\n }\n\n // Step 4: Inject CSS After at end of <head>\n if (this.config.cssAfter.enabled) {\n result = this.injectCssAfter(result);\n }\n\n // Step 5: Inject JS After at end of <body>\n if (this.config.jsAfter.enabled) {\n result = this.injectJsAfter(result);\n }\n\n return result;\n }\n\n /**\n * Add pa-patched and pa-loading classes to <html> tag\n */\n private addHtmlClasses(html: string): string {\n const { htmlClass, loadingClass } = this.config;\n const classes = `${htmlClass} ${loadingClass}`;\n\n // Match <html> tag with or without existing class attribute\n const htmlTagPattern = /<html([^>]*)>/i;\n const match = html.match(htmlTagPattern);\n\n if (!match) {\n return html;\n }\n\n const attributes = match[1];\n\n // Check if class attribute exists\n if (/class\\s*=\\s*[\"'][^\"']*[\"']/i.test(attributes)) {\n // Append to existing class\n return html.replace(\n htmlTagPattern,\n (_match: string, attrs: string) => {\n const newAttrs = attrs.replace(\n /class\\s*=\\s*[\"']([^\"']*)[\"']/i,\n (_fullMatch: string, existingClasses: string) => `class=\"${existingClasses} ${classes}\"`\n );\n return `<html${newAttrs}>`;\n }\n );\n } else {\n // Add class attribute\n return html.replace(htmlTagPattern, `<html${attributes} class=\"${classes}\">`);\n }\n }\n\n /**\n * Inject CSS Before loader at start of <head>\n */\n private injectCssBefore(html: string): string {\n const options = buildCssBeforeOptions(this.config);\n const loader = generateCssBeforeLoader(options);\n\n // Insert right after <head> tag\n return html.replace(/<head([^>]*)>/i, `<head$1>\\n${loader}`);\n }\n\n /**\n * Inject JS Before loader at start of <head> (after CSS Before if present)\n */\n private injectJsBefore(html: string): string {\n const options = buildJsBeforeOptions(this.config);\n const loader = generateJsBeforeLoader(options);\n\n // Look for the CSS Before marker to insert after it\n const cssBeforeMarker = '<!-- === PATCH-ADAMS: CSS BEFORE';\n if (html.includes(cssBeforeMarker)) {\n // Find end of CSS Before block and insert after\n const cssBeforeEndPattern = /<\\/script>\\s*(?=\\n|<)/;\n const cssBeforeStart = html.indexOf(cssBeforeMarker);\n const afterCssBefore = html.substring(cssBeforeStart);\n const endMatch = afterCssBefore.match(cssBeforeEndPattern);\n\n if (endMatch && endMatch.index !== undefined) {\n const insertPos = cssBeforeStart + endMatch.index + endMatch[0].length;\n return html.slice(0, insertPos) + '\\n' + loader + html.slice(insertPos);\n }\n }\n\n // Fallback: insert after <head> tag\n return html.replace(/<head([^>]*)>/i, `<head$1>\\n${loader}`);\n }\n\n /**\n * Inject CSS After loader at end of <head>\n */\n private injectCssAfter(html: string): string {\n const options = buildCssAfterOptions(this.config);\n const loader = generateCssAfterLoader(options);\n\n // Insert before </head>\n return html.replace(/<\\/head>/i, `${loader}\\n</head>`);\n }\n\n /**\n * Inject JS After loader at end of <body> (after __loadEntry)\n */\n private injectJsAfter(html: string): string {\n const options = buildJsAfterOptions(this.config);\n const loader = generateJsAfterLoader(options);\n\n // Try to find __loadEntry() call and insert after it\n const loadEntryPattern = /(<script>__loadEntry\\(\\)<\\/script>)/i;\n if (loadEntryPattern.test(html)) {\n return html.replace(loadEntryPattern, `$1\\n${loader}`);\n }\n\n // Fallback: insert before </body>\n return html.replace(/<\\/body>/i, `${loader}\\n</body>`);\n }\n}\n","import type AdmZip from 'adm-zip';\nimport { XMLParser, XMLBuilder } from 'fast-xml-parser';\nimport type { PatchAdamsConfig } from '../config/schema.js';\nimport type { PackageFormat } from '../detectors/format-detector.js';\n\nexport interface ManifestPaths {\n cssBefore?: string;\n cssAfter?: string;\n jsBefore?: string;\n jsAfter?: string;\n}\n\n/**\n * Update manifest files to include injected assets\n * This ensures SCORM compliance for strict LMS systems\n */\nexport class ManifestUpdater {\n private config: PatchAdamsConfig;\n private parser: XMLParser;\n private builder: XMLBuilder;\n\n constructor(config: PatchAdamsConfig) {\n this.config = config;\n this.parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n preserveOrder: false,\n parseAttributeValue: false,\n trimValues: true,\n });\n this.builder = new XMLBuilder({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n format: true,\n indentBy: ' ',\n suppressEmptyNode: true,\n });\n }\n\n /**\n * Update manifest files based on package format\n */\n update(zip: AdmZip, format: PackageFormat, paths: ManifestPaths): string[] {\n const modified: string[] = [];\n\n switch (format) {\n case 'scorm12':\n case 'scorm2004-3':\n case 'scorm2004-4':\n modified.push(...this.updateImsManifest(zip, paths));\n break;\n\n case 'cmi5':\n // cmi5 packages also typically have an imsmanifest.xml\n modified.push(...this.updateImsManifest(zip, paths));\n break;\n\n case 'xapi':\n // xAPI/tincan.xml doesn't have file manifests\n // Files are loaded directly by HTML\n break;\n\n case 'aicc':\n // AICC may have imsmanifest.xml\n const aiccManifest = zip.getEntry('imsmanifest.xml');\n if (aiccManifest) {\n modified.push(...this.updateImsManifest(zip, paths));\n }\n break;\n }\n\n return modified;\n }\n\n /**\n * Update imsmanifest.xml to include new file references\n */\n private updateImsManifest(zip: AdmZip, paths: ManifestPaths): string[] {\n const entry = zip.getEntry('imsmanifest.xml');\n if (!entry) {\n return [];\n }\n\n try {\n const xmlContent = entry.getData().toString('utf-8');\n const parsed = this.parser.parse(xmlContent);\n\n // Find resources and add file entries\n this.addFilesToManifest(parsed, paths);\n\n // Rebuild XML with declaration\n const xmlDeclaration = this.extractXmlDeclaration(xmlContent);\n let builtXml = this.builder.build(parsed);\n\n // Strip any XML declaration that the builder may have added\n // to avoid duplicate declarations\n builtXml = builtXml.replace(/<\\?xml[^?]*\\?>\\s*/g, '');\n\n const updatedXml = xmlDeclaration + builtXml;\n\n zip.updateFile('imsmanifest.xml', Buffer.from(updatedXml, 'utf-8'));\n\n return ['imsmanifest.xml'];\n } catch (error) {\n console.error('[Patch-Adams] Failed to update imsmanifest.xml:', error);\n return [];\n }\n }\n\n /**\n * Extract XML declaration from original content\n */\n private extractXmlDeclaration(xml: string): string {\n const match = xml.match(/<\\?xml[^?]*\\?>/);\n return match ? match[0] + '\\n' : '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n }\n\n /**\n * Add file entries to the manifest\n */\n private addFilesToManifest(parsed: Record<string, unknown>, paths: ManifestPaths): void {\n // Navigate to find the resource element\n const manifest = parsed.manifest as Record<string, unknown> | undefined;\n if (!manifest) return;\n\n const resources = manifest.resources as Record<string, unknown> | undefined;\n if (!resources) return;\n\n let resource = resources.resource as Record<string, unknown> | Record<string, unknown>[] | undefined;\n if (!resource) return;\n\n // Handle single resource or array\n if (Array.isArray(resource)) {\n resource = resource[0];\n }\n\n // Ensure file array exists\n if (!resource.file) {\n resource.file = [];\n }\n\n let files = resource.file as Array<Record<string, string>>;\n if (!Array.isArray(files)) {\n files = [files as unknown as Record<string, string>];\n resource.file = files;\n }\n\n // Add new file entries\n const filesToAdd = [\n paths.cssBefore,\n paths.cssAfter,\n paths.jsBefore,\n paths.jsAfter,\n ].filter(Boolean) as string[];\n\n for (const filePath of filesToAdd) {\n // Check if already exists\n const exists = files.some((f) => f['@_href'] === filePath);\n if (!exists) {\n files.push({ '@_href': filePath });\n }\n }\n }\n\n /**\n * Get the file paths that will be added to the package\n */\n getFilePaths(): ManifestPaths {\n const paths: ManifestPaths = {};\n\n if (this.config.cssBefore.enabled) {\n paths.cssBefore = `scormcontent/${this.config.localFolders.css}/${this.config.cssBefore.filename}`;\n }\n\n if (this.config.cssAfter.enabled) {\n paths.cssAfter = `scormcontent/${this.config.localFolders.css}/${this.config.cssAfter.filename}`;\n }\n\n if (this.config.jsBefore.enabled) {\n paths.jsBefore = `scormcontent/${this.config.localFolders.js}/${this.config.jsBefore.filename}`;\n }\n\n if (this.config.jsAfter.enabled) {\n paths.jsAfter = `scormcontent/${this.config.localFolders.js}/${this.config.jsAfter.filename}`;\n }\n\n return paths;\n }\n}\n","import AdmZip from 'adm-zip';\nimport archiver from 'archiver';\nimport { PassThrough } from 'stream';\nimport type { PatchAdamsConfig } from '../config/schema.js';\nimport { HtmlInjector } from './html-injector.js';\nimport { ManifestUpdater } from './manifest-updater.js';\nimport { FormatDetector, type PackageFormat } from '../detectors/format-detector.js';\n\n/**\n * Result of a patch operation\n */\nexport interface PatchResult {\n success: boolean;\n format: PackageFormat;\n formatDisplayName: string;\n filesModified: string[];\n filesAdded: string[];\n errors: string[];\n warnings: string[];\n}\n\n/**\n * Options for patching\n */\nexport interface PatchOptions {\n /** Content for CSS before (local fallback) */\n cssBeforeContent?: string;\n /** Content for CSS after (local fallback) */\n cssAfterContent?: string;\n /** Content for JS before (local fallback) */\n jsBeforeContent?: string;\n /** Content for JS after (local fallback) */\n jsAfterContent?: string;\n}\n\n/**\n * Default fallback file contents\n */\nconst DEFAULT_CSS_BEFORE = `/* Patch-Adams: CSS Before (blocking)\n * This file loads at the start of <head> and blocks rendering.\n * Use it to hide content and prevent flash of unstyled content.\n *\n * Example:\n * html.pa-patched.pa-loading body {\n * visibility: hidden !important;\n * }\n */\n`;\n\nconst DEFAULT_CSS_AFTER = `/* Patch-Adams: CSS After (async)\n * This file loads at the end of <head> with remote fallback.\n * Use it for style overrides that take precedence over Rise styles.\n *\n * Example:\n * html.pa-patched .blocks-text {\n * font-family: 'Your Font', sans-serif !important;\n * }\n */\n`;\n\nconst DEFAULT_JS_BEFORE = `// Patch-Adams: JS Before (blocking)\n// This file loads at the start of <head> and blocks rendering.\n// Use it for setup, API interception, and preparing globals.\n//\n// Example:\n// window.PatchAdams.customConfig = {\n// theme: 'dark',\n// analytics: true\n// };\n\nconsole.log('[Patch-Adams] JS Before loaded');\n`;\n\nconst DEFAULT_JS_AFTER = `// Patch-Adams: JS After (async)\n// This file loads at the end of <body> with remote fallback.\n// Use it for DOM manipulation after Rise has initialized.\n//\n// IMPORTANT: This script should NOT remove the loading class.\n// The loader script handles that automatically after this script loads.\n//\n// Example:\n// document.querySelectorAll('.blocks-text').forEach(function(el) {\n// // Your modifications here\n// });\n\nconsole.log('[Patch-Adams] JS After loaded');\n`;\n\n/**\n * Main Patcher class for patching Rise course packages\n */\nexport class Patcher {\n private config: PatchAdamsConfig;\n private htmlInjector: HtmlInjector;\n private manifestUpdater: ManifestUpdater;\n private formatDetector: FormatDetector;\n\n constructor(config: PatchAdamsConfig) {\n this.config = config;\n this.htmlInjector = new HtmlInjector(config);\n this.manifestUpdater = new ManifestUpdater(config);\n this.formatDetector = new FormatDetector();\n }\n\n /**\n * Patch a Rise course ZIP file\n * @param inputBuffer - Input ZIP file as Buffer\n * @param options - Additional patching options\n * @returns Patched ZIP file as Buffer and result details\n */\n async patch(\n inputBuffer: Buffer,\n options: PatchOptions = {}\n ): Promise<{ buffer: Buffer; result: PatchResult }> {\n const result: PatchResult = {\n success: false,\n format: 'unknown',\n formatDisplayName: 'Unknown',\n filesModified: [],\n filesAdded: [],\n errors: [],\n warnings: [],\n };\n\n try {\n // 1. Open ZIP with adm-zip for reading\n const zip = new AdmZip(inputBuffer);\n\n // 2. Detect package format\n result.format = this.formatDetector.detect(zip);\n result.formatDisplayName = this.formatDetector.getFormatDisplayName(result.format);\n\n if (result.format === 'unknown') {\n result.warnings.push('Could not determine package format, proceeding anyway');\n }\n\n // 3. Find and patch index.html\n const indexHtmlEntry = zip.getEntry('scormcontent/index.html');\n if (!indexHtmlEntry) {\n throw new Error('Could not find scormcontent/index.html in package. Is this a valid Rise export?');\n }\n\n const originalHtml = indexHtmlEntry.getData().toString('utf-8');\n const patchedHtml = this.htmlInjector.inject(originalHtml);\n zip.updateFile('scormcontent/index.html', Buffer.from(patchedHtml, 'utf-8'));\n result.filesModified.push('scormcontent/index.html');\n\n // 4. Add local fallback files\n const addedFiles = this.addFallbackFiles(zip, options);\n result.filesAdded.push(...addedFiles);\n\n // 5. Update manifest files\n if (this.config.updateManifests) {\n const manifestPaths = this.manifestUpdater.getFilePaths();\n const modifiedManifests = this.manifestUpdater.update(zip, result.format, manifestPaths);\n result.filesModified.push(...modifiedManifests);\n }\n\n // 6. Write output using adm-zip's toBuffer\n const outputBuffer = zip.toBuffer();\n\n result.success = true;\n return { buffer: outputBuffer, result };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n result.errors.push(message);\n throw error;\n }\n }\n\n /**\n * Write ZIP using archiver for better compatibility\n * adm-zip's toBuffer() produces ZIPs that some parsers don't handle well.\n * archiver produces more standard ZIP output.\n */\n private writeZipWithArchiver(admZip: AdmZip): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n const archive = archiver('zip', {\n zlib: { level: 9 }, // Maximum compression\n });\n\n const chunks: Buffer[] = [];\n const passThrough = new PassThrough();\n\n passThrough.on('data', (chunk: Buffer) => chunks.push(chunk));\n passThrough.on('end', () => resolve(Buffer.concat(chunks)));\n passThrough.on('error', reject);\n\n archive.on('error', reject);\n archive.pipe(passThrough);\n\n const entries = admZip.getEntries();\n\n for (const entry of entries) {\n const entryName = entry.entryName;\n const mtime = entry.header.time ? new Date(entry.header.time) : new Date();\n\n if (entry.isDirectory) {\n // archiver handles directories automatically when adding files\n continue;\n }\n\n const entryData = entry.getData();\n\n // Determine if we should store or compress based on original\n const store = entry.header.method === 0;\n\n archive.append(entryData, {\n name: entryName,\n date: mtime,\n store: store,\n });\n }\n\n archive.finalize();\n });\n }\n\n /**\n * Add local fallback files to the ZIP\n */\n private addFallbackFiles(zip: AdmZip, options: PatchOptions): string[] {\n const added: string[] = [];\n const cssFolder = `scormcontent/${this.config.localFolders.css}`;\n const jsFolder = `scormcontent/${this.config.localFolders.js}`;\n\n // CSS Before\n if (this.config.cssBefore.enabled) {\n const path = `${cssFolder}/${this.config.cssBefore.filename}`;\n const content = options.cssBeforeContent ?? DEFAULT_CSS_BEFORE;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n // CSS After\n if (this.config.cssAfter.enabled) {\n const path = `${cssFolder}/${this.config.cssAfter.filename}`;\n const content = options.cssAfterContent ?? DEFAULT_CSS_AFTER;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n // JS Before\n if (this.config.jsBefore.enabled) {\n const path = `${jsFolder}/${this.config.jsBefore.filename}`;\n const content = options.jsBeforeContent ?? DEFAULT_JS_BEFORE;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n // JS After\n if (this.config.jsAfter.enabled) {\n const path = `${jsFolder}/${this.config.jsAfter.filename}`;\n const content = options.jsAfterContent ?? DEFAULT_JS_AFTER;\n zip.addFile(path, Buffer.from(content, 'utf-8'));\n added.push(path);\n }\n\n return added;\n }\n\n /**\n * Get the current configuration\n */\n getConfig(): PatchAdamsConfig {\n return this.config;\n }\n\n /**\n * Convenience method to patch a buffer and return only the patched buffer.\n * Used by package-uploader integration.\n * @param buffer - Input ZIP file as Buffer\n * @returns Patched ZIP file as Buffer\n */\n async patchBuffer(buffer: Buffer): Promise<Buffer> {\n console.log(`[Patcher] patchBuffer called with ${buffer.length} bytes`);\n const { buffer: patchedBuffer, result } = await this.patch(buffer);\n console.log(`[Patcher] Patch result:`, JSON.stringify(result, null, 2));\n console.log(`[Patcher] Returning ${patchedBuffer.length} bytes`);\n return patchedBuffer;\n }\n}\n\nexport { HtmlInjector } from './html-injector.js';\nexport { ManifestUpdater, type ManifestPaths } from './manifest-updater.js';\n","import { z } from 'zod';\n\n/**\n * Configuration for a blocking asset (CSS before, JS before)\n * These load synchronously and block page rendering\n */\nexport const BlockingAssetConfigSchema = z.object({\n /** Filename for the asset */\n filename: z.string().min(1),\n /** Whether this asset is enabled */\n enabled: z.boolean().default(true),\n});\n\n/**\n * Configuration for an async asset (CSS after, JS after)\n * These load asynchronously with remote-first, local fallback\n */\nexport const AsyncAssetConfigSchema = z.object({\n /** Filename for the asset */\n filename: z.string().min(1),\n /** Whether this asset is enabled */\n enabled: z.boolean().default(true),\n /** Timeout in milliseconds for remote loading before falling back to local */\n timeout: z.number().min(1000).max(30000).default(5000),\n});\n\n/**\n * Local folder configuration for fallback files\n */\nexport const LocalFoldersConfigSchema = z.object({\n /** Folder name for CSS files within scormcontent */\n css: z.string().default('css'),\n /** Folder name for JS files within scormcontent */\n js: z.string().default('js'),\n});\n\n/**\n * Main configuration schema for Patch-Adams\n */\nexport const PatchAdamsConfigSchema = z.object({\n /** Remote domain for assets (e.g., \"https://cdn.example.com/rise-overrides\") */\n remoteDomain: z.string().url(),\n\n /** CSS class added to <html> tag for specificity (default: \"pa-patched\") */\n htmlClass: z.string().default('pa-patched'),\n\n /** CSS class added during loading, removed when ready (default: \"pa-loading\") */\n loadingClass: z.string().default('pa-loading'),\n\n /** CSS loaded at start of <head> - blocking, prevents FOUC */\n cssBefore: BlockingAssetConfigSchema.default({\n filename: 'before.css',\n enabled: true,\n }),\n\n /** CSS loaded at end of <head> - async with fallback, for overrides */\n cssAfter: AsyncAssetConfigSchema.default({\n filename: 'after.css',\n enabled: true,\n timeout: 5000,\n }),\n\n /** JS loaded at start of <head> - blocking, for setup/interception */\n jsBefore: BlockingAssetConfigSchema.default({\n filename: 'before.js',\n enabled: true,\n }),\n\n /** JS loaded at end of <body> - async with fallback, removes loading class */\n jsAfter: AsyncAssetConfigSchema.default({\n filename: 'after.js',\n enabled: true,\n timeout: 5000,\n }),\n\n /** Local folder names for fallback files */\n localFolders: LocalFoldersConfigSchema.default({}),\n\n /** Whether to update manifest files (imsmanifest.xml, etc.) for SCORM compliance */\n updateManifests: z.boolean().default(true),\n});\n\nexport type PatchAdamsConfig = z.infer<typeof PatchAdamsConfigSchema>;\nexport type BlockingAssetConfig = z.infer<typeof BlockingAssetConfigSchema>;\nexport type AsyncAssetConfig = z.infer<typeof AsyncAssetConfigSchema>;\nexport type LocalFoldersConfig = z.infer<typeof LocalFoldersConfigSchema>;\n","import type { PatchAdamsConfig } from './schema.js';\n\n/**\n * Default configuration values for Patch-Adams\n */\nexport const defaultConfig: PatchAdamsConfig = {\n remoteDomain: 'https://cdn.example.com/rise-overrides',\n\n htmlClass: 'pa-patched',\n loadingClass: 'pa-loading',\n\n cssBefore: {\n filename: 'before.css',\n enabled: true,\n },\n\n cssAfter: {\n filename: 'after.css',\n enabled: true,\n timeout: 5000,\n },\n\n jsBefore: {\n filename: 'before.js',\n enabled: true,\n },\n\n jsAfter: {\n filename: 'after.js',\n enabled: true,\n timeout: 5000,\n },\n\n localFolders: {\n css: 'css',\n js: 'js',\n },\n\n updateManifests: true,\n};\n","import { readFileSync, existsSync } from 'fs';\nimport { resolve, extname } from 'path';\nimport { pathToFileURL } from 'url';\nimport { PatchAdamsConfigSchema, type PatchAdamsConfig } from './schema.js';\nimport { defaultConfig } from './defaults.js';\n\n/**\n * Load and validate a Patch-Adams configuration file\n * Supports .ts, .js, and .json files\n */\nexport async function loadConfig(configPath: string): Promise<PatchAdamsConfig> {\n const absolutePath = resolve(configPath);\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Configuration file not found: ${absolutePath}`);\n }\n\n const ext = extname(absolutePath).toLowerCase();\n let rawConfig: unknown;\n\n if (ext === '.json') {\n const content = readFileSync(absolutePath, 'utf-8');\n rawConfig = JSON.parse(content);\n } else if (ext === '.ts' || ext === '.js' || ext === '.mjs') {\n // Dynamic import for ESM modules\n const fileUrl = pathToFileURL(absolutePath).href;\n const module = await import(fileUrl);\n rawConfig = module.default ?? module;\n } else {\n throw new Error(`Unsupported config file extension: ${ext}. Use .ts, .js, .mjs, or .json`);\n }\n\n // Validate and return\n const validated = PatchAdamsConfigSchema.parse(rawConfig);\n return validated;\n}\n\n/**\n * Create a merged config with defaults\n */\nexport function mergeWithDefaults(partial: Partial<PatchAdamsConfig>): PatchAdamsConfig {\n return PatchAdamsConfigSchema.parse({\n ...defaultConfig,\n ...partial,\n });\n}\n\n/**\n * Generate a configuration file template\n */\nexport function generateConfigTemplate(): string {\n return `import type { PatchAdamsConfig } from '@patch-adams/core';\n\nconst config: PatchAdamsConfig = {\n // Remote domain where your CSS/JS files are hosted\n remoteDomain: 'https://cdn.example.com/rise-overrides',\n\n // HTML classes for specificity and loading state\n htmlClass: 'pa-patched', // Always present on <html>\n loadingClass: 'pa-loading', // Removed when assets are loaded\n\n // CSS loaded at start of <head> - BLOCKING\n // Use this to hide content and prevent flash of unstyled content\n cssBefore: {\n filename: 'before.css',\n enabled: true,\n },\n\n // CSS loaded at end of <head> - ASYNC with fallback\n // Use this for style overrides\n cssAfter: {\n filename: 'after.css',\n enabled: true,\n timeout: 5000, // ms before falling back to local\n },\n\n // JS loaded at start of <head> - BLOCKING\n // Use this for setup, API interception, globals\n jsBefore: {\n filename: 'before.js',\n enabled: true,\n },\n\n // JS loaded at end of <body> - ASYNC with fallback\n // Use this for DOM manipulation after Rise loads\n // This should remove the loadingClass when done\n jsAfter: {\n filename: 'after.js',\n enabled: true,\n timeout: 5000, // ms before falling back to local\n },\n\n // Folder names for local fallback files within scormcontent/\n localFolders: {\n css: 'css',\n js: 'js',\n },\n\n // Update manifest files for SCORM compliance\n updateManifests: true,\n};\n\nexport default config;\n`;\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { resolve, basename } from 'path';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { Patcher } from './patcher/index.js';\nimport { loadConfig, generateConfigTemplate, mergeWithDefaults } from './config/index.js';\nimport { PatchAdamsConfigSchema } from './config/schema.js';\n\nconst program = new Command();\n\nprogram\n .name('patch-adams')\n .description('Patch Rise course packages to inject remote CSS/JS with local fallback')\n .version('1.0.0');\n\nprogram\n .command('patch <input>')\n .description('Patch a Rise course ZIP file')\n .option('-o, --output <path>', 'Output file path (default: <input>-patched.zip)')\n .option('-c, --config <path>', 'Configuration file path (default: ./patch-adams.config.ts)')\n .option('--css-before <path>', 'Local CSS file for \"before\" fallback')\n .option('--css-after <path>', 'Local CSS file for \"after\" fallback')\n .option('--js-before <path>', 'Local JS file for \"before\" fallback')\n .option('--js-after <path>', 'Local JS file for \"after\" fallback')\n .option('--no-manifest', 'Skip updating manifest files')\n .action(async (input: string, options) => {\n const spinner = ora('Loading configuration...').start();\n\n try {\n // Load config\n let config;\n const configPath = options.config || './patch-adams.config.ts';\n\n if (existsSync(resolve(configPath))) {\n config = await loadConfig(configPath);\n spinner.text = 'Configuration loaded';\n } else {\n spinner.text = 'No config file found, using defaults';\n config = mergeWithDefaults({});\n }\n\n // Override manifest update setting\n if (options.manifest === false) {\n config = { ...config, updateManifests: false };\n }\n\n // Validate config\n const validatedConfig = PatchAdamsConfigSchema.parse(config);\n\n spinner.text = 'Reading input file...';\n\n // Read input ZIP\n const inputPath = resolve(input);\n if (!existsSync(inputPath)) {\n throw new Error(`Input file not found: ${inputPath}`);\n }\n const inputBuffer = readFileSync(inputPath);\n\n // Read optional CSS/JS files\n const patchOptions: {\n cssBeforeContent?: string;\n cssAfterContent?: string;\n jsBeforeContent?: string;\n jsAfterContent?: string;\n } = {};\n\n if (options.cssBefore) {\n patchOptions.cssBeforeContent = readFileSync(resolve(options.cssBefore), 'utf-8');\n }\n\n if (options.cssAfter) {\n patchOptions.cssAfterContent = readFileSync(resolve(options.cssAfter), 'utf-8');\n }\n\n if (options.jsBefore) {\n patchOptions.jsBeforeContent = readFileSync(resolve(options.jsBefore), 'utf-8');\n }\n\n if (options.jsAfter) {\n patchOptions.jsAfterContent = readFileSync(resolve(options.jsAfter), 'utf-8');\n }\n\n spinner.text = 'Patching package...';\n\n // Patch\n const patcher = new Patcher(validatedConfig);\n const { buffer, result } = await patcher.patch(inputBuffer, patchOptions);\n\n // Determine output path\n const outputPath =\n options.output || inputPath.replace(/\\.zip$/i, '-patched.zip');\n\n spinner.text = 'Writing output file...';\n writeFileSync(outputPath, buffer);\n\n spinner.succeed(chalk.green('Patching complete!'));\n\n // Display results\n console.log('');\n console.log(chalk.blue('Format detected:'), result.formatDisplayName);\n console.log(chalk.blue('Remote domain:'), validatedConfig.remoteDomain);\n console.log('');\n\n if (result.filesModified.length > 0) {\n console.log(chalk.blue('Files modified:'));\n result.filesModified.forEach((f) => console.log(` ${chalk.gray('•')} ${f}`));\n }\n\n if (result.filesAdded.length > 0) {\n console.log(chalk.blue('Files added:'));\n result.filesAdded.forEach((f) => console.log(` ${chalk.gray('•')} ${f}`));\n }\n\n if (result.warnings.length > 0) {\n console.log('');\n console.log(chalk.yellow('Warnings:'));\n result.warnings.forEach((w) => console.log(` ${chalk.yellow('!')} ${w}`));\n }\n\n console.log('');\n console.log(chalk.green('Output:'), outputPath);\n } catch (error) {\n spinner.fail(chalk.red('Patching failed'));\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n\nprogram\n .command('init')\n .description('Create a sample configuration file')\n .option('-o, --output <path>', 'Output path (default: ./patch-adams.config.ts)')\n .action((options) => {\n const outputPath = resolve(options.output || './patch-adams.config.ts');\n\n if (existsSync(outputPath)) {\n console.log(\n chalk.yellow(`Configuration file already exists: ${outputPath}`)\n );\n console.log(chalk.yellow('Use --output to specify a different path'));\n process.exit(1);\n }\n\n const template = generateConfigTemplate();\n writeFileSync(outputPath, template);\n console.log(chalk.green(`Configuration file created: ${outputPath}`));\n console.log('');\n console.log('Next steps:');\n console.log(` 1. Edit ${chalk.cyan(basename(outputPath))} to configure your settings`);\n console.log(` 2. Run ${chalk.cyan('patch-adams patch <input.zip>')} to patch a course`);\n });\n\nprogram\n .command('info <input>')\n .description('Display information about a Rise course package')\n .action(async (input: string) => {\n const spinner = ora('Analyzing package...').start();\n\n try {\n const inputPath = resolve(input);\n if (!existsSync(inputPath)) {\n throw new Error(`Input file not found: ${inputPath}`);\n }\n\n const inputBuffer = readFileSync(inputPath);\n const AdmZip = (await import('adm-zip')).default;\n const zip = new AdmZip(inputBuffer);\n\n const { FormatDetector } = await import('./detectors/index.js');\n const detector = new FormatDetector();\n const format = detector.detect(zip);\n const formatName = detector.getFormatDisplayName(format);\n\n spinner.succeed('Package analyzed');\n\n console.log('');\n console.log(chalk.blue('File:'), inputPath);\n console.log(chalk.blue('Format:'), formatName);\n console.log('');\n\n // Check for key files\n const keyFiles = [\n 'scormcontent/index.html',\n 'scormdriver/indexAPI.html',\n 'imsmanifest.xml',\n 'cmi5.xml',\n 'tincan.xml',\n ];\n\n console.log(chalk.blue('Key files:'));\n for (const file of keyFiles) {\n const exists = zip.getEntry(file) !== null;\n const icon = exists ? chalk.green('✓') : chalk.gray('○');\n console.log(` ${icon} ${file}`);\n }\n\n // Count total files\n const entries = zip.getEntries();\n console.log('');\n console.log(chalk.blue('Total files:'), entries.length);\n } catch (error) {\n spinner.fail(chalk.red('Analysis failed'));\n console.error(\n chalk.red(error instanceof Error ? error.message : String(error))\n );\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
package/dist/cli.js CHANGED
@@ -5,7 +5,8 @@ import { resolve, basename, extname } from 'path';
5
5
  import chalk from 'chalk';
6
6
  import ora from 'ora';
7
7
  import AdmZip from 'adm-zip';
8
- import yazl from 'yazl';
8
+ import archiver from 'archiver';
9
+ import { PassThrough } from 'stream';
9
10
  import { XMLParser, XMLBuilder } from 'fast-xml-parser';
10
11
  import { z } from 'zod';
11
12
  import { pathToFileURL } from 'url';
@@ -586,7 +587,9 @@ var ManifestUpdater = class {
586
587
  const parsed = this.parser.parse(xmlContent);
587
588
  this.addFilesToManifest(parsed, paths);
588
589
  const xmlDeclaration = this.extractXmlDeclaration(xmlContent);
589
- const updatedXml = xmlDeclaration + this.builder.build(parsed);
590
+ let builtXml = this.builder.build(parsed);
591
+ builtXml = builtXml.replace(/<\?xml[^?]*\?>\s*/g, "");
592
+ const updatedXml = xmlDeclaration + builtXml;
590
593
  zip.updateFile("imsmanifest.xml", Buffer.from(updatedXml, "utf-8"));
591
594
  return ["imsmanifest.xml"];
592
595
  } catch (error) {
@@ -753,7 +756,7 @@ var Patcher = class {
753
756
  const modifiedManifests = this.manifestUpdater.update(zip, result.format, manifestPaths);
754
757
  result.filesModified.push(...modifiedManifests);
755
758
  }
756
- const outputBuffer = await this.writeZipWithYazl(zip);
759
+ const outputBuffer = zip.toBuffer();
757
760
  result.success = true;
758
761
  return { buffer: outputBuffer, result };
759
762
  } catch (error) {
@@ -763,32 +766,39 @@ var Patcher = class {
763
766
  }
764
767
  }
765
768
  /**
766
- * Write ZIP using yazl for better compatibility
767
- * adm-zip's toBuffer() sets the data descriptor bit flag which causes
768
- * issues with some ZIP parsers. yazl produces standard ZIP output.
769
+ * Write ZIP using archiver for better compatibility
770
+ * adm-zip's toBuffer() produces ZIPs that some parsers don't handle well.
771
+ * archiver produces more standard ZIP output.
769
772
  */
770
- writeZipWithYazl(admZip) {
773
+ writeZipWithArchiver(admZip) {
771
774
  return new Promise((resolve3, reject) => {
772
- const zipFile = new yazl.ZipFile();
775
+ const archive = archiver("zip", {
776
+ zlib: { level: 9 }
777
+ // Maximum compression
778
+ });
779
+ const chunks = [];
780
+ const passThrough = new PassThrough();
781
+ passThrough.on("data", (chunk) => chunks.push(chunk));
782
+ passThrough.on("end", () => resolve3(Buffer.concat(chunks)));
783
+ passThrough.on("error", reject);
784
+ archive.on("error", reject);
785
+ archive.pipe(passThrough);
773
786
  const entries = admZip.getEntries();
774
787
  for (const entry of entries) {
775
788
  const entryName = entry.entryName;
776
789
  const mtime = entry.header.time ? new Date(entry.header.time) : /* @__PURE__ */ new Date();
777
790
  if (entry.isDirectory) {
778
- zipFile.addEmptyDirectory(entryName, { mtime });
779
791
  continue;
780
792
  }
781
793
  const entryData = entry.getData();
782
- zipFile.addBuffer(entryData, entryName, {
783
- compress: true,
784
- mtime
794
+ const store = entry.header.method === 0;
795
+ archive.append(entryData, {
796
+ name: entryName,
797
+ date: mtime,
798
+ store
785
799
  });
786
800
  }
787
- const chunks = [];
788
- zipFile.outputStream.on("data", (chunk) => chunks.push(chunk));
789
- zipFile.outputStream.on("end", () => resolve3(Buffer.concat(chunks)));
790
- zipFile.outputStream.on("error", reject);
791
- zipFile.end();
801
+ archive.finalize();
792
802
  });
793
803
  }
794
804
  /**