@locuschain/lib 0.1.38 → 0.1.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/accounts/index.amd.js +306 -0
  2. package/dist/accounts/index.cjs.cjs +2 -2
  3. package/dist/accounts/index.esm.js +2 -2
  4. package/dist/autogen/index.amd.js +151 -0
  5. package/dist/autogen/index.cjs.cjs +2 -2
  6. package/dist/autogen/index.esm.js +2 -2
  7. package/dist/chunks/account-BSrvZ7S8.js +77 -0
  8. package/dist/chunks/address-class-Dp7aNQb2.js +18 -0
  9. package/dist/chunks/base-B_kRRfsf.js +27 -0
  10. package/dist/chunks/debugWalletActions-BDz-h2tl.js +993 -0
  11. package/dist/chunks/{keystore-BFVSylSw.js → keystore-B86UzV8A.js} +1 -1
  12. package/dist/chunks/{keystore-BbK5pVrh.cjs → keystore-BUskzeOs.cjs} +1 -1
  13. package/dist/chunks/keystore-y1JlFTKh.js +143 -0
  14. package/dist/chunks/lclib-Bv86gksL.js +3861 -0
  15. package/dist/chunks/{lclib-C2eG5HzD.js → lclib-j2x9RvDY.js} +55 -32
  16. package/dist/chunks/{lclib-DuoOR0-Q.cjs → lclib-rGyKpClJ.cjs} +64 -41
  17. package/dist/chunks/rpc-C4n7t9y0.js +25 -0
  18. package/dist/chunks/transport-BBAz1kmP.js +30 -0
  19. package/dist/chunks/tslib.es6-D29rxPkW.js +37 -0
  20. package/dist/chunks/tx-type-CS4wIUJ8.js +68 -0
  21. package/dist/chunks/{wasm-DTyHBxcY.cjs → wasm-BYOKRR31.cjs} +1 -1
  22. package/dist/chunks/{wasm-BtPcXTR4.js → wasm-CLXJDrJA.js} +1 -1
  23. package/dist/chunks/wasm-CkFW222S.js +213 -0
  24. package/dist/clients/index.amd.js +97 -0
  25. package/dist/clients/index.cjs.cjs +1 -1
  26. package/dist/clients/index.esm.js +1 -1
  27. package/dist/constant/index.amd.js +458 -0
  28. package/dist/contracts/index.amd.js +19640 -0
  29. package/dist/contracts/index.cjs.cjs +2 -2
  30. package/dist/contracts/index.esm.js +2 -2
  31. package/dist/errors/index.amd.js +17 -0
  32. package/dist/index.amd.js +43 -0
  33. package/dist/index.cjs.cjs +3 -3
  34. package/dist/index.esm.js +3 -3
  35. package/dist/transports/index.amd.js +98 -0
  36. package/dist/utils/index.amd.js +353 -0
  37. package/dist/utils/index.cjs.cjs +3 -3
  38. package/dist/utils/index.esm.js +4 -4
  39. package/dist/vite-plugin/index.amd.js +186 -0
  40. package/dist/vite-plugin/index.cjs.cjs +189 -0
  41. package/dist/vite-plugin/index.d.cts +46 -0
  42. package/dist/vite-plugin/index.d.mts +46 -0
  43. package/dist/vite-plugin/index.esm.js +183 -0
  44. package/dist/webpack-plugin/index.amd.js +101 -0
  45. package/dist/webpack-plugin/index.cjs.cjs +104 -0
  46. package/dist/webpack-plugin/index.d.cts +46 -0
  47. package/dist/webpack-plugin/index.d.mts +46 -0
  48. package/dist/webpack-plugin/index.esm.js +98 -0
  49. package/package.json +36 -6
  50. package/dist/index.umd.d.mts +0 -15
  51. package/dist/umd/index.umd.js +0 -26296
