Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: constructor validation on build #226

Merged
merged 29 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
18e9386
fix: constructor validation on build
osalkanovic Sep 16, 2022
6d1d9bf
Update unordered-map.js
osalkanovic Sep 16, 2022
fd356cc
feat: constructor checker
osalkanovic Oct 9, 2022
1c4938e
feat: constructor validation
osalkanovic Oct 9, 2022
eb7730e
Merge branch 'fix/constructor-validation' of github.com:osalkanovic/n…
osalkanovic Oct 9, 2022
a457a44
Merge branch 'develop' of github.com:osalkanovic/near-sdk-js into fix…
osalkanovic Oct 9, 2022
4badd6f
fix: resolve conflicts
osalkanovic Oct 9, 2022
125086e
fix: resolve conflicts
osalkanovic Oct 9, 2022
f7d1b7d
fix: code cleaning
osalkanovic Oct 9, 2022
8e1943b
fix: code cleaning
osalkanovic Oct 9, 2022
8460a91
fix: code cleaning
osalkanovic Oct 9, 2022
1aec5c9
fix: lint
osalkanovic Oct 9, 2022
df50b2d
fix: tests
osalkanovic Oct 9, 2022
72d21d0
fix: empty state contract
osalkanovic Oct 9, 2022
81b48bc
fix: update contract valdiation to handle clean-state example
osalkanovic Oct 9, 2022
1c9eedd
linter fix
volovyks Oct 11, 2022
a2806e6
Merge branch 'develop' into fix/constructor-validation
volovyks Oct 12, 2022
c558746
merge conflicts fixed
volovyks Oct 24, 2022
7e0eb28
constructor validation moved to utils
volovyks Oct 24, 2022
80306f8
constructor test contracts renamed, typos fixed
volovyks Oct 24, 2022
f48b632
redandunt comment deleted
volovyks Oct 24, 2022
391212a
Error messages changed
volovyks Oct 24, 2022
664d178
log comments added to contract validation
volovyks Oct 24, 2022
50c6e59
yarn build
volovyks Oct 24, 2022
5025f8e
cli/cli.js deleted
volovyks Oct 24, 2022
e57364d
contract validation added to the main pipeline
volovyks Oct 25, 2022
bfc09a6
contract validation rewrittent with TS
volovyks Oct 25, 2022
fc0fb95
signal used in contract validation, tests rewritten
volovyks Oct 25, 2022
64a3c6e
contract validation doc added
volovyks Oct 25, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cli/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { nodeResolve } from "@rollup/plugin-node-resolve";
import sourcemaps from "rollup-plugin-sourcemaps";
import { babel } from "@rollup/plugin-babel";
import { rollup } from "rollup";

import validateContract from "./contract_validation.js";
import { executeCommand } from "./utils.js";

