create-stylus 1.1.0
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/.github/issue_template.md +7 -0
- package/.github/pull_request_template.md +11 -0
- package/.github/workflows/release-alpha.yml +32 -0
- package/.yarnrc.yml +1 -0
- package/CONTRIBUTING.md +42 -0
- package/README.md +66 -0
- package/bin/create-dapp-ss.js +4 -0
- package/dist/cli.js +656 -0
- package/dist/cli.js.map +1 -0
- package/package.json +46 -0
- package/rollup.config.js +22 -0
- package/src/cli.ts +14 -0
- package/src/extensions.json +14 -0
- package/src/main.ts +70 -0
- package/src/tasks/copy-extension-file.ts +227 -0
- package/src/tasks/copy-template-files.ts +252 -0
- package/src/tasks/create-first-git-commit.ts +35 -0
- package/src/tasks/create-project-directory.ts +34 -0
- package/src/tasks/index.ts +5 -0
- package/src/tasks/install-packages.ts +15 -0
- package/src/tasks/prettier-format.ts +17 -0
- package/src/types.ts +31 -0
- package/src/utils/consts.ts +1 -0
- package/src/utils/find-files-recursively.ts +19 -0
- package/src/utils/link.ts +44 -0
- package/src/utils/load-extensions.ts +10 -0
- package/src/utils/merge-package-json.ts +33 -0
- package/src/utils/parse-arguments-into-options.ts +38 -0
- package/src/utils/prompt-for-missing-options.ts +53 -0
- package/src/utils/render-intro-message.ts +11 -0
- package/src/utils/render-outro-message.ts +34 -0
- package/templates/base/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
- package/templates/base/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/templates/base/.github/pull_request_template.md +16 -0
- package/templates/base/.github/workflows/lint.yaml +300 -0
- package/templates/base/.gitignore.template.mjs +19 -0
- package/templates/base/.gitmodules +0 -0
- package/templates/base/.husky/pre-commit +4 -0
- package/templates/base/.lintstagedrc.js +21 -0
- package/templates/base/.vscode/settings.json +7 -0
- package/templates/base/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
- package/templates/base/.yarn/releases/yarn-3.2.3.cjs +783 -0
- package/templates/base/.yarnrc.yml +11 -0
- package/templates/base/CONTRIBUTING.md +86 -0
- package/templates/base/LICENCE +21 -0
- package/templates/base/nitro-devnode/LICENSE +201 -0
- package/templates/base/nitro-devnode/README.md +70 -0
- package/templates/base/nitro-devnode/run-dev-node.sh +132 -0
- package/templates/base/nitro-devnode/start-chain-with-cors.sh +150 -0
- package/templates/base/nitro-devnode/stylus-deployer-bytecode.txt +1 -0
- package/templates/base/nitro-devnode/stylus-dev/Dockerfile +10 -0
- package/templates/base/package.json +43 -0
- package/templates/base/packages/nextjs/.env.example +13 -0
- package/templates/base/packages/nextjs/.eslintignore +11 -0
- package/templates/base/packages/nextjs/.eslintrc.json +15 -0
- package/templates/base/packages/nextjs/.gitignore.template.mjs +42 -0
- package/templates/base/packages/nextjs/.prettierrc.js +9 -0
- package/templates/base/packages/nextjs/.prettierrc.json +8 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressCodeTab.tsx +27 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressComponent.tsx +36 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressLogsTab.tsx +21 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressStorageTab.tsx +61 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/BackButton.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx +102 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/PaginationButton.tsx +39 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/SearchBar.tsx +49 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionHash.tsx +28 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionsTable.tsx +71 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/index.tsx +7 -0
- package/templates/base/packages/nextjs/app/blockexplorer/address/[address]/page.tsx +101 -0
- package/templates/base/packages/nextjs/app/blockexplorer/layout.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/page.tsx +83 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx +23 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx +152 -0
- package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +73 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +84 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractReadMethods.tsx +43 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +164 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractVariables.tsx +50 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx +49 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +85 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/InheritanceTooltip.tsx +14 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +102 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/Tuple.tsx +44 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TupleArray.tsx +142 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +42 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +144 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/index.tsx +8 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsContract.tsx +166 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +114 -0
- package/templates/base/packages/nextjs/app/debug/page.tsx +14 -0
- package/templates/base/packages/nextjs/app/layout.tsx +67 -0
- package/templates/base/packages/nextjs/app/not-found.tsx +16 -0
- package/templates/base/packages/nextjs/app/page.tsx +94 -0
- package/templates/base/packages/nextjs/components/Background.tsx +37 -0
- package/templates/base/packages/nextjs/components/Card.tsx +40 -0
- package/templates/base/packages/nextjs/components/Footer.tsx +93 -0
- package/templates/base/packages/nextjs/components/Header.tsx +114 -0
- package/templates/base/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +77 -0
- package/templates/base/packages/nextjs/components/SwitchTheme.tsx +41 -0
- package/templates/base/packages/nextjs/components/ThemeProvider.tsx +13 -0
- package/templates/base/packages/nextjs/components/assets/BuidlGuidlLogo.tsx +18 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/Address.tsx +187 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressCopyIcon.tsx +23 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressLinkWrapper.tsx +29 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Balance.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/BlockieAvatar.tsx +17 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +131 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +120 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/Bytes32Input.tsx +31 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/BytesInput.tsx +28 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/EtherInput.tsx +128 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +66 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/index.ts +9 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/utils.ts +109 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +121 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressQRCodeModal.tsx +33 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/BurnerWalletModal.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/NetworkOptions.tsx +48 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/WrongNetworkDropdown.tsx +32 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +89 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/index.tsx +7 -0
- package/templates/base/packages/nextjs/contracts/deployedContracts.ts +9 -0
- package/templates/base/packages/nextjs/contracts/externalContracts.ts +16 -0
- package/templates/base/packages/nextjs/eslint.config.mjs +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/index.ts +17 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useAnimationConfig.ts +20 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useContractLogs.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useCopyToClipboard.ts +19 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts +86 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDisplayUsdMode.ts +21 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useFetchBlocks.ts +133 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useInitializeNativeCurrencyPrice.ts +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNativeCurrencyPrice.ts +34 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts +22 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useOutsideClick.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts +65 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +213 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts +80 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWatchContractEvent.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +191 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useSelectedNetwork.ts +18 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTargetNetwork.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +114 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useWatchBalance.ts +21 -0
- package/templates/base/packages/nextjs/icons/CompassIcon.tsx +39 -0
- package/templates/base/packages/nextjs/icons/DarkBugAntIcon.tsx +30 -0
- package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +52 -0
- package/templates/base/packages/nextjs/next-env.d.ts +5 -0
- package/templates/base/packages/nextjs/next.config.js +19 -0
- package/templates/base/packages/nextjs/package.json +58 -0
- package/templates/base/packages/nextjs/postcss.config.js +6 -0
- package/templates/base/packages/nextjs/public/debug-image.png +0 -0
- package/templates/base/packages/nextjs/public/favicon.png +0 -0
- package/templates/base/packages/nextjs/public/logo.svg +8 -0
- package/templates/base/packages/nextjs/public/manifest.json +5 -0
- package/templates/base/packages/nextjs/public/thumbnail.jpg +0 -0
- package/templates/base/packages/nextjs/react-copy-to-clipboard.d.ts +44 -0
- package/templates/base/packages/nextjs/scaffold.config.ts +56 -0
- package/templates/base/packages/nextjs/services/store/store.ts +39 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConfig.tsx +44 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +51 -0
- package/templates/base/packages/nextjs/styles/globals.css +80 -0
- package/templates/base/packages/nextjs/tailwind.config.js +97 -0
- package/templates/base/packages/nextjs/tsconfig.json +28 -0
- package/templates/base/packages/nextjs/types/abitype/abi.d.ts +16 -0
- package/templates/base/packages/nextjs/types/utils.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/block.ts +17 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/common.ts +8 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +352 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contractsData.ts +11 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/decodeTxData.ts +65 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/fetchPriceFromUniswap.ts +72 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getMetadata.ts +50 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getParsedError.ts +35 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/index.ts +6 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/notification.tsx +90 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/burner.ts +59 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/chain.ts +42 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/index.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/networks.ts +94 -0
- package/templates/base/packages/nextjs/vercel.json +3 -0
- package/templates/base/packages/stylus/.env.example +13 -0
- package/templates/base/packages/stylus/.eslintrc.js +23 -0
- package/templates/base/packages/stylus/.gitignore.template.mjs +7 -0
- package/templates/base/packages/stylus/README.md +263 -0
- package/templates/base/packages/stylus/header.png +0 -0
- package/templates/base/packages/stylus/jest.config.js +15 -0
- package/templates/base/packages/stylus/package.json +49 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +29 -0
- package/templates/base/packages/stylus/scripts/deploy_all_contracts.ts +59 -0
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +93 -0
- package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +79 -0
- package/templates/base/packages/stylus/scripts/export_abi.ts +87 -0
- package/templates/base/packages/stylus/scripts/index.ts +0 -0
- package/templates/base/packages/stylus/scripts/new_module.sh +35 -0
- package/templates/base/packages/stylus/scripts/test_network.ts +31 -0
- package/templates/base/packages/stylus/scripts/utils/command.ts +165 -0
- package/templates/base/packages/stylus/scripts/utils/contract.ts +219 -0
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +136 -0
- package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
- package/templates/base/packages/stylus/scripts/utils/network.ts +112 -0
- package/templates/base/packages/stylus/scripts/utils/type.ts +48 -0
- package/templates/base/packages/stylus/scripts/utils.ts +3 -0
- package/templates/base/packages/stylus/tsconfig.json +41 -0
- package/templates/base/packages/stylus/your-contract/.cargo/config.toml +18 -0
- package/templates/base/packages/stylus/your-contract/Cargo.lock +5744 -0
- package/templates/base/packages/stylus/your-contract/Cargo.toml +46 -0
- package/templates/base/packages/stylus/your-contract/examples/counter.rs +78 -0
- package/templates/base/packages/stylus/your-contract/header.png +0 -0
- package/templates/base/packages/stylus/your-contract/licenses/Apache-2.0 +201 -0
- package/templates/base/packages/stylus/your-contract/licenses/COPYRIGHT.md +5 -0
- package/templates/base/packages/stylus/your-contract/licenses/DCO.txt +34 -0
- package/templates/base/packages/stylus/your-contract/licenses/MIT +21 -0
- package/templates/base/packages/stylus/your-contract/rust-toolchain.toml +2 -0
- package/templates/base/packages/stylus/your-contract/src/lib.rs +211 -0
- package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
- package/templates/base/readme.md +187 -0
- package/templates/base/yarn.lock +17860 -0
- package/tsconfig.json +13 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import fs, { promises, lstatSync, readdirSync, existsSync } from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import mergeJsonStr from 'merge-packages';
|
|
5
|
+
import url, { fileURLToPath } from 'url';
|
|
6
|
+
import ncp from 'ncp';
|
|
7
|
+
import { promisify } from 'util';
|
|
8
|
+
import { projectInstall } from 'pkg-install';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import Listr from 'listr';
|
|
11
|
+
import arg from 'arg';
|
|
12
|
+
import inquirer from 'inquirer';
|
|
13
|
+
|
|
14
|
+
const baseDir = "base";
|
|
15
|
+
|
|
16
|
+
const findFilesRecursiveSync = (baseDir, criteriaFn = () => true) => {
|
|
17
|
+
const subPaths = fs.readdirSync(baseDir);
|
|
18
|
+
const files = subPaths.map((relativePath) => {
|
|
19
|
+
const fullPath = path.resolve(baseDir, relativePath);
|
|
20
|
+
return fs.lstatSync(fullPath).isDirectory()
|
|
21
|
+
? [...findFilesRecursiveSync(fullPath, criteriaFn)]
|
|
22
|
+
: criteriaFn(fullPath)
|
|
23
|
+
? [fullPath]
|
|
24
|
+
: [];
|
|
25
|
+
});
|
|
26
|
+
return files.flat();
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// @ts-expect-error We don't have types for this probably add .d.ts file
|
|
30
|
+
function mergePackageJson$1(targetPackageJsonPath, secondPackageJsonPath, isDev) {
|
|
31
|
+
const existsTarget = fs.existsSync(targetPackageJsonPath);
|
|
32
|
+
const existsSecond = fs.existsSync(secondPackageJsonPath);
|
|
33
|
+
if (!existsTarget && !existsSecond) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const targetPackageJson = existsTarget ? fs.readFileSync(targetPackageJsonPath, "utf8") : '{}';
|
|
37
|
+
const secondPackageJson = existsSecond ? fs.readFileSync(secondPackageJsonPath, "utf8") : '{}';
|
|
38
|
+
const mergedPkgStr = mergeJsonStr.default(targetPackageJson, secondPackageJson);
|
|
39
|
+
// Parse and reformat the merged JSON to ensure proper formatting
|
|
40
|
+
const mergedPkgObj = JSON.parse(mergedPkgStr);
|
|
41
|
+
const formattedPkgStr = JSON.stringify(mergedPkgObj, null, 2) + '\n';
|
|
42
|
+
fs.writeFileSync(targetPackageJsonPath, formattedPkgStr, "utf8");
|
|
43
|
+
if (isDev) {
|
|
44
|
+
const devStr = `TODO: write relevant information for the contributor`;
|
|
45
|
+
fs.writeFileSync(`${targetPackageJsonPath}.dev`, devStr, "utf8");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const { mkdir, link } = promises;
|
|
50
|
+
/**
|
|
51
|
+
* The goal is that this function has the same API as ncp, so they can be used
|
|
52
|
+
* interchangeably.
|
|
53
|
+
*
|
|
54
|
+
* - clobber not implemented
|
|
55
|
+
*/
|
|
56
|
+
const linkRecursive = async (source, destination, options) => {
|
|
57
|
+
const passesFilter = options?.filter === undefined
|
|
58
|
+
? true // no filter
|
|
59
|
+
: typeof options.filter === 'function'
|
|
60
|
+
? options.filter(source) // filter is function
|
|
61
|
+
: options.filter.test(source); // filter is regex
|
|
62
|
+
if (!passesFilter) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (lstatSync(source).isDirectory()) {
|
|
66
|
+
const subPaths = readdirSync(source);
|
|
67
|
+
await Promise.all(subPaths.map(async (subPath) => {
|
|
68
|
+
const sourceSubpath = path.join(source, subPath);
|
|
69
|
+
const isSubPathAFolder = lstatSync(sourceSubpath).isDirectory();
|
|
70
|
+
const destSubPath = path.join(destination, subPath);
|
|
71
|
+
const existsDestSubPath = existsSync(destSubPath);
|
|
72
|
+
if (isSubPathAFolder && !existsDestSubPath) {
|
|
73
|
+
await mkdir(destSubPath);
|
|
74
|
+
}
|
|
75
|
+
await linkRecursive(sourceSubpath, destSubPath, options);
|
|
76
|
+
}));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
return link(source, destination);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
var extensions = [
|
|
83
|
+
{
|
|
84
|
+
extensionFlagValue: "erc-20",
|
|
85
|
+
description: "Adds support for ERC-20 token contracts, including balance checks and token transfers.",
|
|
86
|
+
repository: "https://github.com/Arb-Stylus/create-stylus-extensions",
|
|
87
|
+
branch: "erc-20"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
extensionFlagValue: "erc-721",
|
|
91
|
+
description: "Adds support for ERC-721 NFT contracts, including supply, balance, listing, and transfer features.",
|
|
92
|
+
repository: "https://github.com/Arb-Stylus/create-stylus-extensions",
|
|
93
|
+
branch: "erc-721"
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
function loadExtensions() {
|
|
98
|
+
return extensions;
|
|
99
|
+
}
|
|
100
|
+
function findExtensionByFlag(flagValue) {
|
|
101
|
+
return extensions.find((ext) => ext.extensionFlagValue === flagValue);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function copyExtensionFile(extensionName, targetDirectory) {
|
|
105
|
+
if (!extensionName || extensionName.trim() === "") {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const extensionConfig = findExtensionByFlag(extensionName);
|
|
109
|
+
if (!extensionConfig) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const targetPackagesDir = path.join(targetDirectory, "packages");
|
|
113
|
+
if (!fs.existsSync(targetPackagesDir)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const tempDir = path.join(targetDirectory, ".temp-extension");
|
|
118
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
119
|
+
await cloneExtensionRepository(extensionConfig, tempDir);
|
|
120
|
+
await copyExtensionFiles(tempDir, targetPackagesDir, extensionConfig.extensionFlagValue);
|
|
121
|
+
await mergePackageJsonFiles(tempDir, targetPackagesDir, extensionConfig.extensionFlagValue);
|
|
122
|
+
await mergeRootPackageJson(tempDir, targetDirectory, extensionConfig.extensionFlagValue);
|
|
123
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function cloneExtensionRepository(extension, tempDir) {
|
|
130
|
+
try {
|
|
131
|
+
const { stdout, stderr } = await execa("git", [
|
|
132
|
+
"clone",
|
|
133
|
+
"--branch", extension.branch,
|
|
134
|
+
"--single-branch",
|
|
135
|
+
"--depth", "1",
|
|
136
|
+
extension.repository,
|
|
137
|
+
tempDir
|
|
138
|
+
]);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async function copyExtensionFiles(tempDir, targetPackagesDir, extensionName) {
|
|
145
|
+
let extensionPackageDir = path.join(tempDir, "packages", extensionName);
|
|
146
|
+
if (!fs.existsSync(extensionPackageDir)) {
|
|
147
|
+
extensionPackageDir = path.join(tempDir, "extensions", "packages", extensionName);
|
|
148
|
+
}
|
|
149
|
+
if (fs.existsSync(extensionPackageDir)) {
|
|
150
|
+
const targetExtensionDir = path.join(targetPackagesDir, extensionName);
|
|
151
|
+
copyDirectoryRecursive(extensionPackageDir, targetExtensionDir);
|
|
152
|
+
}
|
|
153
|
+
let extensionPackagesDir = path.join(tempDir, "packages");
|
|
154
|
+
if (!fs.existsSync(extensionPackagesDir)) {
|
|
155
|
+
extensionPackagesDir = path.join(tempDir, "extensions", "packages");
|
|
156
|
+
}
|
|
157
|
+
if (fs.existsSync(extensionPackagesDir)) {
|
|
158
|
+
const packages = fs.readdirSync(extensionPackagesDir);
|
|
159
|
+
for (const packageName of packages) {
|
|
160
|
+
if (packageName === extensionName) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const sourcePackageDir = path.join(extensionPackagesDir, packageName);
|
|
164
|
+
const targetPackageDir = path.join(targetPackagesDir, packageName);
|
|
165
|
+
if (fs.existsSync(targetPackageDir)) {
|
|
166
|
+
mergeDirectoryRecursive(sourcePackageDir, targetPackageDir);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
copyDirectoryRecursive(sourcePackageDir, targetPackageDir);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function mergePackageJsonFiles(tempDir, targetPackagesDir, extensionName) {
|
|
175
|
+
let extensionPackagesDir = path.join(tempDir, "packages");
|
|
176
|
+
if (!fs.existsSync(extensionPackagesDir)) {
|
|
177
|
+
extensionPackagesDir = path.join(tempDir, "extensions", "packages");
|
|
178
|
+
}
|
|
179
|
+
if (!fs.existsSync(extensionPackagesDir)) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const packages = fs.readdirSync(extensionPackagesDir);
|
|
183
|
+
for (const packageName of packages) {
|
|
184
|
+
const sourcePackageDir = path.join(extensionPackagesDir, packageName);
|
|
185
|
+
const targetPackageDir = path.join(targetPackagesDir, packageName);
|
|
186
|
+
if (fs.existsSync(targetPackageDir)) {
|
|
187
|
+
const sourcePackageJsonPath = path.join(sourcePackageDir, "package.json");
|
|
188
|
+
const targetPackageJsonPath = path.join(targetPackageDir, "package.json");
|
|
189
|
+
if (fs.existsSync(sourcePackageJsonPath) && fs.existsSync(targetPackageJsonPath)) {
|
|
190
|
+
mergePackageJson(sourcePackageJsonPath, targetPackageJsonPath);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function mergeRootPackageJson(tempDir, targetDirectory, extensionName) {
|
|
196
|
+
let extensionRootPackageJsonPath = path.join(tempDir, "package.json");
|
|
197
|
+
if (!fs.existsSync(extensionRootPackageJsonPath)) {
|
|
198
|
+
extensionRootPackageJsonPath = path.join(tempDir, "extensions", "package.json");
|
|
199
|
+
}
|
|
200
|
+
if (!fs.existsSync(extensionRootPackageJsonPath)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const targetRootPackageJsonPath = path.join(targetDirectory, "package.json");
|
|
204
|
+
if (fs.existsSync(targetRootPackageJsonPath)) {
|
|
205
|
+
mergePackageJson(extensionRootPackageJsonPath, targetRootPackageJsonPath);
|
|
206
|
+
addPackageToWorkspaces(targetRootPackageJsonPath, extensionName);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function mergePackageJson(sourcePath, targetPath) {
|
|
210
|
+
try {
|
|
211
|
+
const sourcePackageJson = JSON.parse(fs.readFileSync(sourcePath, 'utf8'));
|
|
212
|
+
const targetPackageJson = JSON.parse(fs.readFileSync(targetPath, 'utf8'));
|
|
213
|
+
if (sourcePackageJson.scripts && targetPackageJson.scripts) {
|
|
214
|
+
targetPackageJson.scripts = { ...targetPackageJson.scripts, ...sourcePackageJson.scripts };
|
|
215
|
+
}
|
|
216
|
+
if (sourcePackageJson.dependencies && targetPackageJson.dependencies) {
|
|
217
|
+
targetPackageJson.dependencies = { ...targetPackageJson.dependencies, ...sourcePackageJson.dependencies };
|
|
218
|
+
}
|
|
219
|
+
if (sourcePackageJson.devDependencies && targetPackageJson.devDependencies) {
|
|
220
|
+
targetPackageJson.devDependencies = { ...targetPackageJson.devDependencies, ...sourcePackageJson.devDependencies };
|
|
221
|
+
}
|
|
222
|
+
if (sourcePackageJson.peerDependencies && targetPackageJson.peerDependencies) {
|
|
223
|
+
targetPackageJson.peerDependencies = { ...targetPackageJson.peerDependencies, ...sourcePackageJson.peerDependencies };
|
|
224
|
+
}
|
|
225
|
+
fs.writeFileSync(targetPath, JSON.stringify(targetPackageJson, null, 2));
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
// Error handling without logging
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function addPackageToWorkspaces(packageJsonPath, packageName) {
|
|
232
|
+
try {
|
|
233
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
234
|
+
if (packageJson.workspaces && packageJson.workspaces.packages) {
|
|
235
|
+
const workspacePath = `packages/${packageName}`;
|
|
236
|
+
if (!packageJson.workspaces.packages.includes(workspacePath)) {
|
|
237
|
+
packageJson.workspaces.packages.push(workspacePath);
|
|
238
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
// Error handling without logging
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function copyDirectoryRecursive(source, destination) {
|
|
247
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
248
|
+
const files = fs.readdirSync(source);
|
|
249
|
+
for (const file of files) {
|
|
250
|
+
const sourcePath = path.join(source, file);
|
|
251
|
+
const destPath = path.join(destination, file);
|
|
252
|
+
const stat = fs.statSync(sourcePath);
|
|
253
|
+
if (stat.isDirectory()) {
|
|
254
|
+
copyDirectoryRecursive(sourcePath, destPath);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function mergeDirectoryRecursive(source, destination) {
|
|
262
|
+
if (!fs.existsSync(destination)) {
|
|
263
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
264
|
+
}
|
|
265
|
+
const files = fs.readdirSync(source);
|
|
266
|
+
for (const file of files) {
|
|
267
|
+
const sourcePath = path.join(source, file);
|
|
268
|
+
const destPath = path.join(destination, file);
|
|
269
|
+
const stat = fs.statSync(sourcePath);
|
|
270
|
+
if (stat.isDirectory()) {
|
|
271
|
+
mergeDirectoryRecursive(sourcePath, destPath);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const copy = promisify(ncp);
|
|
280
|
+
let copyOrLink = copy;
|
|
281
|
+
const isTemplateRegex = /([^\/\\]*?)\.template\./;
|
|
282
|
+
const isPackageJsonRegex = /package\.json/;
|
|
283
|
+
const isYarnLockRegex = /yarn\.lock/;
|
|
284
|
+
const isNextGeneratedRegex = /packages\/nextjs\/generated/;
|
|
285
|
+
const isArgsRegex = /([^\/\\]*?)\.args\./;
|
|
286
|
+
const isGitKeepRegex = /\.gitkeep/;
|
|
287
|
+
// Additional files/directories to exclude from template copying
|
|
288
|
+
const excludePatterns = [
|
|
289
|
+
/\.github\//, // GitHub specific files todo: add workflows/main.yml later
|
|
290
|
+
/CHANGELOG\.md/, // Changelog file
|
|
291
|
+
/__test.*__/, // All test directories (__test__, __tests__, etc.)
|
|
292
|
+
];
|
|
293
|
+
const copyBaseFiles = async ({ dev: isDev }, basePath, targetDir) => {
|
|
294
|
+
await copyOrLink(basePath, targetDir, {
|
|
295
|
+
clobber: false,
|
|
296
|
+
filter: (fileName) => {
|
|
297
|
+
const isPackageJson = isPackageJsonRegex.test(fileName);
|
|
298
|
+
const isYarnLock = isYarnLockRegex.test(fileName);
|
|
299
|
+
const isNextGenerated = isNextGeneratedRegex.test(fileName);
|
|
300
|
+
const isGitKeep = isGitKeepRegex.test(fileName);
|
|
301
|
+
// Check if file matches any exclude pattern
|
|
302
|
+
const isExcluded = excludePatterns.some(pattern => pattern.test(fileName));
|
|
303
|
+
const skipAlways = isPackageJson || isGitKeep || isExcluded;
|
|
304
|
+
const skipDevOnly = isYarnLock || isNextGenerated;
|
|
305
|
+
const shouldSkip = skipAlways || (isDev && skipDevOnly);
|
|
306
|
+
return !shouldSkip;
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
["stylus", "nextjs"].forEach(packageName => {
|
|
310
|
+
const envExamplePath = path.join(basePath, "packages", packageName, ".env.example");
|
|
311
|
+
const envPath = path.join(targetDir, "packages", packageName, ".env");
|
|
312
|
+
if (fs.existsSync(envExamplePath)) {
|
|
313
|
+
copy(envExamplePath, envPath);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
const basePackageJsonPaths = findFilesRecursiveSync(basePath, (path) => isPackageJsonRegex.test(path));
|
|
317
|
+
basePackageJsonPaths.forEach((packageJsonPath) => {
|
|
318
|
+
const partialPath = packageJsonPath.split(basePath)[1];
|
|
319
|
+
mergePackageJson$1(path.join(targetDir, partialPath), path.join(basePath, partialPath), isDev);
|
|
320
|
+
});
|
|
321
|
+
if (isDev) {
|
|
322
|
+
const baseYarnLockPaths = findFilesRecursiveSync(basePath, (path) => isYarnLockRegex.test(path));
|
|
323
|
+
baseYarnLockPaths.forEach((yarnLockPath) => {
|
|
324
|
+
const partialPath = yarnLockPath.split(basePath)[1];
|
|
325
|
+
copy(path.join(basePath, partialPath), path.join(targetDir, partialPath));
|
|
326
|
+
});
|
|
327
|
+
const nextGeneratedPaths = findFilesRecursiveSync(basePath, (path) => isNextGeneratedRegex.test(path));
|
|
328
|
+
nextGeneratedPaths.forEach((nextGeneratedPath) => {
|
|
329
|
+
const partialPath = nextGeneratedPath.split(basePath)[1];
|
|
330
|
+
copy(path.join(basePath, partialPath), path.join(targetDir, partialPath));
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
const processTemplatedFiles = async ({ dev: isDev, extension }, basePath, targetDir) => {
|
|
335
|
+
const baseTemplatedFileDescriptors = findFilesRecursiveSync(basePath, (path) => isTemplateRegex.test(path)).map((baseTemplatePath) => ({
|
|
336
|
+
path: baseTemplatePath,
|
|
337
|
+
fileUrl: url.pathToFileURL(baseTemplatePath).href,
|
|
338
|
+
relativePath: baseTemplatePath.split(basePath)[1],
|
|
339
|
+
source: "base",
|
|
340
|
+
}));
|
|
341
|
+
await Promise.all(baseTemplatedFileDescriptors.map(async (templateFileDescriptor) => {
|
|
342
|
+
const templateTargetName = templateFileDescriptor.path.match(isTemplateRegex)?.[1];
|
|
343
|
+
const argsPath = templateFileDescriptor.relativePath.replace(isTemplateRegex, `${templateTargetName}.args.`);
|
|
344
|
+
// Load the template
|
|
345
|
+
const template = (await import(templateFileDescriptor.fileUrl)).default;
|
|
346
|
+
if (!template) {
|
|
347
|
+
throw new Error(`Template ${templateTargetName} from ${templateFileDescriptor.source} doesn't have a default export`);
|
|
348
|
+
}
|
|
349
|
+
if (typeof template !== "function") {
|
|
350
|
+
throw new Error(`Template ${templateTargetName} from ${templateFileDescriptor.source} is not exporting a function by default`);
|
|
351
|
+
}
|
|
352
|
+
// Collect args from multiple sources
|
|
353
|
+
const argsFileUrls = [];
|
|
354
|
+
// Check for args in target directory (from extensions)
|
|
355
|
+
if (extension) {
|
|
356
|
+
const extensionArgsPath = path.join(targetDir, argsPath);
|
|
357
|
+
if (fs.existsSync(extensionArgsPath)) {
|
|
358
|
+
argsFileUrls.push(url.pathToFileURL(extensionArgsPath).href);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Load and combine all args
|
|
362
|
+
const argsModules = await Promise.all(argsFileUrls.map(async (argsFileUrl) => {
|
|
363
|
+
try {
|
|
364
|
+
return await import(argsFileUrl);
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
console.warn(`Failed to load args from: ${argsFileUrl}`);
|
|
368
|
+
return {};
|
|
369
|
+
}
|
|
370
|
+
}));
|
|
371
|
+
// Combine all args into a single object
|
|
372
|
+
const combinedArgs = argsModules.reduce((acc, module) => {
|
|
373
|
+
return { ...acc, ...module };
|
|
374
|
+
}, {});
|
|
375
|
+
// Execute template with combined args
|
|
376
|
+
const output = template(combinedArgs);
|
|
377
|
+
const targetPath = path.join(targetDir, templateFileDescriptor.relativePath.split(templateTargetName)[0], templateTargetName);
|
|
378
|
+
fs.writeFileSync(targetPath, output);
|
|
379
|
+
if (isDev) {
|
|
380
|
+
const devOutput = `--- TEMPLATE FILE
|
|
381
|
+
templates/${templateFileDescriptor.source}${templateFileDescriptor.relativePath}
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
--- ARGS FILES
|
|
385
|
+
${argsFileUrls.length > 0
|
|
386
|
+
? argsFileUrls.map(url => `\t- ${url.split("packages")[1] || url}`).join("\n")
|
|
387
|
+
: "(no args files writing to the template)"}
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
--- RESULTING ARGS
|
|
391
|
+
${Object.keys(combinedArgs).length > 0
|
|
392
|
+
? Object.entries(combinedArgs)
|
|
393
|
+
.map(([key, value]) => `\t- ${key}:\t${JSON.stringify(value)}`)
|
|
394
|
+
.join("\n")
|
|
395
|
+
: "(no args sent for the template)"}
|
|
396
|
+
`;
|
|
397
|
+
fs.writeFileSync(`${targetPath}.dev`, devOutput);
|
|
398
|
+
}
|
|
399
|
+
}));
|
|
400
|
+
};
|
|
401
|
+
async function copyTemplateFiles(options, templateDir, targetDir) {
|
|
402
|
+
copyOrLink = options.dev ? linkRecursive : copy;
|
|
403
|
+
const basePath = path.join(templateDir, baseDir);
|
|
404
|
+
// 1. Copy base template to target directory
|
|
405
|
+
await copyBaseFiles(options, basePath, targetDir);
|
|
406
|
+
// 2. Copy extension files if extension is provided
|
|
407
|
+
if (options.extension) {
|
|
408
|
+
await copyExtensionFile(options.extension, targetDir);
|
|
409
|
+
}
|
|
410
|
+
// 3. Process templated files with extension args
|
|
411
|
+
await processTemplatedFiles(options, basePath, targetDir);
|
|
412
|
+
// 4. Clean up template and args files
|
|
413
|
+
await cleanupTemplateFiles(targetDir);
|
|
414
|
+
// 5. Initialize git repo to avoid husky error
|
|
415
|
+
await execa("git", ["init"], { cwd: targetDir });
|
|
416
|
+
await execa("git", ["checkout", "-b", "main"], { cwd: targetDir });
|
|
417
|
+
}
|
|
418
|
+
async function cleanupTemplateFiles(targetDir) {
|
|
419
|
+
const basePath = targetDir;
|
|
420
|
+
// Find all template and args files
|
|
421
|
+
const templateFiles = findFilesRecursiveSync(basePath, (path) => isTemplateRegex.test(path));
|
|
422
|
+
const argsFiles = findFilesRecursiveSync(basePath, (path) => isArgsRegex.test(path));
|
|
423
|
+
// Delete template files
|
|
424
|
+
templateFiles.forEach((templatePath) => {
|
|
425
|
+
try {
|
|
426
|
+
fs.unlinkSync(templatePath);
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
console.warn(`Failed to delete template file: ${templatePath}`);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
// Delete args files
|
|
433
|
+
argsFiles.forEach((argsPath) => {
|
|
434
|
+
try {
|
|
435
|
+
fs.unlinkSync(argsPath);
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
console.warn(`Failed to delete args file: ${argsPath}`);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async function createProjectDirectory(projectName) {
|
|
444
|
+
// Check if directory already exists
|
|
445
|
+
if (fs.existsSync(projectName)) {
|
|
446
|
+
// If directory exists, check if it's empty
|
|
447
|
+
if (fs.readdirSync(projectName).length > 0) {
|
|
448
|
+
throw new Error(`Directory ${projectName} already exists and is not empty. Cannot continue.`);
|
|
449
|
+
}
|
|
450
|
+
// If directory exists and is empty, we can proceed (or do nothing here, as it's already created and empty)
|
|
451
|
+
// For clarity, we can return true or simply let the function continue if no further action is needed.
|
|
452
|
+
// In this case, since the directory exists and is empty, the goal is achieved.
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
const result = await execa("mkdir", [projectName]);
|
|
457
|
+
if (result.failed) {
|
|
458
|
+
throw new Error("There was a problem running the mkdir command");
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
catch (error) {
|
|
462
|
+
throw new Error(`Failed to create directory: ${error instanceof Error ? error.message : String(error)}`);
|
|
463
|
+
}
|
|
464
|
+
return true;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async function installPackages(targetDir, options) {
|
|
468
|
+
// Condition to check if 'devnet' is included and only update submodules
|
|
469
|
+
// if (options.extensions?.includes("starknet-native")) {
|
|
470
|
+
// }
|
|
471
|
+
return projectInstall({
|
|
472
|
+
cwd: targetDir,
|
|
473
|
+
prefer: "yarn",
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async function createFirstGitCommit(targetDir) {
|
|
478
|
+
try {
|
|
479
|
+
await execa("git", ["add", "-A"], { cwd: targetDir });
|
|
480
|
+
await execa("git", ["commit", "-m", "Initial commit with 🏗️ Scaffold-Stylus", "--no-verify"], { cwd: targetDir });
|
|
481
|
+
}
|
|
482
|
+
catch (e) {
|
|
483
|
+
throw new Error("Failed to initialize git repository", {
|
|
484
|
+
cause: e?.stderr ?? e,
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
async function prettierFormat(targetDir) {
|
|
490
|
+
try {
|
|
491
|
+
const nextjsPath = path.join(targetDir, "packages/nextjs");
|
|
492
|
+
const result = await execa("yarn", ["format"], { cwd: nextjsPath });
|
|
493
|
+
if (result.failed) {
|
|
494
|
+
throw new Error("There was a problem running the format command");
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
catch (error) {
|
|
498
|
+
throw new Error("Failed to format Next.js project", { cause: error });
|
|
499
|
+
}
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async function renderOutroMessage(options) {
|
|
504
|
+
let message = `
|
|
505
|
+
\n
|
|
506
|
+
${chalk.bold.green("Congratulations!")} Your project has been scaffolded! 🎉
|
|
507
|
+
|
|
508
|
+
${chalk.bold("Next steps:")}
|
|
509
|
+
|
|
510
|
+
${chalk.dim("cd")} ${options.directory}
|
|
511
|
+
`;
|
|
512
|
+
message += `
|
|
513
|
+
\t${chalk.bold("Start the local development node")}
|
|
514
|
+
\t${chalk.dim("yarn")} chain
|
|
515
|
+
`;
|
|
516
|
+
message += `
|
|
517
|
+
\t${chalk.bold("In a new terminal window, deploy your contracts")}
|
|
518
|
+
\t${chalk.dim("yarn")} deploy
|
|
519
|
+
`;
|
|
520
|
+
message += `
|
|
521
|
+
\t${chalk.bold("In a new terminal window, start the frontend")}
|
|
522
|
+
\t${chalk.dim("yarn")} start
|
|
523
|
+
`;
|
|
524
|
+
message += `
|
|
525
|
+
${chalk.bold.green("Thanks for using Scaffold-Stylus 🙏, Happy Building!")}
|
|
526
|
+
`;
|
|
527
|
+
console.log(message);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
async function createProject(options) {
|
|
531
|
+
console.log(`\n`);
|
|
532
|
+
const currentFileUrl = import.meta.url;
|
|
533
|
+
const templateDirectory = path.resolve(decodeURI(fileURLToPath(currentFileUrl)), "../../templates");
|
|
534
|
+
const targetDirectory = path.resolve(process.cwd(), options.directory);
|
|
535
|
+
const tasks = new Listr([
|
|
536
|
+
{
|
|
537
|
+
title: `📁 Create project directory ${targetDirectory}`,
|
|
538
|
+
task: () => createProjectDirectory(options.directory),
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
title: `🚀 Creating a new Scaffold-Stylus app in ${chalk.green.bold(options.directory)}`,
|
|
542
|
+
task: () => copyTemplateFiles(options, templateDirectory, targetDirectory),
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
title: `📡 Initializing Git repository`,
|
|
546
|
+
task: () => createFirstGitCommit(targetDirectory),
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
title: `📦 Installing dependencies with yarn, this could take a while`,
|
|
550
|
+
task: () => installPackages(targetDirectory),
|
|
551
|
+
skip: () => {
|
|
552
|
+
if (!options.install) {
|
|
553
|
+
return "Manually skipped";
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
title: "🪄 Formatting Next.js files with prettier",
|
|
559
|
+
task: () => prettierFormat(targetDirectory),
|
|
560
|
+
skip: () => {
|
|
561
|
+
if (!options.install) {
|
|
562
|
+
return "Skipping because prettier install was skipped";
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
]);
|
|
567
|
+
try {
|
|
568
|
+
await tasks.run();
|
|
569
|
+
renderOutroMessage(options);
|
|
570
|
+
}
|
|
571
|
+
catch (error) {
|
|
572
|
+
console.log("%s Error occurred", chalk.red.bold("ERROR"), error);
|
|
573
|
+
console.log("%s Exiting...", chalk.red.bold("Uh oh! 😕 Sorry about that!"));
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// TODO update smartContractFramework code with general extensions
|
|
578
|
+
function parseArgumentsIntoOptions(rawArgs) {
|
|
579
|
+
const args = arg({
|
|
580
|
+
"--skip-install": Boolean,
|
|
581
|
+
"-s": "--skip-install",
|
|
582
|
+
"--dev": Boolean,
|
|
583
|
+
"--dir": String,
|
|
584
|
+
"-d": "--dir",
|
|
585
|
+
"--extension": String,
|
|
586
|
+
"-e": "--extension",
|
|
587
|
+
}, {
|
|
588
|
+
argv: rawArgs.slice(2).map((a) => a.toLowerCase()),
|
|
589
|
+
});
|
|
590
|
+
const skipInstall = args["--skip-install"] ?? null;
|
|
591
|
+
const dev = args["--dev"] ?? false; // info: use false avoid asking user
|
|
592
|
+
const directory = args["--dir"] ?? null;
|
|
593
|
+
const extension = args["--extension"] ?? null;
|
|
594
|
+
return {
|
|
595
|
+
directory,
|
|
596
|
+
install: skipInstall ? false : null,
|
|
597
|
+
dev,
|
|
598
|
+
extension,
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// default values for unspecified args
|
|
603
|
+
const defaultOptions = {
|
|
604
|
+
directory: "./my-dapp-example",
|
|
605
|
+
install: true,
|
|
606
|
+
dev: false};
|
|
607
|
+
async function promptForMissingOptions(options) {
|
|
608
|
+
const cliAnswers = Object.fromEntries(Object.entries(options).filter(([key, value]) => value !== null));
|
|
609
|
+
const extensions = loadExtensions();
|
|
610
|
+
extensions.map(ext => ({
|
|
611
|
+
name: `${ext.extensionFlagValue} - ${ext.description}`,
|
|
612
|
+
value: ext.extensionFlagValue,
|
|
613
|
+
}));
|
|
614
|
+
const questions = [
|
|
615
|
+
{
|
|
616
|
+
type: "input",
|
|
617
|
+
name: "directory",
|
|
618
|
+
message: "Where do you want to install the new files? Choose ./ (root folder) or provide a new folder name.",
|
|
619
|
+
default: defaultOptions.directory,
|
|
620
|
+
validate: (value) => value.length > 0,
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
type: "confirm",
|
|
624
|
+
name: "install",
|
|
625
|
+
message: "Install dependencies?",
|
|
626
|
+
default: defaultOptions.install,
|
|
627
|
+
},
|
|
628
|
+
];
|
|
629
|
+
const answers = await inquirer.prompt(questions, cliAnswers);
|
|
630
|
+
const mergedOptions = {
|
|
631
|
+
directory: options.directory ?? answers.directory,
|
|
632
|
+
install: options.install ?? answers.install,
|
|
633
|
+
dev: options.dev ?? defaultOptions.dev,
|
|
634
|
+
extension: options.extension ?? answers.extension,
|
|
635
|
+
};
|
|
636
|
+
return mergedOptions;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const TITLE_TEXT = `
|
|
640
|
+
${chalk.bold.blue("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")}
|
|
641
|
+
${chalk.bold.blue("| Create Scaffold-Stylus app |")}
|
|
642
|
+
${chalk.bold.blue("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")}
|
|
643
|
+
`;
|
|
644
|
+
function renderIntroMessage() {
|
|
645
|
+
console.log(TITLE_TEXT);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
async function cli(args) {
|
|
649
|
+
renderIntroMessage();
|
|
650
|
+
const rawOptions = parseArgumentsIntoOptions(args);
|
|
651
|
+
const options = await promptForMissingOptions(rawOptions);
|
|
652
|
+
await createProject(options);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export { cli };
|
|
656
|
+
//# sourceMappingURL=cli.js.map
|