@@ -0,0 +1,186 @@
1
+ define(['module', 'exports', 'node:fs', 'node:path', 'node:url'], (function (module, exports, fs, path, node_url) { 'use strict';
2
+
3
+ /**
4
+ * @locuschain/lib/vite-plugin
5
+ *
6
+ * Vite (그리고 wxt) 사용자가 lib 의 wasm 4 개를 자동으로 빌드 그래프에 포함시키도록 돕는 plugin.
7
+ *
8
+ * 두 가지 모드:
9
+ * - `mode: 'assets'` (기본): wasm 을 Vite 의 emitFile 로 자산 그래프에 등록.
10
+ * Vite 가 `assets/<name>-<hash>.wasm` 으로 emit. URL 은 `import.meta.ROLLUP_FILE_URL_<id>`
11
+ * placeholder 로 치환. 일반 Vite 웹 빌드, wxt 단일 entry 빌드에 적합.
12
+ *
13
+ * - `mode: 'public'`: wasm 을 Vite 의 publicDir 안 `wasm/` 폴더로 복사하고,
14
+ * lib URL 을 `chrome.runtime.getURL('wasm/<name>')` 로 치환.
15
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 환경에서 모든 entry 가 같은 wasm 사본을
16
+ * 공유하도록 한다. chrome extension 한정.
17
+ *
18
+ * 왜 두 모드인가:
19
+ * - 모던 Vite/Webpack 의 자산 그래프는 정적 분석 기반인데, wxt 의 defineImportMeta
20
+ * plugin 이 `import.meta.url` 을 `self.location.href` 로 매크로 치환해서 그 그래프
21
+ * 추적을 깨뜨린다. 이 plugin 은 `enforce: 'pre'` 로 wxt:define 보다 먼저 lib 코드의
22
+ * `new URL("../autogen/wasm/<name>", import.meta.url)` 패턴을 직접 잡아 처리한다.
23
+ * - 'assets' 모드는 entry 별 빌드 격리 환경에서 entry 마다 wasm 사본이 중복 emit 됨.
24
+ * - 'public' 모드는 publicDir 기반이라 entry 빌드와 무관하게 한 번만 출력 + 공유.
25
+ *
26
+ * 사용법:
27
+ * import { locusWasmPlugin } from '@locuschain/lib/vite-plugin';
28
+ * // 단일 entry (일반 web app)
29
+ * plugins: [locusWasmPlugin()]
30
+ * // wxt 의 chrome extension (entry 격리 빌드)
31
+ * plugins: [locusWasmPlugin({ mode: 'public' })]
32
+ */
33
+ const WASM_FILES = [
34
+ 'lclib.wasm',
35
+ 'crypto_aimer.wasm',
36
+ 'crypto_smaugt.wasm',
37
+ 'crypto_haetae.wasm'
38
+ ];
39
+ // 이 모듈은 lib 패키지의 dist/vite-plugin/index.{esm.js|cjs.cjs} 로 빌드된다.
40
+ // 따라서 `../autogen/wasm/` 은 dist/autogen/wasm/ 을 가리킨다 (rollup-plugin-copy 로 동봉됨).
41
+ const WASM_DIR = node_url.fileURLToPath(new URL('../autogen/wasm/', new URL(module.uri, document.baseURI).href));
42
+ // lib 코드(자체 패키지 또는 npm link 된 로컬 경로) 안에서만 transform 한다.
43
+ const LIB_ID_PATTERN = /(?:@locuschain[/\\]lib|locuschain-js[/\\]packages[/\\]lib)[/\\]dist[/\\]/;
44
+ // 두 가지 패턴 모두 매칭:
45
+ // (1) `new URL("../autogen/wasm/<name>", import.meta.url)` — 라이브러리 진입점에서 사용
46
+ // (2) `new URL("<name>", import.meta.url)` — emscripten glue 의 findWasmBinary() 잔여
47
+ function buildWasmUrlPatterns(filename) {
48
+ const fnameEscaped = filename.replace(/\./g, '\\.');
49
+ return [
50
+ new RegExp(`new\\s+URL\\(\\s*["']\\.\\./autogen/wasm/${fnameEscaped}["']\\s*,\\s*import\\.meta\\.url\\s*\\)`, 'g'),
51
+ new RegExp(`new\\s+URL\\(\\s*["']${fnameEscaped}["']\\s*,\\s*import\\.meta\\.url\\s*\\)`, 'g')
52
+ ];
53
+ }
54
+ function locusWasmPlugin(opts = {}) {
55
+ var _a, _b;
56
+ const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'assets';
57
+ const publicSubdir = (_b = opts.publicSubdir) !== null && _b !== void 0 ? _b : 'wasm';
58
+ const refIds = new Map();
59
+ let isServe = false;
60
+ let publicDir = false;
61
+ return {
62
+ name: 'locuschain-wasm',
63
+ enforce: 'pre',
64
+ configResolved(config) {
65
+ var _a, _b;
66
+ isServe = config.command === 'serve';
67
+ publicDir = config.publicDir;
68
+ // WASM_DIR 은 lib 패키지 안(보통 node_modules 또는 외부 symlink) 이라 사용자 프로젝트 root
69
+ // 바깥일 수 있다. dev 에서 `/@fs/<absolute>` 로 wasm 을 서빙하려면 fs.allow 에 등록돼 있어야 한다.
70
+ // `config()` hook 에서 `server.fs.allow: [WASM_DIR]` 를 반환하면 사용자가 명시하지 않은 경우
71
+ // Vite 가 기본 workspace root 탐색을 건너뛰어 프로젝트 root 가 allow 에서 빠진다 (→ 사용자 소스 403).
72
+ // configResolved 시점엔 이미 default 가 채워져 있으므로 안전하게 push 만 한다.
73
+ if (Array.isArray((_b = (_a = config.server) === null || _a === void 0 ? void 0 : _a.fs) === null || _b === void 0 ? void 0 : _b.allow)) {
74
+ config.server.fs.allow.push(WASM_DIR);
75
+ }
76
+ },
77
+ buildStart() {
78
+ refIds.clear();
79
+ // public 모드: dev/build 양쪽 모두 wasm 4 개를 publicDir/<publicSubdir>/ 로 복사한다.
80
+ // wxt dev 는 그 폴더를 그대로 .output/chrome-mv3-dev 에 복사해 extension origin
81
+ // (chrome.runtime.getURL) 으로 노출하므로 /@fs/ 우회가 필요 없어진다.
82
+ // 같은 build 안에서 여러 번 호출돼도 멱등 (mtime 비교).
83
+ if (mode === 'public') {
84
+ if (!publicDir || typeof publicDir !== 'string') {
85
+ this.warn(`[locuschain-wasm] mode:'public' requires Vite publicDir. ` +
86
+ `Falling back to 'assets' mode for this build.`);
87
+ }
88
+ else {
89
+ const targetDir = path.join(publicDir, publicSubdir);
90
+ if (!fs.existsSync(targetDir)) {
91
+ fs.mkdirSync(targetDir, { recursive: true });
92
+ }
93
+ for (const filename of WASM_FILES) {
94
+ const src = path.join(WASM_DIR, filename);
95
+ const dst = path.join(targetDir, filename);
96
+ if (!fs.existsSync(src)) {
97
+ this.error(`[locuschain-wasm] missing wasm asset: ${src}\n` +
98
+ `lib 가 정상적으로 빌드/설치되었는지 확인하세요.`);
99
+ }
100
+ // mtime 비교로 불필요한 재복사 회피 (watch 모드 친화적).
101
+ const srcMtime = fs.statSync(src).mtimeMs;
102
+ const dstMtime = fs.existsSync(dst) ? fs.statSync(dst).mtimeMs : 0;
103
+ if (srcMtime > dstMtime) {
104
+ fs.copyFileSync(src, dst);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ },
110
+ transform(code, id) {
111
+ const cleanId = id.replace(/\\/g, '/').replace(/\?.*$/, '');
112
+ if (!LIB_ID_PATTERN.test(cleanId)) {
113
+ return null;
114
+ }
115
+ // 이 모듈 안에서 어떤 wasm 들이 참조되는지 먼저 스캔.
116
+ const referenced = [];
117
+ for (const filename of WASM_FILES) {
118
+ const patterns = buildWasmUrlPatterns(filename);
119
+ if (patterns.some(p => p.test(code))) {
120
+ referenced.push(filename);
121
+ }
122
+ }
123
+ if (referenced.length === 0)
124
+ return null;
125
+ // assets 모드 + build: 처음 보는 wasm 은 emit.
126
+ if (mode === 'assets' && !isServe) {
127
+ for (const filename of referenced) {
128
+ if (refIds.has(filename))
129
+ continue;
130
+ const filepath = path.join(WASM_DIR, filename);
131
+ if (!fs.existsSync(filepath)) {
132
+ this.error(`[locuschain-wasm] missing wasm asset: ${filepath}\n` +
133
+ `lib 가 정상적으로 빌드/설치되었는지 확인하세요.`);
134
+ }
135
+ const referenceId = this.emitFile({
136
+ type: 'asset',
137
+ name: filename,
138
+ source: fs.readFileSync(filepath)
139
+ });
140
+ refIds.set(filename, referenceId);
141
+ }
142
+ }
143
+ // 패턴 치환. mode 가 먼저 — public 모드는 dev/build 양쪽 모두 publicDir 안
144
+ // wasm 을 chrome.runtime.getURL 또는 root-relative URL 로 가리킨다.
145
+ let newCode = code;
146
+ for (const filename of referenced) {
147
+ const patterns = buildWasmUrlPatterns(filename);
148
+ let replacement;
149
+ if (mode === 'public') {
150
+ // chrome extension: chrome.runtime.getURL 로 절대 URL 생성.
151
+ // 일반 web (chrome 없음) 폴백: root-relative URL — dev/build 모두 publicDir
152
+ // 의 wasm 을 dev server / 빌드 output 이 동일 경로로 서빙한다.
153
+ const relPath = `${publicSubdir}/${filename}`;
154
+ replacement =
155
+ `((typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getURL) ` +
156
+ `? chrome.runtime.getURL(${JSON.stringify(relPath)}) ` +
157
+ `: new URL(${JSON.stringify('/' + relPath)}, import.meta.url))`;
158
+ }
159
+ else if (isServe) {
160
+ // assets 모드 + dev: /@fs/<absolute path> 로 dev server 가 직접 서빙.
161
+ // (이 경로는 fs.allow 에 WASM_DIR 가 등록돼 있어야 한다 — configResolved 참조.)
162
+ const absUrl = path.join(WASM_DIR, filename).replace(/\\/g, '/');
163
+ replacement = `new URL(${JSON.stringify('/@fs/' + absUrl)}, import.meta.url)`;
164
+ }
165
+ else {
166
+ // assets 모드 + build
167
+ const refId = refIds.get(filename);
168
+ if (!refId)
169
+ continue;
170
+ replacement = `new URL(import.meta.ROLLUP_FILE_URL_${refId}, import.meta.url)`;
171
+ }
172
+ for (const pattern of patterns) {
173
+ newCode = newCode.replace(pattern, replacement);
174
+ }
175
+ }
176
+ return { code: newCode, map: null };
177
+ }
178
+ };
179
+ }
180
+
181
+ exports.default = locusWasmPlugin;
182
+ exports.locusWasmPlugin = locusWasmPlugin;
183
+
184
+ Object.defineProperty(exports, '__esModule', { value: true });
185
+
186
+ }));
@@ -0,0 +1,189 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var fs = require('node:fs');
6
+ var path = require('node:path');
7
+ var node_url = require('node:url');
8
+
9
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
10
+ /**
11
+ * @locuschain/lib/vite-plugin
12
+ *
13
+ * Vite (그리고 wxt) 사용자가 lib 의 wasm 4 개를 자동으로 빌드 그래프에 포함시키도록 돕는 plugin.
14
+ *
15
+ * 두 가지 모드:
16
+ * - `mode: 'assets'` (기본): wasm 을 Vite 의 emitFile 로 자산 그래프에 등록.
17
+ * Vite 가 `assets/<name>-<hash>.wasm` 으로 emit. URL 은 `import.meta.ROLLUP_FILE_URL_<id>`
18
+ * placeholder 로 치환. 일반 Vite 웹 빌드, wxt 단일 entry 빌드에 적합.
19
+ *
20
+ * - `mode: 'public'`: wasm 을 Vite 의 publicDir 안 `wasm/` 폴더로 복사하고,
21
+ * lib URL 을 `chrome.runtime.getURL('wasm/<name>')` 로 치환.
22
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 환경에서 모든 entry 가 같은 wasm 사본을
23
+ * 공유하도록 한다. chrome extension 한정.
24
+ *
25
+ * 왜 두 모드인가:
26
+ * - 모던 Vite/Webpack 의 자산 그래프는 정적 분석 기반인데, wxt 의 defineImportMeta
27
+ * plugin 이 `import.meta.url` 을 `self.location.href` 로 매크로 치환해서 그 그래프
28
+ * 추적을 깨뜨린다. 이 plugin 은 `enforce: 'pre'` 로 wxt:define 보다 먼저 lib 코드의
29
+ * `new URL("../autogen/wasm/<name>", import.meta.url)` 패턴을 직접 잡아 처리한다.
30
+ * - 'assets' 모드는 entry 별 빌드 격리 환경에서 entry 마다 wasm 사본이 중복 emit 됨.
31
+ * - 'public' 모드는 publicDir 기반이라 entry 빌드와 무관하게 한 번만 출력 + 공유.
32
+ *
33
+ * 사용법:
34
+ * import { locusWasmPlugin } from '@locuschain/lib/vite-plugin';
35
+ * // 단일 entry (일반 web app)
36
+ * plugins: [locusWasmPlugin()]
37
+ * // wxt 의 chrome extension (entry 격리 빌드)
38
+ * plugins: [locusWasmPlugin({ mode: 'public' })]
39
+ */
40
+ const WASM_FILES = [
41
+ 'lclib.wasm',
42
+ 'crypto_aimer.wasm',
43
+ 'crypto_smaugt.wasm',
44
+ 'crypto_haetae.wasm'
45
+ ];
46
+ // 이 모듈은 lib 패키지의 dist/vite-plugin/index.{esm.js|cjs.cjs} 로 빌드된다.
47
+ // 따라서 `../autogen/wasm/` 은 dist/autogen/wasm/ 을 가리킨다 (rollup-plugin-copy 로 동봉됨).
48
+ const WASM_DIR = node_url.fileURLToPath(new URL('../autogen/wasm/', (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('vite-plugin/index.cjs.cjs', document.baseURI).href))));
49
+ // lib 코드(자체 패키지 또는 npm link 된 로컬 경로) 안에서만 transform 한다.
50
+ const LIB_ID_PATTERN = /(?:@locuschain[/\\]lib|locuschain-js[/\\]packages[/\\]lib)[/\\]dist[/\\]/;
51
+ // 두 가지 패턴 모두 매칭:
52
+ // (1) `new URL("../autogen/wasm/<name>", import.meta.url)` — 라이브러리 진입점에서 사용
53
+ // (2) `new URL("<name>", import.meta.url)` — emscripten glue 의 findWasmBinary() 잔여
54
+ function buildWasmUrlPatterns(filename) {
55
+ const fnameEscaped = filename.replace(/\./g, '\\.');
56
+ return [
57
+ new RegExp(`new\\s+URL\\(\\s*["']\\.\\./autogen/wasm/${fnameEscaped}["']\\s*,\\s*import\\.meta\\.url\\s*\\)`, 'g'),
58
+ new RegExp(`new\\s+URL\\(\\s*["']${fnameEscaped}["']\\s*,\\s*import\\.meta\\.url\\s*\\)`, 'g')
59
+ ];
60
+ }
61
+ function locusWasmPlugin(opts = {}) {
62
+ var _a, _b;
63
+ const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'assets';
64
+ const publicSubdir = (_b = opts.publicSubdir) !== null && _b !== void 0 ? _b : 'wasm';
65
+ const refIds = new Map();
66
+ let isServe = false;
67
+ let publicDir = false;
68
+ return {
69
+ name: 'locuschain-wasm',
70
+ enforce: 'pre',
71
+ configResolved(config) {
72
+ var _a, _b;
73
+ isServe = config.command === 'serve';
74
+ publicDir = config.publicDir;
75
+ // WASM_DIR 은 lib 패키지 안(보통 node_modules 또는 외부 symlink) 이라 사용자 프로젝트 root
76
+ // 바깥일 수 있다. dev 에서 `/@fs/<absolute>` 로 wasm 을 서빙하려면 fs.allow 에 등록돼 있어야 한다.
77
+ // `config()` hook 에서 `server.fs.allow: [WASM_DIR]` 를 반환하면 사용자가 명시하지 않은 경우
78
+ // Vite 가 기본 workspace root 탐색을 건너뛰어 프로젝트 root 가 allow 에서 빠진다 (→ 사용자 소스 403).
79
+ // configResolved 시점엔 이미 default 가 채워져 있으므로 안전하게 push 만 한다.
80
+ if (Array.isArray((_b = (_a = config.server) === null || _a === void 0 ? void 0 : _a.fs) === null || _b === void 0 ? void 0 : _b.allow)) {
81
+ config.server.fs.allow.push(WASM_DIR);
82
+ }
83
+ },
84
+ buildStart() {
85
+ refIds.clear();
86
+ // public 모드: dev/build 양쪽 모두 wasm 4 개를 publicDir/<publicSubdir>/ 로 복사한다.
87
+ // wxt dev 는 그 폴더를 그대로 .output/chrome-mv3-dev 에 복사해 extension origin
88
+ // (chrome.runtime.getURL) 으로 노출하므로 /@fs/ 우회가 필요 없어진다.
89
+ // 같은 build 안에서 여러 번 호출돼도 멱등 (mtime 비교).
90
+ if (mode === 'public') {
91
+ if (!publicDir || typeof publicDir !== 'string') {
92
+ this.warn(`[locuschain-wasm] mode:'public' requires Vite publicDir. ` +
93
+ `Falling back to 'assets' mode for this build.`);
94
+ }
95
+ else {
96
+ const targetDir = path.join(publicDir, publicSubdir);
97
+ if (!fs.existsSync(targetDir)) {
98
+ fs.mkdirSync(targetDir, { recursive: true });
99
+ }
100
+ for (const filename of WASM_FILES) {
101
+ const src = path.join(WASM_DIR, filename);
102
+ const dst = path.join(targetDir, filename);
103
+ if (!fs.existsSync(src)) {
104
+ this.error(`[locuschain-wasm] missing wasm asset: ${src}\n` +
105
+ `lib 가 정상적으로 빌드/설치되었는지 확인하세요.`);
106
+ }
107
+ // mtime 비교로 불필요한 재복사 회피 (watch 모드 친화적).
108
+ const srcMtime = fs.statSync(src).mtimeMs;
109
+ const dstMtime = fs.existsSync(dst) ? fs.statSync(dst).mtimeMs : 0;
110
+ if (srcMtime > dstMtime) {
111
+ fs.copyFileSync(src, dst);
112
+ }
113
+ }
114
+ }
115
+ }
116
+ },
117
+ transform(code, id) {
118
+ const cleanId = id.replace(/\\/g, '/').replace(/\?.*$/, '');
119
+ if (!LIB_ID_PATTERN.test(cleanId)) {
120
+ return null;
121
+ }
122
+ // 이 모듈 안에서 어떤 wasm 들이 참조되는지 먼저 스캔.
123
+ const referenced = [];
124
+ for (const filename of WASM_FILES) {
125
+ const patterns = buildWasmUrlPatterns(filename);
126
+ if (patterns.some(p => p.test(code))) {
127
+ referenced.push(filename);
128
+ }
129
+ }
130
+ if (referenced.length === 0)
131
+ return null;
132
+ // assets 모드 + build: 처음 보는 wasm 은 emit.
133
+ if (mode === 'assets' && !isServe) {
134
+ for (const filename of referenced) {
135
+ if (refIds.has(filename))
136
+ continue;
137
+ const filepath = path.join(WASM_DIR, filename);
138
+ if (!fs.existsSync(filepath)) {
139
+ this.error(`[locuschain-wasm] missing wasm asset: ${filepath}\n` +
140
+ `lib 가 정상적으로 빌드/설치되었는지 확인하세요.`);
141
+ }
142
+ const referenceId = this.emitFile({
143
+ type: 'asset',
144
+ name: filename,
145
+ source: fs.readFileSync(filepath)
146
+ });
147
+ refIds.set(filename, referenceId);
148
+ }
149
+ }
150
+ // 패턴 치환. mode 가 먼저 — public 모드는 dev/build 양쪽 모두 publicDir 안
151
+ // wasm 을 chrome.runtime.getURL 또는 root-relative URL 로 가리킨다.
152
+ let newCode = code;
153
+ for (const filename of referenced) {
154
+ const patterns = buildWasmUrlPatterns(filename);
155
+ let replacement;
156
+ if (mode === 'public') {
157
+ // chrome extension: chrome.runtime.getURL 로 절대 URL 생성.
158
+ // 일반 web (chrome 없음) 폴백: root-relative URL — dev/build 모두 publicDir
159
+ // 의 wasm 을 dev server / 빌드 output 이 동일 경로로 서빙한다.
160
+ const relPath = `${publicSubdir}/${filename}`;
161
+ replacement =
162
+ `((typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getURL) ` +
163
+ `? chrome.runtime.getURL(${JSON.stringify(relPath)}) ` +
164
+ `: new URL(${JSON.stringify('/' + relPath)}, import.meta.url))`;
165
+ }
166
+ else if (isServe) {
167
+ // assets 모드 + dev: /@fs/<absolute path> 로 dev server 가 직접 서빙.
168
+ // (이 경로는 fs.allow 에 WASM_DIR 가 등록돼 있어야 한다 — configResolved 참조.)
169
+ const absUrl = path.join(WASM_DIR, filename).replace(/\\/g, '/');
170
+ replacement = `new URL(${JSON.stringify('/@fs/' + absUrl)}, import.meta.url)`;
171
+ }
172
+ else {
173
+ // assets 모드 + build
174
+ const refId = refIds.get(filename);
175
+ if (!refId)
176
+ continue;
177
+ replacement = `new URL(import.meta.ROLLUP_FILE_URL_${refId}, import.meta.url)`;
178
+ }
179
+ for (const pattern of patterns) {
180
+ newCode = newCode.replace(pattern, replacement);
181
+ }
182
+ }
183
+ return { code: newCode, map: null };
184
+ }
185
+ };
186
+ }
187
+
188
+ exports.default = locusWasmPlugin;
189
+ exports.locusWasmPlugin = locusWasmPlugin;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @locuschain/lib/vite-plugin
3
+ *
4
+ * Vite (그리고 wxt) 사용자가 lib 의 wasm 4 개를 자동으로 빌드 그래프에 포함시키도록 돕는 plugin.
5
+ *
6
+ * 두 가지 모드:
7
+ * - `mode: 'assets'` (기본): wasm 을 Vite 의 emitFile 로 자산 그래프에 등록.
8
+ * Vite 가 `assets/<name>-<hash>.wasm` 으로 emit. URL 은 `import.meta.ROLLUP_FILE_URL_<id>`
9
+ * placeholder 로 치환. 일반 Vite 웹 빌드, wxt 단일 entry 빌드에 적합.
10
+ *
11
+ * - `mode: 'public'`: wasm 을 Vite 의 publicDir 안 `wasm/` 폴더로 복사하고,
12
+ * lib URL 을 `chrome.runtime.getURL('wasm/<name>')` 로 치환.
13
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 환경에서 모든 entry 가 같은 wasm 사본을
14
+ * 공유하도록 한다. chrome extension 한정.
15
+ *
16
+ * 왜 두 모드인가:
17
+ * - 모던 Vite/Webpack 의 자산 그래프는 정적 분석 기반인데, wxt 의 defineImportMeta
18
+ * plugin 이 `import.meta.url` 을 `self.location.href` 로 매크로 치환해서 그 그래프
19
+ * 추적을 깨뜨린다. 이 plugin 은 `enforce: 'pre'` 로 wxt:define 보다 먼저 lib 코드의
20
+ * `new URL("../autogen/wasm/<name>", import.meta.url)` 패턴을 직접 잡아 처리한다.
21
+ * - 'assets' 모드는 entry 별 빌드 격리 환경에서 entry 마다 wasm 사본이 중복 emit 됨.
22
+ * - 'public' 모드는 publicDir 기반이라 entry 빌드와 무관하게 한 번만 출력 + 공유.
23
+ *
24
+ * 사용법:
25
+ * import { locusWasmPlugin } from '@locuschain/lib/vite-plugin';
26
+ * // 단일 entry (일반 web app)
27
+ * plugins: [locusWasmPlugin()]
28
+ * // wxt 의 chrome extension (entry 격리 빌드)
29
+ * plugins: [locusWasmPlugin({ mode: 'public' })]
30
+ */
31
+ import type { Plugin } from 'vite';
32
+ export interface LocusWasmPluginOptions {
33
+ /**
34
+ * - 'assets' (기본): Vite emitFile + ROLLUP_FILE_URL placeholder. 단일 entry 빌드용.
35
+ * - 'public' : publicDir/wasm/ 에 wasm 복사 + chrome.runtime.getURL 치환.
36
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 chrome extension 환경용.
37
+ */
38
+ mode?: 'assets' | 'public';
39
+ /**
40
+ * public 모드에서 wasm 을 두는 서브 디렉토리. publicDir 기준 상대 경로. 기본 'wasm'.
41
+ * 빌드 결과는 `<output>/<publicSubdir>/<name>.wasm` 로 나온다.
42
+ */
43
+ publicSubdir?: string;
44
+ }
45
+ export declare function locusWasmPlugin(opts?: LocusWasmPluginOptions): Plugin;
46
+ export default locusWasmPlugin;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @locuschain/lib/vite-plugin
3
+ *
4
+ * Vite (그리고 wxt) 사용자가 lib 의 wasm 4 개를 자동으로 빌드 그래프에 포함시키도록 돕는 plugin.
5
+ *
6
+ * 두 가지 모드:
7
+ * - `mode: 'assets'` (기본): wasm 을 Vite 의 emitFile 로 자산 그래프에 등록.
8
+ * Vite 가 `assets/<name>-<hash>.wasm` 으로 emit. URL 은 `import.meta.ROLLUP_FILE_URL_<id>`
9
+ * placeholder 로 치환. 일반 Vite 웹 빌드, wxt 단일 entry 빌드에 적합.
10
+ *
11
+ * - `mode: 'public'`: wasm 을 Vite 의 publicDir 안 `wasm/` 폴더로 복사하고,
12
+ * lib URL 을 `chrome.runtime.getURL('wasm/<name>')` 로 치환.
13
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 환경에서 모든 entry 가 같은 wasm 사본을
14
+ * 공유하도록 한다. chrome extension 한정.
15
+ *
16
+ * 왜 두 모드인가:
17
+ * - 모던 Vite/Webpack 의 자산 그래프는 정적 분석 기반인데, wxt 의 defineImportMeta
18
+ * plugin 이 `import.meta.url` 을 `self.location.href` 로 매크로 치환해서 그 그래프
19
+ * 추적을 깨뜨린다. 이 plugin 은 `enforce: 'pre'` 로 wxt:define 보다 먼저 lib 코드의
20
+ * `new URL("../autogen/wasm/<name>", import.meta.url)` 패턴을 직접 잡아 처리한다.
21
+ * - 'assets' 모드는 entry 별 빌드 격리 환경에서 entry 마다 wasm 사본이 중복 emit 됨.
22
+ * - 'public' 모드는 publicDir 기반이라 entry 빌드와 무관하게 한 번만 출력 + 공유.
23
+ *
24
+ * 사용법:
25
+ * import { locusWasmPlugin } from '@locuschain/lib/vite-plugin';
26
+ * // 단일 entry (일반 web app)
27
+ * plugins: [locusWasmPlugin()]
28
+ * // wxt 의 chrome extension (entry 격리 빌드)
29
+ * plugins: [locusWasmPlugin({ mode: 'public' })]
30
+ */
31
+ import type { Plugin } from 'vite';
32
+ export interface LocusWasmPluginOptions {
33
+ /**
34
+ * - 'assets' (기본): Vite emitFile + ROLLUP_FILE_URL placeholder. 단일 entry 빌드용.
35
+ * - 'public' : publicDir/wasm/ 에 wasm 복사 + chrome.runtime.getURL 치환.
36
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 chrome extension 환경용.
37
+ */
38
+ mode?: 'assets' | 'public';
39
+ /**
40
+ * public 모드에서 wasm 을 두는 서브 디렉토리. publicDir 기준 상대 경로. 기본 'wasm'.
41
+ * 빌드 결과는 `<output>/<publicSubdir>/<name>.wasm` 로 나온다.
42
+ */
43
+ publicSubdir?: string;
44
+ }
45
+ export declare function locusWasmPlugin(opts?: LocusWasmPluginOptions): Plugin;
46
+ export default locusWasmPlugin;
@@ -0,0 +1,183 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ /**
6
+ * @locuschain/lib/vite-plugin
7
+ *
8
+ * Vite (그리고 wxt) 사용자가 lib 의 wasm 4 개를 자동으로 빌드 그래프에 포함시키도록 돕는 plugin.
9
+ *
10
+ * 두 가지 모드:
11
+ * - `mode: 'assets'` (기본): wasm 을 Vite 의 emitFile 로 자산 그래프에 등록.
12
+ * Vite 가 `assets/<name>-<hash>.wasm` 으로 emit. URL 은 `import.meta.ROLLUP_FILE_URL_<id>`
13
+ * placeholder 로 치환. 일반 Vite 웹 빌드, wxt 단일 entry 빌드에 적합.
14
+ *
15
+ * - `mode: 'public'`: wasm 을 Vite 의 publicDir 안 `wasm/` 폴더로 복사하고,
16
+ * lib URL 을 `chrome.runtime.getURL('wasm/<name>')` 로 치환.
17
+ * wxt 처럼 entry 별 별도 빌드를 돌리는 환경에서 모든 entry 가 같은 wasm 사본을
18
+ * 공유하도록 한다. chrome extension 한정.
19
+ *
20
+ * 왜 두 모드인가:
21
+ * - 모던 Vite/Webpack 의 자산 그래프는 정적 분석 기반인데, wxt 의 defineImportMeta
22
+ * plugin 이 `import.meta.url` 을 `self.location.href` 로 매크로 치환해서 그 그래프
23
+ * 추적을 깨뜨린다. 이 plugin 은 `enforce: 'pre'` 로 wxt:define 보다 먼저 lib 코드의
24
+ * `new URL("../autogen/wasm/<name>", import.meta.url)` 패턴을 직접 잡아 처리한다.
25
+ * - 'assets' 모드는 entry 별 빌드 격리 환경에서 entry 마다 wasm 사본이 중복 emit 됨.
26
+ * - 'public' 모드는 publicDir 기반이라 entry 빌드와 무관하게 한 번만 출력 + 공유.
27
+ *
28
+ * 사용법:
29
+ * import { locusWasmPlugin } from '@locuschain/lib/vite-plugin';
30
+ * // 단일 entry (일반 web app)
31
+ * plugins: [locusWasmPlugin()]
32
+ * // wxt 의 chrome extension (entry 격리 빌드)
33
+ * plugins: [locusWasmPlugin({ mode: 'public' })]
34
+ */
35
+ const WASM_FILES = [
36
+ 'lclib.wasm',
37
+ 'crypto_aimer.wasm',
38
+ 'crypto_smaugt.wasm',
39
+ 'crypto_haetae.wasm'
40
+ ];
41
+ // 이 모듈은 lib 패키지의 dist/vite-plugin/index.{esm.js|cjs.cjs} 로 빌드된다.
42
+ // 따라서 `../autogen/wasm/` 은 dist/autogen/wasm/ 을 가리킨다 (rollup-plugin-copy 로 동봉됨).
43
+ const WASM_DIR = fileURLToPath(new URL('../autogen/wasm/', import.meta.url));
44
+ // lib 코드(자체 패키지 또는 npm link 된 로컬 경로) 안에서만 transform 한다.
45
+ const LIB_ID_PATTERN = /(?:@locuschain[/\\]lib|locuschain-js[/\\]packages[/\\]lib)[/\\]dist[/\\]/;
46
+ // 두 가지 패턴 모두 매칭:
47
+ // (1) `new URL("../autogen/wasm/<name>", import.meta.url)` — 라이브러리 진입점에서 사용
48
+ // (2) `new URL("<name>", import.meta.url)` — emscripten glue 의 findWasmBinary() 잔여
49
+ function buildWasmUrlPatterns(filename) {
50
+ const fnameEscaped = filename.replace(/\./g, '\\.');
51
+ return [
52
+ new RegExp(`new\\s+URL\\(\\s*["']\\.\\./autogen/wasm/${fnameEscaped}["']\\s*,\\s*import\\.meta\\.url\\s*\\)`, 'g'),
53
+ new RegExp(`new\\s+URL\\(\\s*["']${fnameEscaped}["']\\s*,\\s*import\\.meta\\.url\\s*\\)`, 'g')
54
+ ];
55
+ }
56
+ function locusWasmPlugin(opts = {}) {
57
+ var _a, _b;
58
+ const mode = (_a = opts.mode) !== null && _a !== void 0 ? _a : 'assets';
59
+ const publicSubdir = (_b = opts.publicSubdir) !== null && _b !== void 0 ? _b : 'wasm';
60
+ const refIds = new Map();
61
+ let isServe = false;
62
+ let publicDir = false;
63
+ return {
64
+ name: 'locuschain-wasm',
65
+ enforce: 'pre',
66
+ configResolved(config) {
67
+ var _a, _b;
68
+ isServe = config.command === 'serve';
69
+ publicDir = config.publicDir;
70
+ // WASM_DIR 은 lib 패키지 안(보통 node_modules 또는 외부 symlink) 이라 사용자 프로젝트 root
71
+ // 바깥일 수 있다. dev 에서 `/@fs/<absolute>` 로 wasm 을 서빙하려면 fs.allow 에 등록돼 있어야 한다.
72
+ // `config()` hook 에서 `server.fs.allow: [WASM_DIR]` 를 반환하면 사용자가 명시하지 않은 경우
73
+ // Vite 가 기본 workspace root 탐색을 건너뛰어 프로젝트 root 가 allow 에서 빠진다 (→ 사용자 소스 403).
74
+ // configResolved 시점엔 이미 default 가 채워져 있으므로 안전하게 push 만 한다.
75
+ if (Array.isArray((_b = (_a = config.server) === null || _a === void 0 ? void 0 : _a.fs) === null || _b === void 0 ? void 0 : _b.allow)) {
76
+ config.server.fs.allow.push(WASM_DIR);
77
+ }
78
+ },
79
+ buildStart() {
80
+ refIds.clear();
81
+ // public 모드: dev/build 양쪽 모두 wasm 4 개를 publicDir/<publicSubdir>/ 로 복사한다.
82
+ // wxt dev 는 그 폴더를 그대로 .output/chrome-mv3-dev 에 복사해 extension origin
83
+ // (chrome.runtime.getURL) 으로 노출하므로 /@fs/ 우회가 필요 없어진다.
84
+ // 같은 build 안에서 여러 번 호출돼도 멱등 (mtime 비교).
85
+ if (mode === 'public') {
86
+ if (!publicDir || typeof publicDir !== 'string') {
87
+ this.warn(`[locuschain-wasm] mode:'public' requires Vite publicDir. ` +
88
+ `Falling back to 'assets' mode for this build.`);
89
+ }
90
+ else {
91
+ const targetDir = path.join(publicDir, publicSubdir);
92
+ if (!fs.existsSync(targetDir)) {
93
+ fs.mkdirSync(targetDir, { recursive: true });
94
+ }
95
+ for (const filename of WASM_FILES) {
96
+ const src = path.join(WASM_DIR, filename);
97
+ const dst = path.join(targetDir, filename);
98
+ if (!fs.existsSync(src)) {
99
+ this.error(`[locuschain-wasm] missing wasm asset: ${src}\n` +
100
+ `lib 가 정상적으로 빌드/설치되었는지 확인하세요.`);
101
+ }
102
+ // mtime 비교로 불필요한 재복사 회피 (watch 모드 친화적).
103
+ const srcMtime = fs.statSync(src).mtimeMs;
104
+ const dstMtime = fs.existsSync(dst) ? fs.statSync(dst).mtimeMs : 0;
105
+ if (srcMtime > dstMtime) {
106
+ fs.copyFileSync(src, dst);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ },
112
+ transform(code, id) {
113
+ const cleanId = id.replace(/\\/g, '/').replace(/\?.*$/, '');
114
+ if (!LIB_ID_PATTERN.test(cleanId)) {
115
+ return null;
116
+ }
117
+ // 이 모듈 안에서 어떤 wasm 들이 참조되는지 먼저 스캔.
118
+ const referenced = [];
119
+ for (const filename of WASM_FILES) {
120
+ const patterns = buildWasmUrlPatterns(filename);
121
+ if (patterns.some(p => p.test(code))) {
122
+ referenced.push(filename);
123
+ }
124
+ }
125
+ if (referenced.length === 0)
126
+ return null;
127
+ // assets 모드 + build: 처음 보는 wasm 은 emit.
128
+ if (mode === 'assets' && !isServe) {
129
+ for (const filename of referenced) {
130
+ if (refIds.has(filename))
131
+ continue;
132
+ const filepath = path.join(WASM_DIR, filename);
133
+ if (!fs.existsSync(filepath)) {
134
+ this.error(`[locuschain-wasm] missing wasm asset: ${filepath}\n` +
135
+ `lib 가 정상적으로 빌드/설치되었는지 확인하세요.`);
136
+ }
137
+ const referenceId = this.emitFile({
138
+ type: 'asset',
139
+ name: filename,
140
+ source: fs.readFileSync(filepath)
141
+ });
142
+ refIds.set(filename, referenceId);
143
+ }
144
+ }
145
+ // 패턴 치환. mode 가 먼저 — public 모드는 dev/build 양쪽 모두 publicDir 안
146
+ // wasm 을 chrome.runtime.getURL 또는 root-relative URL 로 가리킨다.
147
+ let newCode = code;
148
+ for (const filename of referenced) {
149
+ const patterns = buildWasmUrlPatterns(filename);
150
+ let replacement;
151
+ if (mode === 'public') {
152
+ // chrome extension: chrome.runtime.getURL 로 절대 URL 생성.
153
+ // 일반 web (chrome 없음) 폴백: root-relative URL — dev/build 모두 publicDir
154
+ // 의 wasm 을 dev server / 빌드 output 이 동일 경로로 서빙한다.
155
+ const relPath = `${publicSubdir}/${filename}`;
156
+ replacement =
157
+ `((typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getURL) ` +
158
+ `? chrome.runtime.getURL(${JSON.stringify(relPath)}) ` +
159
+ `: new URL(${JSON.stringify('/' + relPath)}, import.meta.url))`;
160
+ }
161
+ else if (isServe) {
162
+ // assets 모드 + dev: /@fs/<absolute path> 로 dev server 가 직접 서빙.
163
+ // (이 경로는 fs.allow 에 WASM_DIR 가 등록돼 있어야 한다 — configResolved 참조.)
164
+ const absUrl = path.join(WASM_DIR, filename).replace(/\\/g, '/');
165
+ replacement = `new URL(${JSON.stringify('/@fs/' + absUrl)}, import.meta.url)`;
166
+ }
167
+ else {
168
+ // assets 모드 + build
169
+ const refId = refIds.get(filename);
170
+ if (!refId)
171
+ continue;
172
+ replacement = `new URL(import.meta.ROLLUP_FILE_URL_${refId}, import.meta.url)`;
173
+ }
174
+ for (const pattern of patterns) {
175
+ newCode = newCode.replace(pattern, replacement);
176
+ }
177
+ }
178
+ return { code: newCode, map: null };
179
+ }
180
+ };
181
+ }
182
+
183
+ export { locusWasmPlugin as default, locusWasmPlugin };