@miden-sdk/create-para-react 0.0.0-bootstrap → 0.16.0-rc.6
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/LICENSE +21 -0
- package/README.md +16 -6
- package/bin/create-miden-para-react.mjs +369 -0
- package/package.json +28 -8
- package/template/src/App.tsx +49 -0
- package/template/src/optional-connectors.ts +1 -0
- package/template/src/polyfills.ts +11 -0
- package/template/vite.config.ts +87 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Miden
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
# @miden-sdk/create-para-react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`npm create @miden-sdk/para-react@latest my-app` scaffolds the latest Vite `react-ts` starter, overwrites it with this repo's `vite.config.ts`, swaps in a Para + Miden-ready `App.tsx`, and adds the deps needed to run it out of the box. The scaffold always runs `create-vite` with `--yes --no-install` and pipes "no" to the install prompt to prevent upstream installs from overwriting the template before we patch it.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
## What it does
|
|
6
|
+
- Runs `npm create vite@latest <target> -- --template react-ts` so you always start from the upstream default.
|
|
7
|
+
- Replaces `vite.config.ts` with the Para + Miden-friendly config (dedupe/exclude and WASM asset handling).
|
|
8
|
+
- Replaces `src/App.tsx` with a `ParaSignerProvider` + `MidenProvider` starter that reports wallet, account ID, and client readiness.
|
|
9
|
+
- Adds Para/Miden deps: `@miden-sdk/para`, `@miden-sdk/react`, `@getpara/react-sdk-lite`, `@getpara/evm-wallet-connectors`, `@miden-sdk/miden-sdk`, plus dev plugins `vite-plugin-node-polyfills`, `vite-plugin-wasm`, and `vite-plugin-top-level-await`.
|
|
10
|
+
- Installs dependencies using your detected package manager (`pnpm`, `yarn`, `bun`, or falls back to `npm`); `create-vite` is invoked with `--yes --no-install` and auto-answers "no" to install prompts to avoid reverting the patched files.
|
|
11
|
+
- Writes `.npmrc` with `legacy-peer-deps=true` for peer dependency resolution.
|
|
12
|
+
- Adds `src/polyfills.ts` and injects it into `src/main.tsx` to provide `Buffer`/`process` in the browser.
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
## Usage
|
|
15
|
+
- Standard: `npm create @miden-sdk/para-react@latest my-new-app`
|
|
16
|
+
- Skip install: add `--skip-install` if you want to install later.
|
|
17
|
+
- Set `VITE_PARA_API_KEY` in a `.env.local` (or similar) file so the generated `App.tsx` can initialize Para. **Production deployments require a Para production API key.**
|
|
18
|
+
- Recommended next steps: `cd my-new-app && npm install && npm run dev` (`.npmrc` opts into legacy peer deps so npm works).
|
|
19
|
+
|
|
20
|
+
Publish from this folder with `npm publish --access public` when you're ready. For local testing, run `node ./packages/create-miden-para-react/bin/create-miden-para-react.mjs my-app`.
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import {
|
|
5
|
+
copyFileSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
} from "node:fs";
|
|
11
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const templateConfigPath = resolve(
|
|
17
|
+
__dirname,
|
|
18
|
+
"..",
|
|
19
|
+
"template",
|
|
20
|
+
"vite.config.ts"
|
|
21
|
+
);
|
|
22
|
+
const templateAppPath = resolve(__dirname, "..", "template", "src", "App.tsx");
|
|
23
|
+
const templatePolyfillsPath = resolve(
|
|
24
|
+
__dirname,
|
|
25
|
+
"..",
|
|
26
|
+
"template",
|
|
27
|
+
"src",
|
|
28
|
+
"polyfills.ts"
|
|
29
|
+
);
|
|
30
|
+
const templateOptionalConnectorsPath = resolve(
|
|
31
|
+
__dirname,
|
|
32
|
+
"..",
|
|
33
|
+
"template",
|
|
34
|
+
"src",
|
|
35
|
+
"optional-connectors.ts"
|
|
36
|
+
);
|
|
37
|
+
const repoRoot = resolve(__dirname, "..", "..", "..");
|
|
38
|
+
const localMidenParaPath =
|
|
39
|
+
process.env.MIDEN_PARA_LOCAL_MIDEN_PARA_PATH ?? repoRoot;
|
|
40
|
+
const localUseMidenParaReactPath =
|
|
41
|
+
process.env.MIDEN_PARA_LOCAL_USE_MIDEN_PARA_REACT_PATH ??
|
|
42
|
+
join(repoRoot, "packages", "use-miden-para-react");
|
|
43
|
+
const useLocalDeps = process.env.MIDEN_PARA_LOCAL_DEPS === "1";
|
|
44
|
+
|
|
45
|
+
const args = process.argv.slice(2);
|
|
46
|
+
const target =
|
|
47
|
+
args.find((arg) => !arg.startsWith("-")) ?? "miden-para-react-app";
|
|
48
|
+
const skipInstall = args.some(
|
|
49
|
+
(flag) => flag === "--skip-install" || flag === "--no-install"
|
|
50
|
+
);
|
|
51
|
+
const skipScaffold =
|
|
52
|
+
args.some((flag) => flag === "--skip-scaffold" || flag === "--no-scaffold") ||
|
|
53
|
+
process.env.MIDEN_PARA_TEST_MODE === "1";
|
|
54
|
+
const targetDir = resolve(process.cwd(), target);
|
|
55
|
+
const targetParent = dirname(targetDir);
|
|
56
|
+
const targetName = basename(targetDir);
|
|
57
|
+
const baseEnv = {
|
|
58
|
+
...process.env,
|
|
59
|
+
CI: process.env.CI ?? "true",
|
|
60
|
+
npm_config_yes: process.env.npm_config_yes ?? "true",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
ensureTargetParent();
|
|
64
|
+
if (skipScaffold) {
|
|
65
|
+
scaffoldMinimalProject(targetDir, targetName);
|
|
66
|
+
} else {
|
|
67
|
+
runCreateVite(targetName);
|
|
68
|
+
}
|
|
69
|
+
overrideViteConfig(targetDir);
|
|
70
|
+
overrideApp(targetDir);
|
|
71
|
+
ensurePolyfills(targetDir);
|
|
72
|
+
ensureOptionalConnectorsShim(targetDir);
|
|
73
|
+
ensurePolyfillDependency(targetDir);
|
|
74
|
+
ensureMidenParaDependencies(targetDir);
|
|
75
|
+
ensureViteConfigTsconfig(targetDir);
|
|
76
|
+
ensureNpmRc(targetDir);
|
|
77
|
+
logEnvReminder(targetName);
|
|
78
|
+
|
|
79
|
+
if (!skipInstall) {
|
|
80
|
+
installDependencies(targetDir);
|
|
81
|
+
} else {
|
|
82
|
+
logStep("Skipped dependency installation (--skip-install)");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function ensureTargetParent() {
|
|
86
|
+
mkdirSync(targetParent, { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function runCreateVite(targetArg) {
|
|
90
|
+
const scaffoldArgs = [
|
|
91
|
+
"create",
|
|
92
|
+
"vite@latest",
|
|
93
|
+
targetArg,
|
|
94
|
+
"--",
|
|
95
|
+
"--template",
|
|
96
|
+
"react-ts",
|
|
97
|
+
"--yes", // avoid interactive prompts that might install/revert files
|
|
98
|
+
"--no-install", // we handle installs after patching package.json
|
|
99
|
+
];
|
|
100
|
+
runOrExit("npm", scaffoldArgs, targetParent, baseEnv, "n\n");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function scaffoldMinimalProject(targetRoot, name) {
|
|
104
|
+
mkdirSync(targetRoot, { recursive: true });
|
|
105
|
+
const pkgPath = join(targetRoot, "package.json");
|
|
106
|
+
if (!existsSync(pkgPath)) {
|
|
107
|
+
const pkg = {
|
|
108
|
+
name,
|
|
109
|
+
private: true,
|
|
110
|
+
version: "0.0.0",
|
|
111
|
+
type: "module",
|
|
112
|
+
scripts: {
|
|
113
|
+
dev: "vite",
|
|
114
|
+
build: "vite build",
|
|
115
|
+
preview: "vite preview",
|
|
116
|
+
},
|
|
117
|
+
dependencies: {
|
|
118
|
+
react: "^18.2.0",
|
|
119
|
+
"react-dom": "^18.2.0",
|
|
120
|
+
},
|
|
121
|
+
devDependencies: {
|
|
122
|
+
"@types/react": "^18.2.0",
|
|
123
|
+
"@types/react-dom": "^18.2.0",
|
|
124
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
125
|
+
typescript: "^5.2.2",
|
|
126
|
+
vite: "^5.2.0",
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const srcDir = join(targetRoot, "src");
|
|
133
|
+
mkdirSync(srcDir, { recursive: true });
|
|
134
|
+
const mainPath = join(srcDir, "main.tsx");
|
|
135
|
+
if (!existsSync(mainPath)) {
|
|
136
|
+
writeFileSync(
|
|
137
|
+
mainPath,
|
|
138
|
+
`import React from "react";\nimport ReactDOM from "react-dom/client";\nimport App from "./App";\n\nReactDOM.createRoot(document.getElementById("root")!).render(<App />);\n`
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
const appPath = join(srcDir, "App.tsx");
|
|
142
|
+
if (!existsSync(appPath)) {
|
|
143
|
+
writeFileSync(appPath, "export default function App() { return null; }\n");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function overrideViteConfig(targetRoot) {
|
|
148
|
+
const dest = join(targetRoot, "vite.config.ts");
|
|
149
|
+
copyFileSync(templateConfigPath, dest);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function overrideApp(targetRoot) {
|
|
153
|
+
const dest = join(targetRoot, "src", "App.tsx");
|
|
154
|
+
mkdirSync(join(targetRoot, "src"), { recursive: true });
|
|
155
|
+
logStep(`Replacing App.tsx with Para + Miden starter at ${dest}`);
|
|
156
|
+
copyFileSync(templateAppPath, dest);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function ensurePolyfills(targetRoot) {
|
|
160
|
+
const dest = join(targetRoot, "src", "polyfills.ts");
|
|
161
|
+
mkdirSync(join(targetRoot, "src"), { recursive: true });
|
|
162
|
+
copyFileSync(templatePolyfillsPath, dest);
|
|
163
|
+
|
|
164
|
+
const mainPath = join(targetRoot, "src", "main.tsx");
|
|
165
|
+
if (existsSync(mainPath)) {
|
|
166
|
+
const main = readFileSync(mainPath, "utf8");
|
|
167
|
+
if (!main.includes("./polyfills") && !main.includes("./polyfills")) {
|
|
168
|
+
writeFileSync(mainPath, `import "./polyfills";\n${main}`);
|
|
169
|
+
logStep(`Injected polyfills import into ${mainPath}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function ensureOptionalConnectorsShim(targetRoot) {
|
|
175
|
+
const dest = join(targetRoot, "src", "optional-connectors.ts");
|
|
176
|
+
mkdirSync(join(targetRoot, "src"), { recursive: true });
|
|
177
|
+
copyFileSync(templateOptionalConnectorsPath, dest);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function ensurePolyfillDependency(targetRoot) {
|
|
181
|
+
const pkgPath = join(targetRoot, "package.json");
|
|
182
|
+
if (!existsSync(pkgPath)) {
|
|
183
|
+
logStep("No package.json found after scaffolding; nothing to patch");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
188
|
+
pkg.devDependencies = pkg.devDependencies ?? {};
|
|
189
|
+
pkg.devDependencies["vite-plugin-node-polyfills"] ??= "^0.24.0";
|
|
190
|
+
pkg.devDependencies["vite-plugin-wasm"] ??= "^3.5.0";
|
|
191
|
+
pkg.devDependencies["vite-plugin-top-level-await"] ??= "^1.6.0";
|
|
192
|
+
// vite-plugin-top-level-await does `require("rollup")` / `require("esbuild")`
|
|
193
|
+
// but doesn't declare them as dependencies. Vite 8 switched to rolldown and
|
|
194
|
+
// no longer installs either transitively, so pin them explicitly.
|
|
195
|
+
pkg.devDependencies["rollup"] ??= "^4.0.0";
|
|
196
|
+
pkg.devDependencies["esbuild"] ??= "^0.27.0";
|
|
197
|
+
// vite-plugin-top-level-await depends on `@swc/core: ^1.12.14` and drives it
|
|
198
|
+
// through the AST printer. swc 1.16 changed that AST's schema, so the caret
|
|
199
|
+
// range resolves to a version the plugin cannot use and the build fails at
|
|
200
|
+
// `generateBundle` with `Error: missing field \`type\``. Hold it on 1.15.x
|
|
201
|
+
// until the plugin catches up.
|
|
202
|
+
pkg.devDependencies["@swc/core"] ??= "~1.15.47";
|
|
203
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
204
|
+
logStep("Added Vite plugin deps (polyfills/wasm/top-level-await)");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function ensureViteConfigTsconfig(targetRoot) {
|
|
208
|
+
// create-vite scaffolds `tsconfig.node.json` (the project that compiles
|
|
209
|
+
// vite.config.ts) with `"module": "nodenext"`. Under nodenext, TypeScript
|
|
210
|
+
// decides a dependency's .d.ts is CJS or ESM from that package's own
|
|
211
|
+
// `type` field — and vite-plugin-wasm / vite-plugin-top-level-await ship
|
|
212
|
+
// ESM-only `dist/*.d.ts` without declaring `"type": "module"`. Both are
|
|
213
|
+
// therefore read as CJS, so `import wasm from "vite-plugin-wasm"` resolves
|
|
214
|
+
// to the module namespace rather than the default export and the build
|
|
215
|
+
// dies with `TS2349: This expression is not callable`.
|
|
216
|
+
//
|
|
217
|
+
// Bundler resolution is what actually matches how Vite loads its own
|
|
218
|
+
// config, and it does not apply that CJS/ESM detection. Patch it back.
|
|
219
|
+
const tsconfigPath = join(targetRoot, "tsconfig.node.json");
|
|
220
|
+
if (!existsSync(tsconfigPath)) {
|
|
221
|
+
logStep("No tsconfig.node.json found after scaffolding; nothing to patch");
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const raw = readFileSync(tsconfigPath, "utf8");
|
|
226
|
+
let tsconfig;
|
|
227
|
+
try {
|
|
228
|
+
tsconfig = JSON.parse(stripJsonComments(raw));
|
|
229
|
+
} catch {
|
|
230
|
+
logStep("Could not parse tsconfig.node.json; leaving it untouched");
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const options = tsconfig.compilerOptions ?? {};
|
|
235
|
+
if (options.moduleResolution === "bundler" && options.module === "esnext") {
|
|
236
|
+
logStep("tsconfig.node.json already uses bundler resolution");
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
options.module = "esnext";
|
|
241
|
+
options.moduleResolution = "bundler";
|
|
242
|
+
tsconfig.compilerOptions = options;
|
|
243
|
+
writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
|
|
244
|
+
logStep("Set bundler module resolution for vite.config.ts");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// tsconfig files scaffolded by create-vite carry `/* ... */` comments, which
|
|
248
|
+
// JSON.parse rejects. Strip them rather than pulling in a dependency.
|
|
249
|
+
function stripJsonComments(text) {
|
|
250
|
+
return text
|
|
251
|
+
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
252
|
+
.replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function ensureNpmRc(targetRoot) {
|
|
256
|
+
const npmrcPath = join(targetRoot, ".npmrc");
|
|
257
|
+
const line = "legacy-peer-deps=true";
|
|
258
|
+
if (existsSync(npmrcPath)) {
|
|
259
|
+
const contents = readFileSync(npmrcPath, "utf8");
|
|
260
|
+
if (contents.includes(line)) {
|
|
261
|
+
logStep("Existing .npmrc already opts into legacy-peer-deps");
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
writeFileSync(npmrcPath, `${contents.trim()}\n${line}\n`);
|
|
265
|
+
logStep("Updated .npmrc to include legacy-peer-deps");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
writeFileSync(npmrcPath, `${line}\n`);
|
|
269
|
+
logStep("Created .npmrc with legacy-peer-deps=true");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function ensureMidenParaDependencies(targetRoot) {
|
|
273
|
+
const pkgPath = join(targetRoot, "package.json");
|
|
274
|
+
if (!existsSync(pkgPath)) {
|
|
275
|
+
logStep("No package.json found after scaffolding; cannot add dependencies");
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
280
|
+
pkg.dependencies = pkg.dependencies ?? {};
|
|
281
|
+
pkg.devDependencies = pkg.devDependencies ?? {};
|
|
282
|
+
pkg.resolutions = pkg.resolutions ?? {};
|
|
283
|
+
pkg.scripts = pkg.scripts ?? {};
|
|
284
|
+
const midenParaVersion = useLocalDeps
|
|
285
|
+
? `file:${localMidenParaPath}`
|
|
286
|
+
: "0.15.1";
|
|
287
|
+
const useMidenParaReactVersion = useLocalDeps
|
|
288
|
+
? `file:${localUseMidenParaReactPath}`
|
|
289
|
+
: "^0.15.1";
|
|
290
|
+
// Align with examples/react-signer so Para SDK connector peers are satisfied
|
|
291
|
+
Object.assign(pkg.dependencies, {
|
|
292
|
+
...pkg.dependencies,
|
|
293
|
+
"@getpara/react-sdk-lite": "^2.2.0",
|
|
294
|
+
"@getpara/evm-wallet-connectors": "^2.2.0",
|
|
295
|
+
"@miden-sdk/miden-sdk": "^0.15.1",
|
|
296
|
+
"@miden-sdk/para": midenParaVersion,
|
|
297
|
+
"@miden-sdk/para-react": useMidenParaReactVersion,
|
|
298
|
+
"@miden-sdk/react": "^0.15.1",
|
|
299
|
+
"@tanstack/react-query": "^5.0.0",
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
Object.assign(pkg.devDependencies, {
|
|
303
|
+
...pkg.devDependencies,
|
|
304
|
+
"vite-plugin-node-polyfills": "^0.24.0",
|
|
305
|
+
"vite-plugin-wasm": "^3.5.0",
|
|
306
|
+
"vite-plugin-top-level-await": "^1.6.0",
|
|
307
|
+
// See ensurePolyfillDependency() — vite 8 dropped rollup/esbuild, so the
|
|
308
|
+
// top-level-await plugin's implicit requires need explicit pins.
|
|
309
|
+
rollup: "^4.0.0",
|
|
310
|
+
esbuild: "^0.27.0",
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
Object.assign(pkg.resolutions, {
|
|
314
|
+
"@getpara/react-sdk": "2.0.0-alpha.73",
|
|
315
|
+
"@getpara/web-sdk": "2.0.0-alpha.73",
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
Object.assign(pkg.scripts, {
|
|
319
|
+
...pkg.scripts,
|
|
320
|
+
postinstall: "setup-para",
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
delete pkg.peerDependencies;
|
|
324
|
+
|
|
325
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
326
|
+
logStep("Added Para + Miden starter dependencies");
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function installDependencies(targetRoot) {
|
|
330
|
+
const pm = detectPackageManager();
|
|
331
|
+
logStep(`Installing dependencies with ${pm.command}`);
|
|
332
|
+
runOrExit(pm.command, pm.args, targetRoot);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function detectPackageManager() {
|
|
336
|
+
const ua = process.env.npm_config_user_agent || "";
|
|
337
|
+
if (ua.startsWith("pnpm")) return { command: "pnpm", args: ["install"] };
|
|
338
|
+
if (ua.startsWith("yarn")) return { command: "yarn", args: [] };
|
|
339
|
+
if (ua.startsWith("bun")) return { command: "bun", args: ["install"] };
|
|
340
|
+
return { command: "npm", args: ["install"] };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function runOrExit(command, args, cwd, env, input) {
|
|
344
|
+
const result = spawnSync(command, args, {
|
|
345
|
+
stdio: input ? ["pipe", "inherit", "inherit"] : "inherit",
|
|
346
|
+
input,
|
|
347
|
+
cwd,
|
|
348
|
+
env,
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
if (result.error) {
|
|
352
|
+
console.error(result.error);
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (result.status !== 0) {
|
|
357
|
+
process.exit(result.status ?? 1);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function logStep(message) {
|
|
362
|
+
console.log(`\n> ${message}`);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function logEnvReminder(dirName) {
|
|
366
|
+
logStep(
|
|
367
|
+
`Remember to use VITE_PARA_API_KEY like this:\n cd ${dirName}\n VITE_PARA_API_KEY=... npm run dev`
|
|
368
|
+
);
|
|
369
|
+
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miden-sdk/create-para-react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.16.0-rc.6",
|
|
4
|
+
"description": "Create a Vite react-ts app preconfigured with Miden + Para's Vite setup",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": "./bin/create-miden-para-react.mjs",
|
|
7
|
+
"files": [
|
|
8
|
+
"bin",
|
|
9
|
+
"template",
|
|
10
|
+
"README.md",
|
|
11
|
+
"package.json"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
},
|
|
5
16
|
"license": "MIT",
|
|
6
17
|
"author": "Miden Contributors",
|
|
7
18
|
"repository": {
|
|
8
19
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/0xMiden/web-sdk.git"
|
|
20
|
+
"url": "git+https://github.com/0xMiden/web-sdk.git",
|
|
21
|
+
"directory": "packages/para/create"
|
|
10
22
|
},
|
|
11
23
|
"bugs": {
|
|
12
24
|
"url": "https://github.com/0xMiden/web-sdk/issues"
|
|
13
25
|
},
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"create-vite",
|
|
31
|
+
"vite",
|
|
32
|
+
"react",
|
|
33
|
+
"typescript",
|
|
34
|
+
"miden",
|
|
35
|
+
"para"
|
|
36
|
+
],
|
|
37
|
+
"homepage": "https://github.com/0xMiden/web-sdk"
|
|
38
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import "./App.css";
|
|
2
|
+
import "@getpara/react-sdk-lite/styles.css";
|
|
3
|
+
import { ParaSignerProvider, useParaSigner } from "@miden-sdk/para-react";
|
|
4
|
+
import { MidenProvider, useSigner, useMiden } from "@miden-sdk/react";
|
|
5
|
+
|
|
6
|
+
function App() {
|
|
7
|
+
return (
|
|
8
|
+
<ParaSignerProvider
|
|
9
|
+
apiKey={import.meta.env.VITE_PARA_API_KEY}
|
|
10
|
+
environment="BETA"
|
|
11
|
+
appName="Starter for MidenxPara"
|
|
12
|
+
>
|
|
13
|
+
<MidenProvider config={{ rpcUrl: "testnet" }}>
|
|
14
|
+
<Content />
|
|
15
|
+
</MidenProvider>
|
|
16
|
+
</ParaSignerProvider>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function Content() {
|
|
21
|
+
const signer = useSigner();
|
|
22
|
+
const { wallet } = useParaSigner();
|
|
23
|
+
const { isReady, signerAccountId } = useMiden();
|
|
24
|
+
|
|
25
|
+
const handleConnect = async () => {
|
|
26
|
+
if (signer?.isConnected) {
|
|
27
|
+
await signer.disconnect();
|
|
28
|
+
} else {
|
|
29
|
+
await signer?.connect();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div>
|
|
35
|
+
<button onClick={handleConnect}>
|
|
36
|
+
{signer?.isConnected ? "Disconnect Para" : "Connect with Para"}
|
|
37
|
+
</button>
|
|
38
|
+
{signer?.isConnected && (
|
|
39
|
+
<>
|
|
40
|
+
<p>Wallet: {wallet?.address ?? "—"}</p>
|
|
41
|
+
<p>Account: {signerAccountId ?? "—"}</p>
|
|
42
|
+
<p>Client ready: {isReady ? "yes" : "no"}</p>
|
|
43
|
+
</>
|
|
44
|
+
)}
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default App;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Buffer } from "buffer";
|
|
2
|
+
import process from "process";
|
|
3
|
+
|
|
4
|
+
// Ensure Node globals exist when dependencies expect them in the browser.
|
|
5
|
+
if (!globalThis.Buffer) {
|
|
6
|
+
globalThis.Buffer = Buffer;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (!globalThis.process) {
|
|
10
|
+
globalThis.process = process;
|
|
11
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
import { nodePolyfills } from "vite-plugin-node-polyfills";
|
|
4
|
+
import wasm from "vite-plugin-wasm";
|
|
5
|
+
import topLevelAwait from "vite-plugin-top-level-await";
|
|
6
|
+
|
|
7
|
+
// Optional connector families that are never imported by the starter template.
|
|
8
|
+
// Alias them to an empty module so Vite doesn't try to resolve their deps.
|
|
9
|
+
// @getpara/aa-* packages are lazy `import()`ed by @getpara/react-core but the
|
|
10
|
+
// rolldown bundler in Vite 8 still fails if they can't be resolved at build time.
|
|
11
|
+
const optionalPackages = [
|
|
12
|
+
"@getpara/solana-wallet-connectors",
|
|
13
|
+
"@getpara/cosmos-wallet-connectors",
|
|
14
|
+
"@getpara/wagmi-v2-connector",
|
|
15
|
+
"@getpara/aa-alchemy",
|
|
16
|
+
"@getpara/aa-biconomy",
|
|
17
|
+
"@getpara/aa-cdp",
|
|
18
|
+
"@getpara/aa-gelato",
|
|
19
|
+
"@getpara/aa-pimlico",
|
|
20
|
+
"@getpara/aa-porto",
|
|
21
|
+
"@getpara/aa-rhinestone",
|
|
22
|
+
"@getpara/aa-safe",
|
|
23
|
+
"@getpara/aa-thirdweb",
|
|
24
|
+
"@getpara/aa-zerodev",
|
|
25
|
+
"wagmi",
|
|
26
|
+
"@wagmi/core",
|
|
27
|
+
"@wagmi/connectors",
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// Mark any import whose bare specifier starts with an optional package
|
|
31
|
+
// (including subpath imports like "wagmi/connectors") as external so
|
|
32
|
+
// Rollup skips them entirely. These code paths are never reached at runtime.
|
|
33
|
+
function externalizeOptionalPackages() {
|
|
34
|
+
return {
|
|
35
|
+
name: "externalize-optional-packages",
|
|
36
|
+
enforce: "pre" as const,
|
|
37
|
+
resolveId(id: string) {
|
|
38
|
+
if (
|
|
39
|
+
optionalPackages.some((pkg) => id === pkg || id.startsWith(pkg + "/"))
|
|
40
|
+
) {
|
|
41
|
+
return { id, external: true };
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Keep the miden SDK unbundled so its WASM asset path stays valid in dev.
|
|
48
|
+
export default defineConfig({
|
|
49
|
+
plugins: [
|
|
50
|
+
externalizeOptionalPackages(),
|
|
51
|
+
wasm(),
|
|
52
|
+
topLevelAwait(),
|
|
53
|
+
react(),
|
|
54
|
+
nodePolyfills({
|
|
55
|
+
include: ["buffer", "crypto", "stream", "util"],
|
|
56
|
+
}),
|
|
57
|
+
],
|
|
58
|
+
optimizeDeps: {
|
|
59
|
+
// Keep Miden SDK unbundled and avoid prebundling Para's Stencil component bundles
|
|
60
|
+
// to prevent multiple runtimes in dev.
|
|
61
|
+
exclude: ["@miden-sdk/miden-sdk", ...optionalPackages],
|
|
62
|
+
esbuildOptions: {
|
|
63
|
+
target: "esnext",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
build: {
|
|
67
|
+
target: "esnext",
|
|
68
|
+
},
|
|
69
|
+
worker: {
|
|
70
|
+
format: "es",
|
|
71
|
+
},
|
|
72
|
+
resolve: {
|
|
73
|
+
dedupe: [
|
|
74
|
+
"@getpara/web-sdk",
|
|
75
|
+
"@getpara/react-sdk-lite",
|
|
76
|
+
"react",
|
|
77
|
+
"react-dom",
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
// Ensure Vite treats wasm as a static asset with the correct MIME type.
|
|
81
|
+
assetsInclude: ["**/*.wasm"],
|
|
82
|
+
server: {
|
|
83
|
+
fs: {
|
|
84
|
+
allow: [process.cwd()],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
});
|