const PROJECT_DIR = process.cwd();
Expand Down Expand Up @@ -86,6 +86,7 @@ async function checkTsBuildWithTsc(sourceFileWithPath) {

// Common build function
async function createJsFileWithRullup(sourceFileWithPath, rollupTarget) {
await validateContract(sourceFileWithPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice step! All existing contracts can pass the validation

console.log(`Creating ${rollupTarget} file with Rollup...`);
const bundle = await rollup({
input: sourceFileWithPath,
Expand Down
57 changes: 57 additions & 0 deletions cli/contract_validation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Project } from "ts-morph";
import path from "path";
import chalk from "chalk";

const validateContract = async (contractPath) => {
const project = new Project();
project.addSourceFilesAtPaths(contractPath);
const baseFileName = path.parse(contractPath).base;
const contractClassFile = project.getSourceFile(contractPath);
const contractClasses = contractClassFile.getClasses(baseFileName);
for (const contractClass of contractClasses) {
const classStructure = contractClass.getStructure();
const { decorators, properties } = classStructure;
const hasBindgen = decorators.find(
(decorator) => decorator.name === "NearBindgen"
);
if (hasBindgen) {
const constructors = contractClass.getConstructors();
const hasConstructor = constructors.length > 0;
const propertiesToBeInited = properties.filter((p) => !p.initializer);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it work with JS contracts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not work for JS contracts due to the absence of parameter declaration.

// reson: examples/clean-state.js
volovyks marked this conversation as resolved.
Show resolved Hide resolved
if (!hasConstructor && propertiesToBeInited.length === 0) {
return true;
}
if (!hasConstructor && propertiesToBeInited.length > 0) {
console.log(
chalk.redBright(
`Ops, constructor isnt initialized, after initialization include ${propertiesToBeInited
volovyks marked this conversation as resolved.
Show resolved Hide resolved
.map((p) => p.name)
.join(", ")} in constructor`
)
);
process.exit(2);
}
const constructor = constructors[0];
const constructorContent = constructor.getText();
const nonInitedProperties = [];
for (const property of propertiesToBeInited) {
if (!constructorContent.includes(`this.${property.name} =`)) {
nonInitedProperties.push(property.name);
}
}
if (nonInitedProperties.length > 0) {
console.log(
chalk.redBright(
`Ops, please initialise ${nonInitedProperties.join(
", "
)} in constructor`
)
);
process.exit(2);
}
}
}
};

export default validateContract;
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
"@types/babel__traverse": "^7.18.1",
"@types/node": "^17.0.38",
"@types/rollup": "^0.54.0",
"chalk": "^5.1.0",
"ts-morph": "^16.0.0",
"@typescript-eslint/eslint-plugin": "^5.37.0",
"@typescript-eslint/parser": "^5.37.0",
"eslint": "^8.23.1",
Expand Down
53 changes: 53 additions & 0 deletions tests/__tests__/constructor_validation.ava.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import test from "ava";
import { execSync } from "child_process";

test("should build, constructor is correctly initialized", async (t) => {
let result = null;
try {
result = execSync(
volovyks marked this conversation as resolved.
Show resolved Hide resolved
"near-sdk-js build src/constructor-validation/version-1.ts build/constructor-validation/version-1.wasm"
).toString();
} catch (e) {
result = e;
}
t.not(result.status, 2);
volovyks marked this conversation as resolved.
Show resolved Hide resolved
});

test("should throw error, name isnt inited", async (t) => {
let result = null;
try {
result = execSync(
"near-sdk-js build src/constructor-validation/version-2.ts build/constructor-validation/version-2.wasm"
).toString();
} catch (e) {
result = e;
}

t.is(result.status, 2);
});

test("should throw error, construcor is empty", async (t) => {
let result = null;
try {
volovyks marked this conversation as resolved.
Show resolved Hide resolved
result = execSync(
"near-sdk-js build src/constructor-validation/version-3.ts build/constructor-validation/version-3.wasm"
).toString();
} catch (e) {
result = e;
}

t.is(result.status, 2);
});

test("should throw error, construcor isnt declared", async (t) => {
volovyks marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to compare error text here. Can we do that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think result.stdout / result.stderr records the error text

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation error is overridden with another top-level error. Added const for now.

let result = null;
try {
result = execSync(
"near-sdk-js build src/constructor-validation/version-4.ts build/constructor-validation/version-4.wasm"
).toString();
} catch (e) {
result = e;
}

t.is(result.status, 2);
});
3 changes: 2 additions & 1 deletion tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
"test:private": "ava __tests__/decorators/private.ava.js",
"test:bigint-serialization": "ava __tests__/test-bigint-serialization.ava.js",
"test:date-serialization": "ava __tests__/test-date-serialization.ava.js",
"test:serialization": "ava __tests__/test-serialization.ava.js"
"test:serialization": "ava __tests__/test-serialization.ava.js",
"test:constructor-validation": "ava __tests__/constructor_validation.ava.js"
},
"author": "Near Inc <hello@nearprotocol.com>",
"license": "Apache-2.0",
Expand Down
16 changes: 16 additions & 0 deletions tests/src/constructor-validation/version-1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NearBindgen, LookupMap, call } from "near-sdk-js";

@NearBindgen({})
export class ConstructorValidation {
map: LookupMap<string>;
name: string;
constructor() {
this.map = new LookupMap<string>("a");
this.name = "";
}

@call({})
get() {
return { status: "ok" };
}
}
10 changes: 10 additions & 0 deletions tests/src/constructor-validation/version-2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NearBindgen, LookupMap } from "near-sdk-js";

@NearBindgen({})
export class ConstructorValidation {
map: LookupMap<string>;
name: string;
constructor() {
this.map = new LookupMap<string>("a");
}
}
10 changes: 10 additions & 0 deletions tests/src/constructor-validation/version-3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NearBindgen, LookupMap } from "near-sdk-js";

@NearBindgen({})
export class ConstructorValidation {
map: LookupMap<string>;
name: string;
constructor() {
//
}
}
7 changes: 7 additions & 0 deletions tests/src/constructor-validation/version-4.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { NearBindgen, LookupMap } from "near-sdk-js";
volovyks marked this conversation as resolved.
Show resolved Hide resolved

@NearBindgen({})
export class ConstructorValidation {
map: LookupMap<string>;
name: string;
}
Loading