Skip to content

Commit

Permalink
Migrate to Next.js v14.2.3 and fix latest o1js usage issue. (#652)
Browse files Browse the repository at this point in the history
Co-authored-by: Yoni Mekuria <[email protected]>
  • Loading branch information
shimkiv and ymekuria authored May 20, 2024
1 parent 57e7f68 commit 5d6eeb4
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 82 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## Unreleased

## [0.21.2](https://github.com/o1-labs/zkapp-cli/compare/0.21.0...0.21.2) - 2024-05-20

### Changed

- Migrate **Next.js** UI scaffold to **Next.js** `v14.2.3` and fix the latest `o1js` usage issue. [#652](https://github.com/o1-labs/zkapp-cli/pull/652)

## [0.21.0](https://github.com/o1-labs/zkapp-cli/compare/0.20.1...0.21.0) - 2024-05-16

### Breaking changes
Expand All @@ -26,7 +32,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Changed

- Update ZkProgram proof detection during deployment [#649](https://github.com/o1-labs/zkapp-cli/pull/649)

- Improved `SmartContract` classes inheritance lookup used during the zkApps deployment procedure. [#640](https://github.com/o1-labs/zkapp-cli/pull/640)

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zkapp-cli",
"version": "0.21.1",
"version": "0.21.2",
"description": "CLI to create zkApps (zero-knowledge apps) for Mina Protocol",
"homepage": "https://github.com/o1-labs/zkapp-cli/",
"keywords": [
Expand Down
124 changes: 61 additions & 63 deletions src/lib/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export async function project({ name, ui }) {
// Add dependencies object if none is found in the package.json because generated
// SvelteKit projects do not have dependencies included.
if (!pkgJson.dependencies) pkgJson['dependencies'] = {};
pkgJson.dependencies.o1js = '0.*';
pkgJson.dependencies.o1js = '^1.*';
fs.writeJSONSync(path.join('ui', 'package.json'), pkgJson, { spaces: 2 });

// Use `install`, not `ci`, b/c these won't have package-lock.json yet.
Expand Down Expand Up @@ -268,7 +268,7 @@ function scaffoldSvelte() {
path.join('ui', 'src')
);

const customTsConfig = ` {
const customTsConfig = `{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"target": "es2020",
Expand Down Expand Up @@ -394,7 +394,7 @@ async function scaffoldNext(projectName) {
// set the project name and default flags
// https://nextjs.org/docs/api-reference/create-next-app#options
let args = [
'create-next-app@13.4.1',
'create-next-app@14.2.3',
'ui',
'--use-npm',
'--src-dir',
Expand All @@ -421,17 +421,15 @@ async function scaffoldNext(projectName) {
useTypescript = false;
}

const nextConfig = fs.readFileSync(path.join('ui', 'next.config.js'), 'utf8');
const nextConfig = fs.readFileSync(
path.join('ui', 'next.config.mjs'),
'utf8'
);

let newNextConfig = nextConfig.replace(
/^}(.*?)$/gm, // Search for the last '}' in the file.
/^};(.*?)$/gm, // Search for the last '};' in the file.
`
webpack(config) {
config.resolve.alias = {
...config.resolve.alias,
o1js: require('path').resolve('node_modules/o1js')
};
config.experiments = { ...config.experiments, topLevelAwait: true };
return config;
},
Expand Down Expand Up @@ -463,7 +461,7 @@ async function scaffoldNext(projectName) {
'reactStrictMode: false'
);

fs.writeFileSync(path.join('ui', 'next.config.js'), newNextConfig);
fs.writeFileSync(path.join('ui', 'next.config.mjs'), newNextConfig);

const indexFileName = useTypescript ? 'index.tsx' : 'index.js';

Expand Down Expand Up @@ -494,58 +492,60 @@ async function scaffoldNext(projectName) {
path.join('ui', 'public', 'assets')
);

const tsconfig = `
{
"compilerOptions": {
"target": "es2020",
"module": "esnext",
"lib": ["dom", "dom.iterable","esnext"],
"strict": true,
"strictPropertyInitialization": false, // to enable generic constructors, e.g. on CircuitValue
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowJs": true,
"declaration": true,
"sourceMap": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
"noEmit": true,
"incremental": true,
"resolveJsonModule": true,
"jsx": "preserve",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
const tsconfig = `{
"compilerOptions": {
"target": "es2020",
"module": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"strict": true,
"strictPropertyInitialization": false, // to enable generic constructors, e.g. on CircuitValue
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowJs": true,
"declaration": true,
"sourceMap": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
"noEmit": true,
"incremental": true,
"resolveJsonModule": true,
"jsx": "preserve",
"paths": {
"@/*": ["./src/*"]
}
`;
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
`;

if (useTypescript) {
fs.writeFileSync(path.join('ui', 'tsconfig.json'), tsconfig);

// Add a script to the package.json
let x = fs.readJsonSync(path.join('ui', 'package.json'));
x.scripts['ts-watch'] = 'tsc --noEmit --incremental --watch';
x.scripts['build'] = 'next build --no-lint';
x.type = 'module';
fs.writeJSONSync(path.join('ui', 'package.json'), x, { spaces: 2 });
}

if (useGHPages) {
const nextConfig = fs.readFileSync(
path.join('ui', 'next.config.js'),
path.join('ui', 'next.config.mjs'),
'utf8'
);

console.log(
'Using project name ' +
projectName +
' for GitHub repo name. Change in next.config.js and pages/reactCOIServiceWorker.tsx if this is not correct or changes'
`Using project name '${projectName}' as the GitHub repository name.`
);
console.log(
"Please update it in 'next.config.mjs' and 'pages/reactCOIServiceWorker.tsx' files if this is not correct or if it will be changed.\n"
);

let newNextConfig = nextConfig.replace(
Expand All @@ -555,15 +555,15 @@ async function scaffoldNext(projectName) {
unoptimized: true,
},
output: 'export',
/* Used to serve the Next.js app from a subdirectory (the GitHub repo name) and
* assetPrefix is used to serve assets (JS, CSS, images, etc.) from that subdirectory
/* Used to serve the Next.js app from a subdirectory (the GitHub repo name) and
* assetPrefix is used to serve assets (JS, CSS, images, etc.) from that subdirectory
* when deployed to GitHub Pages. The assetPrefix needs to be added manually to any assets
* if they're not loaded by Next.js' automatic handling (for example, in CSS files or in a <img> element).
* The 'ghp-postbuild.js' script in this project prepends the repo name to asset urls in the built css files
* if they're not loaded by Next.js' automatic handling (for example, in CSS files or in a <img> element).
* The 'ghp-postbuild.js' script in this project prepends the repo name to asset urls in the built css files
* after runing 'npm run deploy'.
*/
basePath: process.env.NODE_ENV === 'production' ? '/${projectName}' : '', // update if your repo name changes for 'npm run deploy' to work successfully
assetPrefix: process.env.NODE_ENV === 'production' ? '/${projectName}/' : '', // update if your repo name changes for 'npm run deploy' to work successfully
basePath: process.env.NODE_ENV === 'production' ? '/${projectName}' : '', // update if your repo name changes for 'npm run deploy' to work correctly
assetPrefix: process.env.NODE_ENV === 'production' ? '/${projectName}/' : '', // update if your repo name changes for 'npm run deploy' to work correctly
};`
);

Expand All @@ -580,12 +580,11 @@ async function scaffoldNext(projectName) {
pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],`
);

fs.writeFileSync(path.join('ui', 'next.config.js'), newNextConfig);
fs.writeFileSync(path.join('ui', 'next.config.mjs'), newNextConfig);

// Add some scripts to the package.json
let x = fs.readJsonSync(`ui/package.json`);
x.scripts['export'] = 'next export';
const deployScript = `next build && next export && ${
const deployScript = `next build --no-lint && ${
isWindows
? `type nul > ${path.join('out', '.nojekyll')}`
: `touch ${path.join('out', '.nojekyll')}`
Expand Down Expand Up @@ -647,13 +646,15 @@ export default function`

fs.writeFileSync(
path.join('ui', 'src', 'pages', reactCOIServiceWorkerFileName),
`
export {}
`export {};
function loadCOIServiceWorker() {
if (typeof window !== 'undefined' && window.location.hostname != 'localhost') {
if (
typeof window !== 'undefined' &&
window.location.hostname != 'localhost'
) {
const coi = window.document.createElement('script');
coi.setAttribute('src','/${projectName}/coi-serviceworker.min.js'); // update if your repo name changes for npm run deploy to work successfully
coi.setAttribute('src', '/${projectName}/coi-serviceworker.min.js'); // update if your repo name changes for 'npm run deploy' to work correctly
window.document.head.appendChild(coi);
}
}
Expand Down Expand Up @@ -697,14 +698,11 @@ function scaffoldNuxt() {
const nuxtConfig = fs.readFileSync(path.join('ui', 'nuxt.config.ts'), 'utf8');
let newNuxtConfig = nuxtConfig.replace(
'export default defineNuxtConfig({',
`
export default defineNuxtConfig({
`export default defineNuxtConfig({
vite: {
build: { target: "esnext" },
optimizeDeps: { esbuildOptions: { target: "esnext" } },
},
css: ['~/assets/styles/globals.css'],
`
);
Expand Down
27 changes: 13 additions & 14 deletions src/lib/ui/next/ghp-postbuild.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
const fs = require('fs');
const path = require('path');
import { readdirSync, readFileSync, writeFileSync } from 'fs';
import { dirname, extname, join } from 'path';
import { fileURLToPath } from 'url';

// This script modifies the built CSS files and prepends the repo-name to the asset URLs.
// to be compatible with github pages deployment.
const cssDir = path.join(__dirname, '/out/_next/static/css');
// This script modifies the built CSS files and prepends the repo-name to the asset URLs
// to be compatible with the GitHub pages deployments.
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const cssDir = join(__dirname, '/out/_next/static/css');

// Update your repository name here if it is different from the project name.
let repoURL = '';
const files = fs.readdirSync(cssDir);
const files = readdirSync(cssDir);

files.forEach((file) => {
if (path.extname(file) === '.css') {
const filePath = path.join(cssDir, file);

const data = fs.readFileSync(filePath, 'utf8');

if (extname(file) === '.css') {
const filePath = join(cssDir, file);
const data = readFileSync(filePath, 'utf8');
const singleQuoteRegex = new RegExp(`url\\(\\s*'\\/(?!${repoURL})`, 'g');
const doubleQuoteRegex = new RegExp(`url\\(\\s*"\\/(?!${repoURL})`, 'g');

let result = data.replace(singleQuoteRegex, `url('/${repoURL}/`);
result = result.replace(doubleQuoteRegex, `url("/${repoURL}/`);

fs.writeFileSync(filePath, result, 'utf8');
writeFileSync(filePath, result, 'utf8');
}
});
2 changes: 1 addition & 1 deletion templates/project-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"typescript": "^5.1"
},
"peerDependencies": {
"o1js": "1.*"
"o1js": "^1.*"
},
"engines": {
"node": ">=18.14.0"
Expand Down

0 comments on commit 5d6eeb4

Please sign in to comment.