Skip to content

Commit

Permalink
Feat/migrations typescript support (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
Standaa authored Mar 31, 2021
1 parent d0396ea commit 7f2ef23
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 12 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ jobs:
- pushd examples/misc && anchor test && popd
- pushd examples/events && anchor test && popd
- pushd examples/cashiers-check && anchor test && popd
- pushd examples/typescript && yarn && anchor test && popd
- <<: *examples
name: Runs the examples 2
script:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ incremented for features.
* lang: Allow overriding the `#[state]` account's size ([#121](https://github.com/project-serum/anchor/pull/121)).
* lang, client, ts: Add event emission and subscriptions ([#89](https://github.com/project-serum/anchor/pull/89)).
* lang/account: Allow namespacing account discriminators ([#128](https://github.com/project-serum/anchor/pull/128)).
* cli: TypeScript migrations ([#132](https://github.com/project-serum/anchor/pull/132)).

## Breaking Changes

Expand Down
53 changes: 41 additions & 12 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,22 +252,26 @@ fn init(name: String, typescript: bool) -> Result<()> {

// Build the test suite.
fs::create_dir("tests")?;
// Build the migrations directory.
fs::create_dir("migrations")?;

if typescript {
// Build typescript config
let mut ts_config = File::create("tsconfig.json")?;
ts_config.write_all(template::ts_config().as_bytes())?;

let mut deploy = File::create("migrations/deploy.ts")?;
deploy.write_all(&template::ts_deploy_script().as_bytes())?;

let mut mocha = File::create(&format!("tests/{}.spec.ts", name))?;
mocha.write_all(template::ts_mocha(&name).as_bytes())?;
} else {
let mut mocha = File::create(&format!("tests/{}.js", name))?;
mocha.write_all(template::mocha(&name).as_bytes())?;
}

// Build the migrations directory.
fs::create_dir("migrations")?;
let mut deploy = File::create("migrations/deploy.js")?;
deploy.write_all(&template::deploy_script().as_bytes())?;
let mut deploy = File::create("migrations/deploy.js")?;
deploy.write_all(&template::deploy_script().as_bytes())?;
}

println!("{} initialized", name);

Expand Down Expand Up @@ -1206,7 +1210,8 @@ fn launch(url: Option<String>, keypair: Option<String>, verifiable: bool) -> Res
}

// Run migration script.
if Path::new("migrations/deploy.js").exists() {
if Path::new("migrations/deploy.js").exists() || Path::new("migrations/deploy.ts").exists()
{
migrate(Some(url))?;
}

Expand Down Expand Up @@ -1386,22 +1391,46 @@ fn migrate(url: Option<String>) -> Result<()> {

let url = url.unwrap_or_else(|| cfg.cluster.url().to_string());
let cur_dir = std::env::current_dir()?;
let module_path = format!("{}/migrations/deploy.js", cur_dir.display());
let deploy_script_host_str = template::deploy_script_host(&url, &module_path);
let module_path = cur_dir.join("migrations/deploy.js");

let ts_config_exist = Path::new("tsconfig.json").exists();
let ts_deploy_file_exists = Path::new("migrations/deploy.ts").exists();

if ts_config_exist && ts_deploy_file_exists {
let ts_module_path = cur_dir.join("migrations/deploy.ts");
let exit = std::process::Command::new("tsc")
.arg(&ts_module_path)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()?;
if !exit.status.success() {
std::process::exit(exit.status.code().unwrap());
}
};

let deploy_script_host_str =
template::deploy_script_host(&url, &module_path.display().to_string());

if !Path::new(".anchor").exists() {
fs::create_dir(".anchor")?;
}
std::env::set_current_dir(".anchor")?;

std::fs::write("deploy.js", deploy_script_host_str)?;
if let Err(_e) = std::process::Command::new("node")
let exit = std::process::Command::new("node")
.arg("deploy.js")
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.output()
{
std::process::exit(1);
.output()?;

if ts_config_exist && ts_deploy_file_exists {
std::fs::remove_file(&module_path)
.map_err(|_| anyhow!("Unable to remove file {}", module_path.display()))?;
}

if !exit.status.success() {
println!("Deploy failed.");
std::process::exit(exit.status.code().unwrap());
}

println!("Deploy complete.");
Expand Down
18 changes: 18 additions & 0 deletions cli/src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ module.exports = async function (provider) {
}
"#
}

pub fn ts_deploy_script() -> &'static str {
r#"
// Migrations are an early feature. Currently, they're nothing more than this
// single deploy script that's invoked from the CLI, injecting a provider
// configured from the workspace's Anchor.toml.
const anchor = require("@project-serum/anchor");
module.exports = async function (provider) {
// Configure client to use the provider.
anchor.setProvider(provider);
// Add your deploy script here.
}
"#
}

pub fn xargo_toml() -> &'static str {
r#"[target.bpfel-unknown-unknown.dependencies.std]
features = []"#
Expand Down
2 changes: 2 additions & 0 deletions examples/typescript/Anchor.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cluster = "localnet"
wallet = "~/.config/solana/id.json"
4 changes: 4 additions & 0 deletions examples/typescript/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[workspace]
members = [
"programs/*"
]
22 changes: 22 additions & 0 deletions examples/typescript/migrations/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Migrations are an early feature. Currently, they're nothing more than this
// single deploy script that's invoked from the CLI, injecting a provider
// configured from the workspace's Anchor.toml.

const anchor = require("@project-serum/anchor");

module.exports = async function (provider) {
// Configure client to use the provider.
anchor.setProvider(provider);

// Add your deploy script here.
async function deployAsync(exampleString: string): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log(exampleString);
resolve();
}, 2000);
});
}

await deployAsync("Typescript migration example complete.");
}
17 changes: 17 additions & 0 deletions examples/typescript/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "typescript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"test": "tests"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@types/node": "^14.14.37"
}
}
18 changes: 18 additions & 0 deletions examples/typescript/programs/typescript/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "typescript"
version = "0.1.0"
description = "Created with Anchor"
edition = "2018"

[lib]
crate-type = ["cdylib", "lib"]
name = "typescript"

[features]
no-entrypoint = []
no-idl = []
cpi = ["no-entrypoint"]
default = []

[dependencies]
anchor-lang = { path = "../../../../lang" }
2 changes: 2 additions & 0 deletions examples/typescript/programs/typescript/Xargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.bpfel-unknown-unknown.dependencies.std]
features = []
17 changes: 17 additions & 0 deletions examples/typescript/programs/typescript/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! The typescript example serves to show how one would setup an Anchor
//! workspace with TypeScript tests and migrations.
#![feature(proc_macro_hygiene)]

use anchor_lang::prelude::*;

#[program]
pub mod typescript {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> ProgramResult {
Ok(())
}
}

#[derive(Accounts)]
pub struct Initialize {}
14 changes: 14 additions & 0 deletions examples/typescript/tests/typescript.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as anchor from '@project-serum/anchor';

describe('typescript', () => {

// Configure the client to use the local cluster.
anchor.setProvider(anchor.Provider.env());

it('Is initialized!', async () => {
// Add your test here.
const program = anchor.workspace.Typescript;
const tx = await program.rpc.initialize();
console.log("Your transaction signature", tx);
});
});
10 changes: 10 additions & 0 deletions examples/typescript/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"types": ["mocha", "chai"],
"typeRoots": ["./node_modules/@types"],
"lib": ["es2015"],
"module": "commonjs",
"target": "es6",
"esModuleInterop": true
}
}

0 comments on commit 7f2ef23

Please sign in to comment.