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
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { Options, TemplateDescriptor } from "../types";
|
|
3
|
+
import { baseDir } from "../utils/consts";
|
|
4
|
+
import { findFilesRecursiveSync } from "../utils/find-files-recursively";
|
|
5
|
+
import { mergePackageJson } from "../utils/merge-package-json";
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import url from 'url';
|
|
8
|
+
import ncp from "ncp";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { promisify } from "util";
|
|
11
|
+
import link from "../utils/link";
|
|
12
|
+
import { copyExtensionFile } from "./copy-extension-file";
|
|
13
|
+
|
|
14
|
+
const copy = promisify(ncp);
|
|
15
|
+
let copyOrLink = copy;
|
|
16
|
+
|
|
17
|
+
const isTemplateRegex = /([^\/\\]*?)\.template\./;
|
|
18
|
+
const isPackageJsonRegex = /package\.json/;
|
|
19
|
+
const isYarnLockRegex = /yarn\.lock/;
|
|
20
|
+
const isNextGeneratedRegex = /packages\/nextjs\/generated/;
|
|
21
|
+
const isArgsRegex = /([^\/\\]*?)\.args\./;
|
|
22
|
+
const isGitKeepRegex = /\.gitkeep/;
|
|
23
|
+
|
|
24
|
+
// Additional files/directories to exclude from template copying
|
|
25
|
+
const excludePatterns = [
|
|
26
|
+
/\.github\//, // GitHub specific files todo: add workflows/main.yml later
|
|
27
|
+
/CHANGELOG\.md/, // Changelog file
|
|
28
|
+
/__test.*__/, // All test directories (__test__, __tests__, etc.)
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const copyBaseFiles = async (
|
|
32
|
+
{ dev: isDev }: Options,
|
|
33
|
+
basePath: string,
|
|
34
|
+
targetDir: string
|
|
35
|
+
) => {
|
|
36
|
+
await copyOrLink(basePath, targetDir, {
|
|
37
|
+
clobber: false,
|
|
38
|
+
filter: (fileName) => { // NOTE: filter IN
|
|
39
|
+
const isTemplate = isTemplateRegex.test(fileName);
|
|
40
|
+
const isPackageJson = isPackageJsonRegex.test(fileName);
|
|
41
|
+
const isYarnLock = isYarnLockRegex.test(fileName);
|
|
42
|
+
const isNextGenerated = isNextGeneratedRegex.test(fileName);
|
|
43
|
+
const isGitKeep = isGitKeepRegex.test(fileName);
|
|
44
|
+
|
|
45
|
+
// Check if file matches any exclude pattern
|
|
46
|
+
const isExcluded = excludePatterns.some(pattern => pattern.test(fileName));
|
|
47
|
+
|
|
48
|
+
const skipAlways = isPackageJson || isGitKeep || isExcluded;
|
|
49
|
+
const skipDevOnly = isYarnLock || isNextGenerated;
|
|
50
|
+
const shouldSkip = skipAlways || (isDev && skipDevOnly);
|
|
51
|
+
|
|
52
|
+
return !shouldSkip;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
["stylus", "nextjs"].forEach(packageName => {
|
|
57
|
+
const envExamplePath = path.join(basePath, "packages", packageName, ".env.example");
|
|
58
|
+
const envPath = path.join(targetDir, "packages", packageName, ".env");
|
|
59
|
+
if (fs.existsSync(envExamplePath)) {
|
|
60
|
+
copy(envExamplePath, envPath);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const basePackageJsonPaths = findFilesRecursiveSync(basePath, (path: string) => isPackageJsonRegex.test(path));
|
|
65
|
+
|
|
66
|
+
basePackageJsonPaths.forEach((packageJsonPath: string) => {
|
|
67
|
+
const partialPath = packageJsonPath.split(basePath)[1];
|
|
68
|
+
mergePackageJson(
|
|
69
|
+
path.join(targetDir, partialPath),
|
|
70
|
+
path.join(basePath, partialPath),
|
|
71
|
+
isDev
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (isDev) {
|
|
76
|
+
const baseYarnLockPaths = findFilesRecursiveSync(basePath, (path: string) => isYarnLockRegex.test(path));
|
|
77
|
+
baseYarnLockPaths.forEach((yarnLockPath: string) => {
|
|
78
|
+
const partialPath = yarnLockPath.split(basePath)[1];
|
|
79
|
+
copy(
|
|
80
|
+
path.join(basePath, partialPath),
|
|
81
|
+
path.join(targetDir, partialPath)
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const nextGeneratedPaths = findFilesRecursiveSync(basePath, (path: string) => isNextGeneratedRegex.test(path));
|
|
86
|
+
nextGeneratedPaths.forEach((nextGeneratedPath: string) => {
|
|
87
|
+
const partialPath = nextGeneratedPath.split(basePath)[1];
|
|
88
|
+
copy(
|
|
89
|
+
path.join(basePath, partialPath),
|
|
90
|
+
path.join(targetDir, partialPath)
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
const processTemplatedFiles = async (
|
|
99
|
+
{ dev: isDev, extension }: Options,
|
|
100
|
+
basePath: string,
|
|
101
|
+
targetDir: string
|
|
102
|
+
) => {
|
|
103
|
+
const baseTemplatedFileDescriptors: TemplateDescriptor[] =
|
|
104
|
+
findFilesRecursiveSync(basePath, (path: string) => isTemplateRegex.test(path)).map(
|
|
105
|
+
(baseTemplatePath: string) => ({
|
|
106
|
+
path: baseTemplatePath,
|
|
107
|
+
fileUrl: url.pathToFileURL(baseTemplatePath).href,
|
|
108
|
+
relativePath: baseTemplatePath.split(basePath)[1],
|
|
109
|
+
source: "base",
|
|
110
|
+
})
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
await Promise.all(
|
|
114
|
+
baseTemplatedFileDescriptors.map(async (templateFileDescriptor) => {
|
|
115
|
+
const templateTargetName =
|
|
116
|
+
templateFileDescriptor.path.match(isTemplateRegex)?.[1]!;
|
|
117
|
+
|
|
118
|
+
const argsPath = templateFileDescriptor.relativePath.replace(
|
|
119
|
+
isTemplateRegex,
|
|
120
|
+
`${templateTargetName}.args.`
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Load the template
|
|
124
|
+
const template = (await import(templateFileDescriptor.fileUrl)).default;
|
|
125
|
+
|
|
126
|
+
if (!template) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`Template ${templateTargetName} from ${templateFileDescriptor.source} doesn't have a default export`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (typeof template !== "function") {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`Template ${templateTargetName} from ${templateFileDescriptor.source} is not exporting a function by default`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Collect args from multiple sources
|
|
138
|
+
const argsFileUrls = [];
|
|
139
|
+
|
|
140
|
+
// Check for args in target directory (from extensions)
|
|
141
|
+
if (extension) {
|
|
142
|
+
const extensionArgsPath = path.join(targetDir, argsPath);
|
|
143
|
+
if (fs.existsSync(extensionArgsPath)) {
|
|
144
|
+
argsFileUrls.push(url.pathToFileURL(extensionArgsPath).href);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Load and combine all args
|
|
149
|
+
const argsModules = await Promise.all(
|
|
150
|
+
argsFileUrls.map(async (argsFileUrl) => {
|
|
151
|
+
try {
|
|
152
|
+
return await import(argsFileUrl) as Record<string, any>;
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.warn(`Failed to load args from: ${argsFileUrl}`);
|
|
155
|
+
return {};
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
// Combine all args into a single object
|
|
161
|
+
const combinedArgs = argsModules.reduce((acc, module) => {
|
|
162
|
+
return { ...acc, ...module };
|
|
163
|
+
}, {});
|
|
164
|
+
|
|
165
|
+
// Execute template with combined args
|
|
166
|
+
const output = template(combinedArgs);
|
|
167
|
+
|
|
168
|
+
const targetPath = path.join(
|
|
169
|
+
targetDir,
|
|
170
|
+
templateFileDescriptor.relativePath.split(templateTargetName)[0],
|
|
171
|
+
templateTargetName
|
|
172
|
+
);
|
|
173
|
+
fs.writeFileSync(targetPath, output);
|
|
174
|
+
|
|
175
|
+
if (isDev) {
|
|
176
|
+
const devOutput = `--- TEMPLATE FILE
|
|
177
|
+
templates/${templateFileDescriptor.source}${templateFileDescriptor.relativePath}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
--- ARGS FILES
|
|
181
|
+
${argsFileUrls.length > 0
|
|
182
|
+
? argsFileUrls.map(url => `\t- ${url.split("packages")[1] || url}`).join("\n")
|
|
183
|
+
: "(no args files writing to the template)"}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
--- RESULTING ARGS
|
|
187
|
+
${Object.keys(combinedArgs).length > 0
|
|
188
|
+
? Object.entries(combinedArgs)
|
|
189
|
+
.map(([key, value]) => `\t- ${key}:\t${JSON.stringify(value)}`)
|
|
190
|
+
.join("\n")
|
|
191
|
+
: "(no args sent for the template)"}
|
|
192
|
+
`;
|
|
193
|
+
fs.writeFileSync(`${targetPath}.dev`, devOutput);
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
export async function copyTemplateFiles(
|
|
200
|
+
options: Options,
|
|
201
|
+
templateDir: string,
|
|
202
|
+
targetDir: string
|
|
203
|
+
) {
|
|
204
|
+
copyOrLink = options.dev ? link : copy;
|
|
205
|
+
const basePath = path.join(templateDir, baseDir);
|
|
206
|
+
|
|
207
|
+
// 1. Copy base template to target directory
|
|
208
|
+
await copyBaseFiles(options, basePath, targetDir);
|
|
209
|
+
|
|
210
|
+
// 2. Copy extension files if extension is provided
|
|
211
|
+
if (options.extension) {
|
|
212
|
+
await copyExtensionFile(options.extension, targetDir);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 3. Process templated files with extension args
|
|
216
|
+
await processTemplatedFiles(options, basePath, targetDir);
|
|
217
|
+
|
|
218
|
+
// 4. Clean up template and args files
|
|
219
|
+
await cleanupTemplateFiles(targetDir);
|
|
220
|
+
|
|
221
|
+
// 5. Initialize git repo to avoid husky error
|
|
222
|
+
await execa("git", ["init"], { cwd: targetDir });
|
|
223
|
+
await execa("git", ["checkout", "-b", "main"], { cwd: targetDir });
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function cleanupTemplateFiles(targetDir: string) {
|
|
227
|
+
const basePath = targetDir;
|
|
228
|
+
|
|
229
|
+
// Find all template and args files
|
|
230
|
+
const templateFiles = findFilesRecursiveSync(basePath, (path: string) => isTemplateRegex.test(path));
|
|
231
|
+
const argsFiles = findFilesRecursiveSync(basePath, (path: string) => isArgsRegex.test(path));
|
|
232
|
+
|
|
233
|
+
// Delete template files
|
|
234
|
+
templateFiles.forEach((templatePath) => {
|
|
235
|
+
try {
|
|
236
|
+
fs.unlinkSync(templatePath);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.warn(`Failed to delete template file: ${templatePath}`);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Delete args files
|
|
243
|
+
argsFiles.forEach((argsPath) => {
|
|
244
|
+
try {
|
|
245
|
+
fs.unlinkSync(argsPath);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.warn(`Failed to delete args file: ${argsPath}`);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
|
|
3
|
+
// Checkout the latest release tag in a git submodule
|
|
4
|
+
async function checkoutLatestTag(submodulePath: string): Promise<void> {
|
|
5
|
+
try {
|
|
6
|
+
const { stdout } = await execa("git", ["tag", "-l", "--sort=-v:refname"], {
|
|
7
|
+
cwd: submodulePath,
|
|
8
|
+
});
|
|
9
|
+
const tagLines = stdout.split("\n");
|
|
10
|
+
if (tagLines.length > 0) {
|
|
11
|
+
const latestTag = tagLines[0];
|
|
12
|
+
await execa("git", ["-C", `${submodulePath}`, "checkout", latestTag]);
|
|
13
|
+
} else {
|
|
14
|
+
throw new Error(`No tags found in submodule at ${submodulePath}`);
|
|
15
|
+
}
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error("Error checking out latest tag:", error);
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function createFirstGitCommit(targetDir: string) {
|
|
23
|
+
try {
|
|
24
|
+
await execa("git", ["add", "-A"], { cwd: targetDir });
|
|
25
|
+
await execa(
|
|
26
|
+
"git",
|
|
27
|
+
["commit", "-m", "Initial commit with 🏗️ Scaffold-Stylus", "--no-verify"],
|
|
28
|
+
{ cwd: targetDir },
|
|
29
|
+
);
|
|
30
|
+
} catch (e: any) {
|
|
31
|
+
throw new Error("Failed to initialize git repository", {
|
|
32
|
+
cause: e?.stderr ?? e,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
|
|
4
|
+
export async function createProjectDirectory(projectName: string) {
|
|
5
|
+
// Check if directory already exists
|
|
6
|
+
if (fs.existsSync(projectName)) {
|
|
7
|
+
// If directory exists, check if it's empty
|
|
8
|
+
if (fs.readdirSync(projectName).length > 0) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`Directory ${projectName} already exists and is not empty. Cannot continue.`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
// If directory exists and is empty, we can proceed (or do nothing here, as it's already created and empty)
|
|
14
|
+
// For clarity, we can return true or simply let the function continue if no further action is needed.
|
|
15
|
+
// In this case, since the directory exists and is empty, the goal is achieved.
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const result = await execa("mkdir", [projectName]);
|
|
21
|
+
|
|
22
|
+
if (result.failed) {
|
|
23
|
+
throw new Error("There was a problem running the mkdir command");
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`Failed to create directory: ${
|
|
28
|
+
error instanceof Error ? error.message : String(error)
|
|
29
|
+
}`,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { projectInstall } from "pkg-install";
|
|
2
|
+
import {execa} from "execa";
|
|
3
|
+
import type {Options} from "../types";
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
export async function installPackages(targetDir: string, options: Options) {
|
|
7
|
+
// Condition to check if 'devnet' is included and only update submodules
|
|
8
|
+
// if (options.extensions?.includes("starknet-native")) {
|
|
9
|
+
// }
|
|
10
|
+
|
|
11
|
+
return projectInstall({
|
|
12
|
+
cwd: targetDir,
|
|
13
|
+
prefer: "yarn",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export async function prettierFormat(targetDir: string) {
|
|
5
|
+
try {
|
|
6
|
+
const nextjsPath = path.join(targetDir, "packages/nextjs");
|
|
7
|
+
const result = await execa("yarn", ["format"], { cwd: nextjsPath });
|
|
8
|
+
|
|
9
|
+
if (result.failed) {
|
|
10
|
+
throw new Error("There was a problem running the format command");
|
|
11
|
+
}
|
|
12
|
+
} catch (error) {
|
|
13
|
+
throw new Error("Failed to format Next.js project", { cause: error });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return true;
|
|
17
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type Args = string[];
|
|
2
|
+
|
|
3
|
+
export type RawOptions = {
|
|
4
|
+
directory: string | null;
|
|
5
|
+
install: boolean | null;
|
|
6
|
+
dev: boolean;
|
|
7
|
+
extension: string | null;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type NonNullableRawOptions = {
|
|
11
|
+
[Prop in keyof RawOptions]: NonNullable<RawOptions[Prop]>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type Options = NonNullableRawOptions;
|
|
15
|
+
|
|
16
|
+
export const isDefined = <T>(item: T | undefined | null): item is T =>
|
|
17
|
+
item !== undefined && item !== null;
|
|
18
|
+
|
|
19
|
+
export type TemplateDescriptor = {
|
|
20
|
+
path: string;
|
|
21
|
+
fileUrl: string;
|
|
22
|
+
relativePath: string;
|
|
23
|
+
source: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type Extension = {
|
|
27
|
+
extensionFlagValue: string;
|
|
28
|
+
description: string;
|
|
29
|
+
repository: string;
|
|
30
|
+
branch: string;
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const baseDir = "base";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export const findFilesRecursiveSync = (
|
|
5
|
+
baseDir: string,
|
|
6
|
+
criteriaFn: (path: string) => boolean = () => true
|
|
7
|
+
): string[] => {
|
|
8
|
+
const subPaths = fs.readdirSync(baseDir);
|
|
9
|
+
const files = subPaths.map((relativePath) => {
|
|
10
|
+
const fullPath = path.resolve(baseDir, relativePath);
|
|
11
|
+
return fs.lstatSync(fullPath).isDirectory()
|
|
12
|
+
? [...findFilesRecursiveSync(fullPath, criteriaFn)]
|
|
13
|
+
: criteriaFn(fullPath)
|
|
14
|
+
? [fullPath]
|
|
15
|
+
: [];
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return files.flat();
|
|
19
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Options } from "ncp";
|
|
2
|
+
import { existsSync, lstatSync, readdirSync } from "fs";
|
|
3
|
+
import { promises } from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
const { mkdir, link } = promises;
|
|
7
|
+
/**
|
|
8
|
+
* The goal is that this function has the same API as ncp, so they can be used
|
|
9
|
+
* interchangeably.
|
|
10
|
+
*
|
|
11
|
+
* - clobber not implemented
|
|
12
|
+
*/
|
|
13
|
+
const linkRecursive = async (source: string, destination: string, options?: Options): Promise<void> => {
|
|
14
|
+
const passesFilter = options?.filter === undefined
|
|
15
|
+
? true // no filter
|
|
16
|
+
: typeof options.filter === 'function'
|
|
17
|
+
? options.filter(source) // filter is function
|
|
18
|
+
: options.filter.test(source) // filter is regex
|
|
19
|
+
|
|
20
|
+
if (!passesFilter) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if(lstatSync(source).isDirectory()) {
|
|
25
|
+
const subPaths = readdirSync(source);
|
|
26
|
+
await Promise.all(
|
|
27
|
+
subPaths.map(async subPath => {
|
|
28
|
+
const sourceSubpath = path.join(source, subPath);
|
|
29
|
+
const isSubPathAFolder = lstatSync(sourceSubpath).isDirectory()
|
|
30
|
+
const destSubPath = path.join(destination, subPath)
|
|
31
|
+
const existsDestSubPath = existsSync(destSubPath)
|
|
32
|
+
if (isSubPathAFolder && !existsDestSubPath) {
|
|
33
|
+
await mkdir(destSubPath)
|
|
34
|
+
}
|
|
35
|
+
await linkRecursive(sourceSubpath, destSubPath, options)
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return link(source, destination)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default linkRecursive
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Extension } from "../types";
|
|
2
|
+
import extensions from "../extensions.json";
|
|
3
|
+
|
|
4
|
+
export function loadExtensions(): Extension[] {
|
|
5
|
+
return extensions as Extension[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function findExtensionByFlag(flagValue: string): Extension | undefined {
|
|
9
|
+
return extensions.find((ext: Extension) => ext.extensionFlagValue === flagValue);
|
|
10
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// @ts-expect-error We don't have types for this probably add .d.ts file
|
|
2
|
+
import mergeJsonStr from "merge-packages";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
|
|
5
|
+
export function mergePackageJson(
|
|
6
|
+
targetPackageJsonPath: string,
|
|
7
|
+
secondPackageJsonPath: string,
|
|
8
|
+
isDev: boolean
|
|
9
|
+
) {
|
|
10
|
+
const existsTarget = fs.existsSync(targetPackageJsonPath);
|
|
11
|
+
const existsSecond = fs.existsSync(secondPackageJsonPath);
|
|
12
|
+
if (!existsTarget && !existsSecond) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const targetPackageJson = existsTarget ? fs.readFileSync(targetPackageJsonPath, "utf8") : '{}';
|
|
17
|
+
const secondPackageJson = existsSecond ? fs.readFileSync(secondPackageJsonPath, "utf8") : '{}';
|
|
18
|
+
|
|
19
|
+
const mergedPkgStr = mergeJsonStr.default(
|
|
20
|
+
targetPackageJson,
|
|
21
|
+
secondPackageJson
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Parse and reformat the merged JSON to ensure proper formatting
|
|
25
|
+
const mergedPkgObj = JSON.parse(mergedPkgStr);
|
|
26
|
+
const formattedPkgStr = JSON.stringify(mergedPkgObj, null, 2) + '\n';
|
|
27
|
+
|
|
28
|
+
fs.writeFileSync(targetPackageJsonPath, formattedPkgStr, "utf8");
|
|
29
|
+
if (isDev) {
|
|
30
|
+
const devStr = `TODO: write relevant information for the contributor`
|
|
31
|
+
fs.writeFileSync(`${targetPackageJsonPath}.dev`, devStr, "utf8");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Args, RawOptions } from "../types";
|
|
2
|
+
import arg from "arg";
|
|
3
|
+
|
|
4
|
+
// TODO update smartContractFramework code with general extensions
|
|
5
|
+
export function parseArgumentsIntoOptions(rawArgs: Args): RawOptions {
|
|
6
|
+
const args = arg(
|
|
7
|
+
{
|
|
8
|
+
"--skip-install": Boolean,
|
|
9
|
+
"-s": "--skip-install",
|
|
10
|
+
|
|
11
|
+
"--dev": Boolean,
|
|
12
|
+
|
|
13
|
+
"--dir": String,
|
|
14
|
+
"-d": "--dir",
|
|
15
|
+
|
|
16
|
+
"--extension": String,
|
|
17
|
+
"-e": "--extension",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
argv: rawArgs.slice(2).map((a) => a.toLowerCase()),
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const skipInstall = args["--skip-install"] ?? null;
|
|
25
|
+
|
|
26
|
+
const dev = args["--dev"] ?? false; // info: use false avoid asking user
|
|
27
|
+
|
|
28
|
+
const directory = args["--dir"] ?? null;
|
|
29
|
+
|
|
30
|
+
const extension = args["--extension"] ?? null;
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
directory,
|
|
34
|
+
install: skipInstall ? false : null,
|
|
35
|
+
dev,
|
|
36
|
+
extension,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Options, RawOptions } from "../types";
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
import { loadExtensions } from "./load-extensions";
|
|
4
|
+
|
|
5
|
+
// default values for unspecified args
|
|
6
|
+
const defaultOptions: RawOptions = {
|
|
7
|
+
directory: "./my-dapp-example",
|
|
8
|
+
install: true,
|
|
9
|
+
dev: false,
|
|
10
|
+
extension: null,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function promptForMissingOptions(
|
|
14
|
+
options: RawOptions,
|
|
15
|
+
): Promise<Options> {
|
|
16
|
+
const cliAnswers = Object.fromEntries(
|
|
17
|
+
Object.entries(options).filter(([key, value]) => value !== null),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const extensions = loadExtensions();
|
|
21
|
+
const extensionChoices = extensions.map(ext => ({
|
|
22
|
+
name: `${ext.extensionFlagValue} - ${ext.description}`,
|
|
23
|
+
value: ext.extensionFlagValue,
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
const questions = [
|
|
27
|
+
{
|
|
28
|
+
type: "input",
|
|
29
|
+
name: "directory",
|
|
30
|
+
message:
|
|
31
|
+
"Where do you want to install the new files? Choose ./ (root folder) or provide a new folder name.",
|
|
32
|
+
default: defaultOptions.directory,
|
|
33
|
+
validate: (value: string) => value.length > 0,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: "confirm",
|
|
37
|
+
name: "install",
|
|
38
|
+
message: "Install dependencies?",
|
|
39
|
+
default: defaultOptions.install,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const answers = await inquirer.prompt(questions, cliAnswers);
|
|
44
|
+
|
|
45
|
+
const mergedOptions: Options = {
|
|
46
|
+
directory: options.directory ?? answers.directory,
|
|
47
|
+
install: options.install ?? answers.install,
|
|
48
|
+
dev: options.dev ?? defaultOptions.dev,
|
|
49
|
+
extension: options.extension ?? answers.extension,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return mergedOptions;
|
|
53
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
|
|
3
|
+
export const TITLE_TEXT = `
|
|
4
|
+
${chalk.bold.blue("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")}
|
|
5
|
+
${chalk.bold.blue("| Create Scaffold-Stylus app |")}
|
|
6
|
+
${chalk.bold.blue("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")}
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
export function renderIntroMessage() {
|
|
10
|
+
console.log(TITLE_TEXT);
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Options } from "../types";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
|
|
4
|
+
export async function renderOutroMessage(options: Options) {
|
|
5
|
+
let message = `
|
|
6
|
+
\n
|
|
7
|
+
${chalk.bold.green("Congratulations!")} Your project has been scaffolded! 🎉
|
|
8
|
+
|
|
9
|
+
${chalk.bold("Next steps:")}
|
|
10
|
+
|
|
11
|
+
${chalk.dim("cd")} ${options.directory}
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
message += `
|
|
15
|
+
\t${chalk.bold("Start the local development node")}
|
|
16
|
+
\t${chalk.dim("yarn")} chain
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
message += `
|
|
20
|
+
\t${chalk.bold("In a new terminal window, deploy your contracts")}
|
|
21
|
+
\t${chalk.dim("yarn")} deploy
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
message += `
|
|
25
|
+
\t${chalk.bold("In a new terminal window, start the frontend")}
|
|
26
|
+
\t${chalk.dim("yarn")} start
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
message += `
|
|
30
|
+
${chalk.bold.green("Thanks for using Scaffold-Stylus 🙏, Happy Building!")}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
console.log(message);
|
|
34
|
+
}
|