@layerzerolabs/deterministic-zip 0.2.108

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.
@@ -0,0 +1,15 @@
1
+  WARN  Issue while reading "/home/runner/work/monorepo-internal/monorepo-internal/.npmrc". Failed to replace env in config: ${NPM_TOKEN}
2
+
3
+ > @layerzerolabs/deterministic-zip@0.0.0 build /home/runner/work/monorepo-internal/monorepo-internal/tools/vm-utils/common/deterministic-zip
4
+ > tsup
5
+
6
+ CLI Building entry: src/index.ts
7
+ CLI Using tsconfig: tsconfig.json
8
+ CLI tsup v8.5.1
9
+ CLI Using tsup config: /home/runner/work/monorepo-internal/monorepo-internal/tools/vm-utils/common/deterministic-zip/tsup.config.ts
10
+ CLI Target: ES2023
11
+ CLI Cleaning output folder
12
+ ESM Build start
13
+ ESM dist/index.js 2.09 KB
14
+ ESM dist/index.js.map 5.65 KB
15
+ ESM ⚡️ Build success in 99ms
@@ -0,0 +1,8 @@
1
+
2
+ > @layerzerolabs/deterministic-zip@0.0.0 lint /home/runner/work/monorepo-internal/monorepo-internal/tools/vm-utils/common/deterministic-zip
3
+ > eslint . --max-warnings 0 || (eslint . --fix --max-warnings 0 && false)
4
+
5
+ (node:83387) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/runner/work/monorepo-internal/monorepo-internal/eslint.config.js?mtime=1782249605033 is not specified and it doesn't parse as CommonJS.
6
+ Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
7
+ To eliminate this warning, add "type": "module" to /home/runner/work/monorepo-internal/monorepo-internal/package.json.
8
+ (Use `node --trace-warnings ...` to show where the warning was created)
@@ -0,0 +1,17 @@
1
+
2
+ > @layerzerolabs/deterministic-zip@0.0.0 test /home/runner/work/monorepo-internal/monorepo-internal/tools/vm-utils/common/deterministic-zip
3
+ > vitest --run --pass-with-no-tests --typecheck
4
+
5
+ Testing types with tsc and vue-tsc is an experimental feature.
6
+ Breaking changes might not follow SemVer, please pin Vitest's version when using it.
7
+
8
+  RUN  v3.2.4 /home/runner/work/monorepo-internal/monorepo-internal/tools/vm-utils/common/deterministic-zip
9
+
10
+ ✓ tests/deterministicZip.test.ts (3 tests) 23ms
11
+
12
+  Test Files  1 passed (1)
13
+  Tests  3 passed (3)
14
+ Type Errors  no errors
15
+  Start at  21:23:46
16
+  Duration  443ms (transform 58ms, setup 0ms, collect 62ms, tests 23ms, environment 0ms, prepare 110ms)
17
+
@@ -0,0 +1,25 @@
1
+ /** fflate deflate compression levels (0 = store, 9 = max). */
2
+ export type DeflateLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
3
+ export interface ZipDirectoryOptions {
4
+ level?: DeflateLevel;
5
+ mtime?: Date;
6
+ }
7
+ /**
8
+ * Fixed modification time stamped onto every archive entry.
9
+ *
10
+ * fflate derives each ZIP entry's DOS timestamp from the local-time components
11
+ * of the supplied `mtime` (getFullYear/getMonth/getHours/...). Constructing the
12
+ * date from local fields, rather than a UTC instant, makes those components
13
+ * identical on every machine regardless of the builder's timezone.
14
+ */
15
+ export declare const DEFAULT_DETERMINISTIC_ZIP_MTIME: Date;
16
+ /**
17
+ * Build a byte-deterministic ZIP of `sourceDir`.
18
+ *
19
+ * Entry order, timestamps, and compression implementation are pinned so output
20
+ * bytes remain stable across machines.
21
+ */
22
+ export declare const zipDirectoryToUint8Array: (sourceDir: string, options?: ZipDirectoryOptions) => Promise<Uint8Array>;
23
+ export declare const zipDirectoryToBuffer: (sourceDir: string, options?: ZipDirectoryOptions) => Promise<Buffer>;
24
+ export declare const zipDirectoryToBase64: (sourceDir: string, options?: ZipDirectoryOptions) => Promise<string>;
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,8DAA8D;AAC9D,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAChC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,IAAI,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,MAAiC,CAAC;AA+B9E;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GACjC,WAAW,MAAM,EACjB,UAAU,mBAAmB,KAC9B,OAAO,CAAC,UAAU,CAepB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC7B,WAAW,MAAM,EACjB,UAAU,mBAAmB,KAC9B,OAAO,CAAC,MAAM,CAAoE,CAAC;AAEtF,eAAO,MAAM,oBAAoB,GAC7B,WAAW,MAAM,EACjB,UAAU,mBAAmB,KAC9B,OAAO,CAAC,MAAM,CAAwE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ import { zipSync } from 'fflate';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var DEFAULT_DETERMINISTIC_ZIP_MTIME = new Date(2026, 5, 15, 0, 0, 0);
8
+ var collectSortedEntries = /* @__PURE__ */ __name(async (root) => {
9
+ const zipEntries = [];
10
+ const walk = /* @__PURE__ */ __name(async (rel) => {
11
+ const entries = await fs.readdir(path.join(root, rel), {
12
+ withFileTypes: true
13
+ });
14
+ for (const entry of entries) {
15
+ const childRel = rel ? path.posix.join(rel, entry.name) : entry.name;
16
+ if (entry.isDirectory()) {
17
+ zipEntries.push({
18
+ relPath: `${childRel}/`,
19
+ isDirectory: true
20
+ });
21
+ await walk(childRel);
22
+ } else if (entry.isFile()) {
23
+ zipEntries.push({
24
+ relPath: childRel,
25
+ isDirectory: false
26
+ });
27
+ }
28
+ }
29
+ }, "walk");
30
+ await walk("");
31
+ return zipEntries.sort((a, b) => a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0);
32
+ }, "collectSortedEntries");
33
+ var zipDirectoryToUint8Array = /* @__PURE__ */ __name(async (sourceDir, options) => {
34
+ const entries = await collectSortedEntries(sourceDir);
35
+ const fileMap = {};
36
+ for (const entry of entries) {
37
+ fileMap[entry.relPath] = entry.isDirectory ? new Uint8Array(0) : new Uint8Array(await fs.readFile(path.join(sourceDir, entry.relPath)));
38
+ }
39
+ return zipSync(fileMap, {
40
+ level: options?.level ?? 6,
41
+ mtime: options?.mtime ?? DEFAULT_DETERMINISTIC_ZIP_MTIME
42
+ });
43
+ }, "zipDirectoryToUint8Array");
44
+ var zipDirectoryToBuffer = /* @__PURE__ */ __name(async (sourceDir, options) => Buffer.from(await zipDirectoryToUint8Array(sourceDir, options)), "zipDirectoryToBuffer");
45
+ var zipDirectoryToBase64 = /* @__PURE__ */ __name(async (sourceDir, options) => (await zipDirectoryToBuffer(sourceDir, options)).toString("base64"), "zipDirectoryToBase64");
46
+
47
+ export { DEFAULT_DETERMINISTIC_ZIP_MTIME, zipDirectoryToBase64, zipDirectoryToBuffer, zipDirectoryToUint8Array };
48
+ //# sourceMappingURL=index.js.map
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["DEFAULT_DETERMINISTIC_ZIP_MTIME","Date","collectSortedEntries","root","zipEntries","walk","rel","entries","fs","readdir","path","join","withFileTypes","entry","childRel","posix","name","isDirectory","push","relPath","isFile","sort","a","b","zipDirectoryToUint8Array","sourceDir","options","fileMap","Uint8Array","readFile","zipSync","level","mtime","zipDirectoryToBuffer","Buffer","from","zipDirectoryToBase64","toString"],"mappings":";;;;;;AAoBO,IAAMA,+BAAAA,GAAkC,IAAIC,IAAAA,CAAK,IAAA,EAAM,GAAG,EAAA,EAAI,CAAA,EAAG,GAAG,CAAA;AAW3E,IAAMC,oBAAAA,iCAA8BC,IAAAA,KAAAA;AAChC,EAAA,MAAMC,aAAsC,EAAA;AAE5C,EAAA,MAAMC,IAAAA,iCAAcC,GAAAA,KAAAA;AAChB,IAAA,MAAMC,OAAAA,GAAU,MAAMC,EAAAA,CAAGC,OAAAA,CAAQC,KAAKC,IAAAA,CAAKR,IAAAA,EAAMG,GAAAA,CAAAA,EAAM;MAAEM,aAAAA,EAAe;KAAK,CAAA;AAC7E,IAAA,KAAA,MAAWC,SAASN,OAAAA,EAAS;AACzB,MAAA,MAAMO,QAAAA,GAAWR,MAAMI,IAAAA,CAAKK,KAAAA,CAAMJ,KAAKL,GAAAA,EAAKO,KAAAA,CAAMG,IAAI,CAAA,GAAIH,KAAAA,CAAMG,IAAAA;AAChE,MAAA,IAAIH,KAAAA,CAAMI,aAAW,EAAI;AACrBb,QAAAA,UAAAA,CAAWc,IAAAA,CAAK;AAAEC,UAAAA,OAAAA,EAAS,GAAGL,QAAAA,CAAAA,CAAAA,CAAAA;UAAaG,WAAAA,EAAa;SAAK,CAAA;AAC7D,QAAA,MAAMZ,KAAKS,QAAAA,CAAAA;MACf,CAAA,MAAA,IAAWD,KAAAA,CAAMO,QAAM,EAAI;AACvBhB,QAAAA,UAAAA,CAAWc,IAAAA,CAAK;UAAEC,OAAAA,EAASL,QAAAA;UAAUG,WAAAA,EAAa;SAAM,CAAA;AAC5D,MAAA;AACJ,IAAA;EACJ,CAAA,EAXa,MAAA,CAAA;AAab,EAAA,MAAMZ,KAAK,EAAA,CAAA;AACX,EAAA,OAAOD,UAAAA,CAAWiB,IAAAA,CAAK,CAACC,CAAAA,EAAGC,MAAOD,CAAAA,CAAEH,OAAAA,GAAUI,CAAAA,CAAEJ,OAAAA,GAAU,KAAKG,CAAAA,CAAEH,OAAAA,GAAUI,CAAAA,CAAEJ,OAAAA,GAAU,IAAI,CAAA,CAAA;AAC/F,CAAA,EAlB6B,sBAAA,CAAA;AA0BtB,IAAMK,wBAAAA,mBAA2B,MAAA,CAAA,OACpCC,SAAAA,EACAC,OAAAA,KAAAA;AAEA,EAAA,MAAMnB,OAAAA,GAAU,MAAML,oBAAAA,CAAqBuB,SAAAA,CAAAA;AAC3C,EAAA,MAAME,UAAoB,EAAC;AAE3B,EAAA,KAAA,MAAWd,SAASN,OAAAA,EAAS;AAEzBoB,IAAAA,OAAAA,CAAQd,KAAAA,CAAMM,OAAO,CAAA,GAAIN,KAAAA,CAAMI,cACzB,IAAIW,UAAAA,CAAW,CAAA,CAAA,GACf,IAAIA,WAAW,MAAMpB,EAAAA,CAAGqB,SAASnB,IAAAA,CAAKC,IAAAA,CAAKc,WAAWZ,KAAAA,CAAMM,OAAO,CAAA,CAAA,CAAA;AAC7E,EAAA;AAEA,EAAA,OAAOW,QAAQH,OAAAA,EAAS;AACpBI,IAAAA,KAAAA,EAAOL,SAASK,KAAAA,IAAS,CAAA;AACzBC,IAAAA,KAAAA,EAAON,SAASM,KAAAA,IAAShC;GAC7B,CAAA;AACJ,CAAA,EAlBwC,0BAAA;AAoBjC,IAAMiC,oBAAAA,mBAAuB,MAAA,CAAA,OAChCR,SAAAA,EACAC,OAAAA,KACkBQ,MAAAA,CAAOC,IAAAA,CAAK,MAAMX,wBAAAA,CAAyBC,SAAAA,EAAWC,OAAAA,CAAAA,CAAAA,EAHxC,sBAAA;AAK7B,IAAMU,oBAAAA,mBAAuB,MAAA,CAAA,OAChCX,SAAAA,EACAC,OAAAA,KAAAA,CACmB,MAAMO,oBAAAA,CAAqBR,SAAAA,EAAWC,OAAAA,CAAAA,EAAUW,QAAAA,CAAS,QAAA,CAAA,EAH5C,sBAAA","file":"index.js","sourcesContent":["import { type Zippable, zipSync } from 'fflate';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\n/** fflate deflate compression levels (0 = store, 9 = max). */\nexport type DeflateLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\n\nexport interface ZipDirectoryOptions {\n level?: DeflateLevel;\n mtime?: Date;\n}\n\n/**\n * Fixed modification time stamped onto every archive entry.\n *\n * fflate derives each ZIP entry's DOS timestamp from the local-time components\n * of the supplied `mtime` (getFullYear/getMonth/getHours/...). Constructing the\n * date from local fields, rather than a UTC instant, makes those components\n * identical on every machine regardless of the builder's timezone.\n */\nexport const DEFAULT_DETERMINISTIC_ZIP_MTIME = new Date(2026, 5, 15, 0, 0, 0);\n\ntype DeterministicZipEntry = { relPath: string; isDirectory: boolean };\n\n/**\n * Recursively collect every file and directory under `root`, sorted by\n * POSIX-relative path (UTF-16 code unit order).\n *\n * The explicit sort is required for reproducibility because filesystem\n * `readdir` order is not stable across operating systems.\n */\nconst collectSortedEntries = async (root: string): Promise<DeterministicZipEntry[]> => {\n const zipEntries: DeterministicZipEntry[] = [];\n\n const walk = async (rel: string): Promise<void> => {\n const entries = await fs.readdir(path.join(root, rel), { withFileTypes: true });\n for (const entry of entries) {\n const childRel = rel ? path.posix.join(rel, entry.name) : entry.name;\n if (entry.isDirectory()) {\n zipEntries.push({ relPath: `${childRel}/`, isDirectory: true });\n await walk(childRel);\n } else if (entry.isFile()) {\n zipEntries.push({ relPath: childRel, isDirectory: false });\n }\n }\n };\n\n await walk('');\n return zipEntries.sort((a, b) => (a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0));\n};\n\n/**\n * Build a byte-deterministic ZIP of `sourceDir`.\n *\n * Entry order, timestamps, and compression implementation are pinned so output\n * bytes remain stable across machines.\n */\nexport const zipDirectoryToUint8Array = async (\n sourceDir: string,\n options?: ZipDirectoryOptions,\n): Promise<Uint8Array> => {\n const entries = await collectSortedEntries(sourceDir);\n const fileMap: Zippable = {};\n\n for (const entry of entries) {\n // A directory is a zero-length entry whose name already ends in `/`.\n fileMap[entry.relPath] = entry.isDirectory\n ? new Uint8Array(0)\n : new Uint8Array(await fs.readFile(path.join(sourceDir, entry.relPath)));\n }\n\n return zipSync(fileMap, {\n level: options?.level ?? 6,\n mtime: options?.mtime ?? DEFAULT_DETERMINISTIC_ZIP_MTIME,\n });\n};\n\nexport const zipDirectoryToBuffer = async (\n sourceDir: string,\n options?: ZipDirectoryOptions,\n): Promise<Buffer> => Buffer.from(await zipDirectoryToUint8Array(sourceDir, options));\n\nexport const zipDirectoryToBase64 = async (\n sourceDir: string,\n options?: ZipDirectoryOptions,\n): Promise<string> => (await zipDirectoryToBuffer(sourceDir, options)).toString('base64');\n"]}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@layerzerolabs/deterministic-zip",
3
+ "version": "0.2.108",
4
+ "private": false,
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "main": "./dist/index.js",
13
+ "module": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "dependencies": {
16
+ "fflate": "^0.8.3"
17
+ },
18
+ "devDependencies": {
19
+ "tsup": "^8.4.0",
20
+ "vitest": "^3.2.4",
21
+ "@layerzerolabs/tsup-configuration": "0.2.108",
22
+ "@layerzerolabs/typescript-configuration": "0.2.108"
23
+ },
24
+ "publishConfig": {
25
+ "access": "restricted",
26
+ "registry": "https://registry.npmjs.org/"
27
+ },
28
+ "scripts": {
29
+ "build": "tsup",
30
+ "lint": "eslint . --max-warnings 0 || (eslint . --fix --max-warnings 0 && false)",
31
+ "test": "vitest --run --pass-with-no-tests --typecheck"
32
+ }
33
+ }
package/src/index.ts ADDED
@@ -0,0 +1,86 @@
1
+ import { type Zippable, zipSync } from 'fflate';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+
5
+ /** fflate deflate compression levels (0 = store, 9 = max). */
6
+ export type DeflateLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
7
+
8
+ export interface ZipDirectoryOptions {
9
+ level?: DeflateLevel;
10
+ mtime?: Date;
11
+ }
12
+
13
+ /**
14
+ * Fixed modification time stamped onto every archive entry.
15
+ *
16
+ * fflate derives each ZIP entry's DOS timestamp from the local-time components
17
+ * of the supplied `mtime` (getFullYear/getMonth/getHours/...). Constructing the
18
+ * date from local fields, rather than a UTC instant, makes those components
19
+ * identical on every machine regardless of the builder's timezone.
20
+ */
21
+ export const DEFAULT_DETERMINISTIC_ZIP_MTIME = new Date(2026, 5, 15, 0, 0, 0);
22
+
23
+ type DeterministicZipEntry = { relPath: string; isDirectory: boolean };
24
+
25
+ /**
26
+ * Recursively collect every file and directory under `root`, sorted by
27
+ * POSIX-relative path (UTF-16 code unit order).
28
+ *
29
+ * The explicit sort is required for reproducibility because filesystem
30
+ * `readdir` order is not stable across operating systems.
31
+ */
32
+ const collectSortedEntries = async (root: string): Promise<DeterministicZipEntry[]> => {
33
+ const zipEntries: DeterministicZipEntry[] = [];
34
+
35
+ const walk = async (rel: string): Promise<void> => {
36
+ const entries = await fs.readdir(path.join(root, rel), { withFileTypes: true });
37
+ for (const entry of entries) {
38
+ const childRel = rel ? path.posix.join(rel, entry.name) : entry.name;
39
+ if (entry.isDirectory()) {
40
+ zipEntries.push({ relPath: `${childRel}/`, isDirectory: true });
41
+ await walk(childRel);
42
+ } else if (entry.isFile()) {
43
+ zipEntries.push({ relPath: childRel, isDirectory: false });
44
+ }
45
+ }
46
+ };
47
+
48
+ await walk('');
49
+ return zipEntries.sort((a, b) => (a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0));
50
+ };
51
+
52
+ /**
53
+ * Build a byte-deterministic ZIP of `sourceDir`.
54
+ *
55
+ * Entry order, timestamps, and compression implementation are pinned so output
56
+ * bytes remain stable across machines.
57
+ */
58
+ export const zipDirectoryToUint8Array = async (
59
+ sourceDir: string,
60
+ options?: ZipDirectoryOptions,
61
+ ): Promise<Uint8Array> => {
62
+ const entries = await collectSortedEntries(sourceDir);
63
+ const fileMap: Zippable = {};
64
+
65
+ for (const entry of entries) {
66
+ // A directory is a zero-length entry whose name already ends in `/`.
67
+ fileMap[entry.relPath] = entry.isDirectory
68
+ ? new Uint8Array(0)
69
+ : new Uint8Array(await fs.readFile(path.join(sourceDir, entry.relPath)));
70
+ }
71
+
72
+ return zipSync(fileMap, {
73
+ level: options?.level ?? 6,
74
+ mtime: options?.mtime ?? DEFAULT_DETERMINISTIC_ZIP_MTIME,
75
+ });
76
+ };
77
+
78
+ export const zipDirectoryToBuffer = async (
79
+ sourceDir: string,
80
+ options?: ZipDirectoryOptions,
81
+ ): Promise<Buffer> => Buffer.from(await zipDirectoryToUint8Array(sourceDir, options));
82
+
83
+ export const zipDirectoryToBase64 = async (
84
+ sourceDir: string,
85
+ options?: ZipDirectoryOptions,
86
+ ): Promise<string> => (await zipDirectoryToBuffer(sourceDir, options)).toString('base64');
@@ -0,0 +1,59 @@
1
+ import { unzipSync } from 'fflate';
2
+ import fs from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import path from 'node:path';
5
+ import { afterEach, describe, expect, it } from 'vitest';
6
+
7
+ import { zipDirectoryToBase64, zipDirectoryToUint8Array } from '../src';
8
+
9
+ const testDirs: string[] = [];
10
+
11
+ const createTempDir = async () => {
12
+ const dir = await fs.mkdtemp(path.join(tmpdir(), 'deterministic-zip-'));
13
+ testDirs.push(dir);
14
+ return dir;
15
+ };
16
+
17
+ afterEach(async () => {
18
+ await Promise.all(
19
+ testDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })),
20
+ );
21
+ });
22
+
23
+ describe('deterministic zip', () => {
24
+ it('sorts entries and keeps empty directories', async () => {
25
+ const dir = await createTempDir();
26
+ await fs.mkdir(path.join(dir, 'z-empty'), { recursive: true });
27
+ await fs.mkdir(path.join(dir, 'a'), { recursive: true });
28
+ await fs.writeFile(path.join(dir, 'b.txt'), 'b');
29
+ await fs.writeFile(path.join(dir, 'a', 'c.txt'), 'c');
30
+
31
+ const unzipped = unzipSync(await zipDirectoryToUint8Array(dir));
32
+
33
+ expect(Object.keys(unzipped)).toEqual(['a/', 'a/c.txt', 'b.txt', 'z-empty/']);
34
+ });
35
+
36
+ it('produces stable bytes for equivalent directories', async () => {
37
+ const first = await createTempDir();
38
+ const second = await createTempDir();
39
+
40
+ await fs.mkdir(path.join(first, 'sources'), { recursive: true });
41
+ await fs.writeFile(path.join(first, 'sources', 'module.move'), 'module first::m {}');
42
+ await fs.writeFile(path.join(first, 'Move.toml'), '[package]\nname = "first"\n');
43
+
44
+ await fs.writeFile(path.join(second, 'Move.toml'), '[package]\nname = "first"\n');
45
+ await fs.mkdir(path.join(second, 'sources'), { recursive: true });
46
+ await fs.writeFile(path.join(second, 'sources', 'module.move'), 'module first::m {}');
47
+
48
+ expect(await zipDirectoryToBase64(first)).toEqual(await zipDirectoryToBase64(second));
49
+ });
50
+
51
+ it('writes directory entries into the zip', async () => {
52
+ const dir = await createTempDir();
53
+ await fs.mkdir(path.join(dir, 'empty'), { recursive: true });
54
+
55
+ const unzipped = unzipSync(await zipDirectoryToUint8Array(dir));
56
+
57
+ expect(Object.keys(unzipped)).toEqual(['empty/']);
58
+ });
59
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "extends": "@layerzerolabs/typescript-configuration/tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./dist",
6
+ "lib": ["ESNext"],
7
+ "strictPropertyInitialization": false,
8
+ "noUnusedLocals": false,
9
+ "noUnusedParameters": false,
10
+ "jsx": "react-jsx"
11
+ },
12
+ "exclude": [
13
+ "node_modules",
14
+ "**/__mocks__/*",
15
+ "**/__tests__/*",
16
+ "**/*.spec.ts",
17
+ "**/*.test.ts",
18
+ "dist"
19
+ ],
20
+ "include": ["src/**/*"]
21
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ import { createPackageTsupConfig } from '@layerzerolabs/tsup-configuration';
4
+
5
+ export default defineConfig(({ watch }) => ({
6
+ ...createPackageTsupConfig(),
7
+ clean: !watch,
8
+ }));