skittles 1.0.1 → 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/README.md +7 -54
- package/dist/commands/clean.js +10 -16
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/compile.js +11 -17
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +152 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/test.d.ts +7 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +46 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/compiler/codegen.d.ts +1 -1
- package/dist/compiler/codegen.d.ts.map +1 -1
- package/dist/compiler/codegen.js +31 -38
- package/dist/compiler/codegen.js.map +1 -1
- package/dist/compiler/compiler.d.ts +1 -1
- package/dist/compiler/compiler.d.ts.map +1 -1
- package/dist/compiler/compiler.js +42 -48
- package/dist/compiler/compiler.js.map +1 -1
- package/dist/compiler/parser.d.ts +1 -1
- package/dist/compiler/parser.d.ts.map +1 -1
- package/dist/compiler/parser.js +213 -226
- package/dist/compiler/parser.js.map +1 -1
- package/dist/compiler/solc.d.ts +1 -1
- package/dist/compiler/solc.d.ts.map +1 -1
- package/dist/compiler/solc.js +5 -12
- package/dist/compiler/solc.js.map +1 -1
- package/dist/config/config.d.ts +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +16 -48
- package/dist/config/config.js.map +1 -1
- package/dist/exports.d.ts +3 -3
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +4 -7
- package/dist/exports.js.map +1 -1
- package/dist/index.js +22 -16
- package/dist/index.js.map +1 -1
- package/dist/testing.d.ts +93 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +134 -0
- package/dist/testing.js.map +1 -0
- package/dist/types/index.js +2 -5
- package/dist/types/index.js.map +1 -1
- package/dist/utils/console.js +11 -21
- package/dist/utils/console.js.map +1 -1
- package/dist/utils/file.js +18 -28
- package/dist/utils/file.js.map +1 -1
- package/package.json +38 -2
- package/testing.d.ts +76 -0
- package/testing.mjs +83 -0
package/README.md
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
<a href="https://skittles.dev/">
|
|
2
|
+
<img src="https://skittles.dev/banner.png" alt="Skittles" width="100%" />
|
|
3
|
+
</a>
|
|
4
|
+
|
|
1
5
|
# Skittles
|
|
2
6
|
|
|
3
|
-
Write
|
|
7
|
+
Write, Test and Deploy EVM Smart Contracts with TypeScript.
|
|
4
8
|
|
|
5
9
|
Skittles compiles TypeScript classes to Solidity source code, then to ABI and EVM bytecode. You get TypeScript tooling (autocomplete, type checking, familiar syntax) while targeting the EVM.
|
|
6
10
|
|
|
11
|
+
Website: [skittles.dev](https://skittles.dev/)
|
|
12
|
+
|
|
7
13
|
## Install
|
|
8
14
|
|
|
9
15
|
```bash
|
|
@@ -57,59 +63,6 @@ export class Token {
|
|
|
57
63
|
|
|
58
64
|
This compiles to a Solidity contract with events, mappings, a constructor, and a transfer function.
|
|
59
65
|
|
|
60
|
-
## Features
|
|
61
|
-
|
|
62
|
-
**Types** that map to Solidity: `number` (uint256), `string`, `boolean` (bool), `address`, `bytes`, `Record<K,V>` (mapping), `T[]` (array), interfaces (structs), enums.
|
|
63
|
-
|
|
64
|
-
**State variables** with visibility (`public`, `private`), `readonly` (immutable), and `static readonly` (constant).
|
|
65
|
-
|
|
66
|
-
**Functions** with automatic state mutability inference (pure, view, payable), virtual/override, getters/setters, `receive()`, and `fallback()`.
|
|
67
|
-
|
|
68
|
-
**Events** via `SkittlesEvent<T>` with indexed parameter support.
|
|
69
|
-
|
|
70
|
-
**Custom errors** via `SkittlesError<T>` or class extends Error.
|
|
71
|
-
|
|
72
|
-
**Inheritance** with `extends` and `super`.
|
|
73
|
-
|
|
74
|
-
**Control flow**: if/else, for, while, do/while, for...of, switch/case, ternary.
|
|
75
|
-
|
|
76
|
-
**EVM globals**: `msg.sender`, `msg.value`, `block.timestamp`, `block.number`, `tx.origin`, and more.
|
|
77
|
-
|
|
78
|
-
**Built in functions**: `keccak256()`, `sha256()`, `hash()`, `assert()`, `abi.encode()`, `abi.encodePacked()`.
|
|
79
|
-
|
|
80
|
-
**Cross file support**: shared structs, enums, constants, and functions across contract files.
|
|
81
|
-
|
|
82
|
-
**Incremental compilation**: only recompiles files that have changed.
|
|
83
|
-
|
|
84
|
-
## Build Output
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
build/
|
|
88
|
-
abi/ # Contract ABIs (JSON)
|
|
89
|
-
bytecode/ # EVM bytecode
|
|
90
|
-
solidity/ # Generated Solidity source
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## Configuration
|
|
94
|
-
|
|
95
|
-
Create a `skittles.config.json` in your project root:
|
|
96
|
-
|
|
97
|
-
```json
|
|
98
|
-
{
|
|
99
|
-
"contractsDir": "contracts",
|
|
100
|
-
"outputDir": "build",
|
|
101
|
-
"typeCheck": true,
|
|
102
|
-
"optimizer": {
|
|
103
|
-
"enabled": true,
|
|
104
|
-
"runs": 200
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Testing
|
|
110
|
-
|
|
111
|
-
Skittles generates standard Solidity artifacts (ABI + bytecode), so you can test with any EVM testing tool. The [example project](./example) uses Hardhat and ethers.js with Vitest.
|
|
112
|
-
|
|
113
66
|
## Contributing
|
|
114
67
|
|
|
115
68
|
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
package/dist/commands/clean.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
async function cleanCommand(projectRoot) {
|
|
12
|
-
const config = await (0, config_1.loadConfig)(projectRoot);
|
|
13
|
-
const outputDir = path_1.default.join(projectRoot, config.outputDir);
|
|
14
|
-
(0, console_1.logInfo)(`Removing build directory: ${config.outputDir}/`);
|
|
15
|
-
(0, file_1.removeDirectory)(outputDir);
|
|
16
|
-
(0, console_1.logSuccess)("Build artifacts cleaned");
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { removeDirectory } from "../utils/file.js";
|
|
3
|
+
import { logSuccess, logInfo } from "../utils/console.js";
|
|
4
|
+
import { loadConfig } from "../config/config.js";
|
|
5
|
+
export async function cleanCommand(projectRoot) {
|
|
6
|
+
const config = await loadConfig(projectRoot);
|
|
7
|
+
const outputDir = path.join(projectRoot, config.outputDir);
|
|
8
|
+
logInfo(`Removing build directory: ${config.outputDir}/`);
|
|
9
|
+
removeDirectory(outputDir);
|
|
10
|
+
logSuccess("Build artifacts cleaned");
|
|
17
11
|
}
|
|
18
12
|
//# sourceMappingURL=clean.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"clean.js","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3D,OAAO,CAAC,6BAA6B,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;IAC1D,eAAe,CAAC,SAAS,CAAC,CAAC;IAC3B,UAAU,CAAC,yBAAyB,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/commands/compile.js
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const ora_1 = __importDefault(require("ora"));
|
|
8
|
-
const config_1 = require("../config/config");
|
|
9
|
-
const compiler_1 = require("../compiler/compiler");
|
|
10
|
-
const console_1 = require("../utils/console");
|
|
11
|
-
async function compileCommand(projectRoot) {
|
|
12
|
-
const spinner = (0, ora_1.default)("Loading configuration...").start();
|
|
1
|
+
import ora from "ora";
|
|
2
|
+
import { loadConfig } from "../config/config.js";
|
|
3
|
+
import { compile } from "../compiler/compiler.js";
|
|
4
|
+
import { logSuccess, logError } from "../utils/console.js";
|
|
5
|
+
export async function compileCommand(projectRoot) {
|
|
6
|
+
const spinner = ora("Loading configuration...").start();
|
|
13
7
|
try {
|
|
14
|
-
const config = await
|
|
8
|
+
const config = await loadConfig(projectRoot);
|
|
15
9
|
spinner.text = "Compiling contracts...";
|
|
16
|
-
const result = await
|
|
10
|
+
const result = await compile(projectRoot, config);
|
|
17
11
|
if (result.success) {
|
|
18
12
|
spinner.succeed("Compilation complete");
|
|
19
|
-
|
|
13
|
+
logSuccess(`${result.artifacts.length} contract(s) compiled successfully`);
|
|
20
14
|
}
|
|
21
15
|
else {
|
|
22
16
|
spinner.fail("Compilation failed");
|
|
23
17
|
for (const error of result.errors) {
|
|
24
|
-
|
|
18
|
+
logError(error);
|
|
25
19
|
}
|
|
26
20
|
process.exit(1);
|
|
27
21
|
}
|
|
@@ -29,7 +23,7 @@ async function compileCommand(projectRoot) {
|
|
|
29
23
|
catch (err) {
|
|
30
24
|
spinner.fail("Compilation failed");
|
|
31
25
|
const message = err instanceof Error ? err.message : "Unknown error occurred";
|
|
32
|
-
|
|
26
|
+
logError(message);
|
|
33
27
|
process.exit(1);
|
|
34
28
|
}
|
|
35
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,OAAO,GAAG,GAAG,CAAC,0BAA0B,CAAC,CAAC,KAAK,EAAE,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,GAAG,wBAAwB,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAElD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;YACxC,UAAU,CACR,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,oCAAoC,CAC/D,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACnC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACnC,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;QAChE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AA4IA,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2GpE"}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.initCommand = initCommand;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const file_1 = require("../utils/file");
|
|
10
|
-
const console_1 = require("../utils/console");
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { writeFile, ensureDirectory } from "../utils/file.js";
|
|
4
|
+
import { logSuccess, logInfo, logWarning } from "../utils/console.js";
|
|
11
5
|
const CONFIG_TEMPLATE = JSON.stringify({
|
|
12
6
|
typeCheck: true,
|
|
13
7
|
optimizer: {
|
|
@@ -20,7 +14,8 @@ const CONFIG_TEMPLATE = JSON.stringify({
|
|
|
20
14
|
const TSCONFIG_TEMPLATE = JSON.stringify({
|
|
21
15
|
compilerOptions: {
|
|
22
16
|
target: "ES2022",
|
|
23
|
-
module: "
|
|
17
|
+
module: "nodenext",
|
|
18
|
+
moduleResolution: "nodenext",
|
|
24
19
|
lib: ["ES2022"],
|
|
25
20
|
strict: true,
|
|
26
21
|
strictPropertyInitialization: false,
|
|
@@ -32,9 +27,28 @@ const TSCONFIG_TEMPLATE = JSON.stringify({
|
|
|
32
27
|
outDir: "./dist",
|
|
33
28
|
rootDir: ".",
|
|
34
29
|
},
|
|
35
|
-
include: ["contracts/**/*"],
|
|
30
|
+
include: ["contracts/**/*", "test/**/*"],
|
|
36
31
|
exclude: ["node_modules", "build", "dist"],
|
|
37
32
|
}, null, 2);
|
|
33
|
+
const VITEST_CONFIG_TEMPLATE = `import { defineConfig } from "vitest/config";
|
|
34
|
+
|
|
35
|
+
export default defineConfig({
|
|
36
|
+
test: {
|
|
37
|
+
environment: "node",
|
|
38
|
+
include: ["test/**/*.test.ts"],
|
|
39
|
+
testTimeout: 30000,
|
|
40
|
+
server: {
|
|
41
|
+
deps: {
|
|
42
|
+
inline: ["skittles"],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
`;
|
|
48
|
+
const HARDHAT_CONFIG_TEMPLATE = `import { defineConfig } from "hardhat/config";
|
|
49
|
+
|
|
50
|
+
export default defineConfig({});
|
|
51
|
+
`;
|
|
38
52
|
const EXAMPLE_CONTRACT = `import { address, msg } from "skittles";
|
|
39
53
|
|
|
40
54
|
export class Token {
|
|
@@ -63,54 +77,152 @@ export class Token {
|
|
|
63
77
|
}
|
|
64
78
|
}
|
|
65
79
|
`;
|
|
66
|
-
|
|
67
|
-
|
|
80
|
+
const EXAMPLE_TEST = `import { describe, it, expect, beforeAll } from "vitest";
|
|
81
|
+
import { setup } from "skittles/testing";
|
|
82
|
+
|
|
83
|
+
const INITIAL_SUPPLY = 1_000_000n;
|
|
84
|
+
|
|
85
|
+
describe("Token", () => {
|
|
86
|
+
const env = setup();
|
|
87
|
+
let token: any;
|
|
88
|
+
|
|
89
|
+
beforeAll(async () => {
|
|
90
|
+
token = await env.deploy("Token", [INITIAL_SUPPLY]);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("has the correct name", async () => {
|
|
94
|
+
expect(await token.name()).toBe("MyToken");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("has the correct symbol", async () => {
|
|
98
|
+
expect(await token.symbol()).toBe("MTK");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("assigns initial supply to the deployer", async () => {
|
|
102
|
+
const [deployer] = env.accounts;
|
|
103
|
+
const balance = await token.balanceOf(await deployer.getAddress());
|
|
104
|
+
expect(balance).toBe(INITIAL_SUPPLY);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("transfers tokens between accounts", async () => {
|
|
108
|
+
const [, alice] = env.accounts;
|
|
109
|
+
const aliceAddr = await alice.getAddress();
|
|
110
|
+
|
|
111
|
+
await token.transfer(aliceAddr, 100n);
|
|
112
|
+
expect(await token.balanceOf(aliceAddr)).toBe(100n);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("reverts on insufficient balance", async () => {
|
|
116
|
+
const [, alice, bob] = env.accounts;
|
|
117
|
+
const bobAddr = await bob.getAddress();
|
|
118
|
+
const aliceToken = env.connectAs(token, alice);
|
|
119
|
+
|
|
120
|
+
await expect(
|
|
121
|
+
aliceToken.transfer(bobAddr, 999_999_999n)
|
|
122
|
+
).rejects.toThrow();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
`;
|
|
126
|
+
export async function initCommand(projectRoot) {
|
|
127
|
+
logInfo("Initializing new Skittles project...");
|
|
68
128
|
// Create contracts directory
|
|
69
|
-
const contractsDir =
|
|
70
|
-
|
|
71
|
-
|
|
129
|
+
const contractsDir = path.join(projectRoot, "contracts");
|
|
130
|
+
ensureDirectory(contractsDir);
|
|
131
|
+
logSuccess("Created contracts/ directory");
|
|
132
|
+
// Create test directory
|
|
133
|
+
const testDir = path.join(projectRoot, "test");
|
|
134
|
+
ensureDirectory(testDir);
|
|
135
|
+
logSuccess("Created test/ directory");
|
|
72
136
|
// Write config file
|
|
73
|
-
const configPath =
|
|
74
|
-
if (
|
|
75
|
-
|
|
137
|
+
const configPath = path.join(projectRoot, "skittles.config.json");
|
|
138
|
+
if (fs.existsSync(configPath)) {
|
|
139
|
+
logWarning("skittles.config.json already exists, skipping");
|
|
76
140
|
}
|
|
77
141
|
else {
|
|
78
|
-
|
|
79
|
-
|
|
142
|
+
writeFile(configPath, CONFIG_TEMPLATE + "\n");
|
|
143
|
+
logSuccess("Created skittles.config.json");
|
|
80
144
|
}
|
|
81
145
|
// Write example contract
|
|
82
|
-
const examplePath =
|
|
83
|
-
if (
|
|
84
|
-
|
|
146
|
+
const examplePath = path.join(contractsDir, "Token.ts");
|
|
147
|
+
if (fs.existsSync(examplePath)) {
|
|
148
|
+
logWarning("contracts/Token.ts already exists, skipping");
|
|
85
149
|
}
|
|
86
150
|
else {
|
|
87
|
-
|
|
88
|
-
|
|
151
|
+
writeFile(examplePath, EXAMPLE_CONTRACT);
|
|
152
|
+
logSuccess("Created contracts/Token.ts");
|
|
153
|
+
}
|
|
154
|
+
// Write example test
|
|
155
|
+
const exampleTestPath = path.join(testDir, "Token.test.ts");
|
|
156
|
+
if (fs.existsSync(exampleTestPath)) {
|
|
157
|
+
logWarning("test/Token.test.ts already exists, skipping");
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
writeFile(exampleTestPath, EXAMPLE_TEST);
|
|
161
|
+
logSuccess("Created test/Token.test.ts");
|
|
89
162
|
}
|
|
90
163
|
// Write tsconfig.json
|
|
91
|
-
const tsconfigPath =
|
|
92
|
-
if (
|
|
93
|
-
|
|
164
|
+
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
|
165
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
166
|
+
logWarning("tsconfig.json already exists, skipping");
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
writeFile(tsconfigPath, TSCONFIG_TEMPLATE + "\n");
|
|
170
|
+
logSuccess("Created tsconfig.json");
|
|
171
|
+
}
|
|
172
|
+
// Write vitest.config.ts
|
|
173
|
+
const vitestConfigPath = path.join(projectRoot, "vitest.config.ts");
|
|
174
|
+
if (fs.existsSync(vitestConfigPath)) {
|
|
175
|
+
logWarning("vitest.config.ts already exists, skipping");
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
writeFile(vitestConfigPath, VITEST_CONFIG_TEMPLATE);
|
|
179
|
+
logSuccess("Created vitest.config.ts");
|
|
180
|
+
}
|
|
181
|
+
// Write hardhat.config.ts
|
|
182
|
+
const hardhatConfigPath = path.join(projectRoot, "hardhat.config.ts");
|
|
183
|
+
if (fs.existsSync(hardhatConfigPath)) {
|
|
184
|
+
logWarning("hardhat.config.ts already exists, skipping");
|
|
94
185
|
}
|
|
95
186
|
else {
|
|
96
|
-
|
|
97
|
-
|
|
187
|
+
writeFile(hardhatConfigPath, HARDHAT_CONFIG_TEMPLATE);
|
|
188
|
+
logSuccess("Created hardhat.config.ts");
|
|
189
|
+
}
|
|
190
|
+
// Ensure package.json has "type": "module"
|
|
191
|
+
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
192
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
193
|
+
try {
|
|
194
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
195
|
+
if (pkg.type !== "module") {
|
|
196
|
+
pkg.type = "module";
|
|
197
|
+
writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
198
|
+
logSuccess('Added "type": "module" to package.json');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
logWarning("Could not update package.json, please add '\"type\": \"module\"' manually");
|
|
203
|
+
}
|
|
98
204
|
}
|
|
99
205
|
// Update .gitignore
|
|
100
|
-
const gitignorePath =
|
|
206
|
+
const gitignorePath = path.join(projectRoot, ".gitignore");
|
|
101
207
|
const gitignoreEntries = ["build/", "dist/", "node_modules/"];
|
|
102
|
-
if (
|
|
103
|
-
const existing =
|
|
208
|
+
if (fs.existsSync(gitignorePath)) {
|
|
209
|
+
const existing = fs.readFileSync(gitignorePath, "utf-8");
|
|
104
210
|
const toAdd = gitignoreEntries.filter((entry) => !existing.includes(entry));
|
|
105
211
|
if (toAdd.length > 0) {
|
|
106
|
-
|
|
107
|
-
|
|
212
|
+
fs.appendFileSync(gitignorePath, "\n" + toAdd.join("\n") + "\n");
|
|
213
|
+
logSuccess("Updated .gitignore");
|
|
108
214
|
}
|
|
109
215
|
}
|
|
110
216
|
else {
|
|
111
|
-
|
|
112
|
-
|
|
217
|
+
writeFile(gitignorePath, gitignoreEntries.join("\n") + "\n");
|
|
218
|
+
logSuccess("Created .gitignore");
|
|
113
219
|
}
|
|
114
|
-
|
|
220
|
+
logSuccess("Skittles project initialized!");
|
|
221
|
+
logInfo("");
|
|
222
|
+
logInfo("Next steps:");
|
|
223
|
+
logInfo(" 1. Install testing dependencies:");
|
|
224
|
+
logInfo(" npm install --save-dev ethers hardhat vitest");
|
|
225
|
+
logInfo(" 2. Compile and test:");
|
|
226
|
+
logInfo(" npx skittles test");
|
|
115
227
|
}
|
|
116
228
|
//# sourceMappingURL=init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { loadConfig } from "../config/config.js";
|
|
3
|
+
import { compile } from "../compiler/compiler.js";
|
|
4
|
+
import { logSuccess, logError, logInfo } from "../utils/console.js";
|
|
5
|
+
/**
|
|
6
|
+
* The `skittles test` command.
|
|
7
|
+
* 1. Compiles all contracts (same as `skittles compile`)
|
|
8
|
+
* 2. Runs vitest
|
|
9
|
+
*/
|
|
10
|
+
export async function testCommand(projectRoot, watch) {
|
|
11
|
+
// Step 1: Compile contracts
|
|
12
|
+
logInfo("Compiling contracts before running tests...");
|
|
13
|
+
try {
|
|
14
|
+
const config = await loadConfig(projectRoot);
|
|
15
|
+
const result = await compile(projectRoot, config);
|
|
16
|
+
if (!result.success) {
|
|
17
|
+
for (const error of result.errors) {
|
|
18
|
+
logError(error);
|
|
19
|
+
}
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
logSuccess(`${result.artifacts.length} contract(s) compiled successfully`);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const message = err instanceof Error ? err.message : "Unknown error occurred";
|
|
26
|
+
logError(`Compilation failed: ${message}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
// Step 2: Run vitest
|
|
30
|
+
logInfo(watch ? "Starting vitest in watch mode..." : "Running tests...");
|
|
31
|
+
const args = watch ? ["--watch"] : ["run"];
|
|
32
|
+
const child = spawn("npx", ["vitest", ...args], {
|
|
33
|
+
cwd: projectRoot,
|
|
34
|
+
stdio: "inherit",
|
|
35
|
+
shell: true,
|
|
36
|
+
});
|
|
37
|
+
child.on("close", (code) => {
|
|
38
|
+
process.exit(code ?? 0);
|
|
39
|
+
});
|
|
40
|
+
child.on("error", (err) => {
|
|
41
|
+
logError(`Failed to start vitest: ${err.message}`);
|
|
42
|
+
logInfo('Make sure vitest is installed: npm install --save-dev vitest');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEpE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,WAAmB,EACnB,KAAc;IAEd,4BAA4B;IAC5B,OAAO,CAAC,6CAA6C,CAAC,CAAC;IAEvD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAElD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,UAAU,CACR,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,oCAAoC,CAC/D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC;QAChE,QAAQ,CAAC,uBAAuB,OAAO,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAEzE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE;QAC9C,GAAG,EAAE,WAAW;QAChB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;QACzB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACxB,QAAQ,CAAC,2BAA2B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,8DAA8D,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SkittlesContract, type SkittlesType, type Statement, type Expression } from "../types";
|
|
1
|
+
import { type SkittlesContract, type SkittlesType, type Statement, type Expression } from "../types/index.ts";
|
|
2
2
|
/**
|
|
3
3
|
* Generate a Solidity file containing multiple contracts.
|
|
4
4
|
* Used when a single source file defines multiple classes (e.g., for inheritance).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/compiler/codegen.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAKrB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EAKhB,MAAM,
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/compiler/codegen.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EAKrB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EAKhB,MAAM,mBAAmB,CAAC;AAM3B;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAe1E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAEnE;AA8LD,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CA6BvD;AAuBD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAmE3D;AAMD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAiKzE"}
|