Skip to content

Commit

Permalink
Merge pull request #20 from tablelandnetwork/cli-alias-pr
Browse files Browse the repository at this point in the history
import Dan's PR for alias feature
  • Loading branch information
joewagner authored Aug 23, 2023
2 parents d32e0f2 + d167b90 commit 9cbc584
Show file tree
Hide file tree
Showing 24 changed files with 1,522 additions and 143 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,7 @@ packages/local/validator/*.db*
packages/local/validator/backups

# registry artifacts
packages/local/registry/.openzeppelin/
packages/local/registry/.openzeppelin/

### cli ###
packages/cli/tableland.aliases.json
1 change: 1 addition & 0 deletions packages/cli/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
TBL_PRIVATE_KEY=fillme
TBL_CHAIN=fillme
TBL_PROVIDER_URL=fillme
TBL_ALIASES=fillme
2 changes: 1 addition & 1 deletion packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Options:
--version Show version number [boolean]
-k, --privateKey Private key string [string]
-c, --chain The EVM chain to target [string] [default: "maticmum"]
-p, --providerUrl JSON RPC API provider URL. (e.g., https://eth-rinkeby.alche
-p, --providerUrl JSON RPC API provider URL. (e.g., https://eth-sepolia.alche
myapi.io/v2/123abc123a...) [string]
```
Expand Down
11 changes: 9 additions & 2 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface GlobalOptions {
verbose: boolean;
ensProviderUrl?: string;
enableEnsExperiment?: boolean;
aliases?: string;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -59,7 +60,7 @@ const _argv = yargs(hideBin(process.argv))
.env("TBL")
.config(config?.config)
// the help and version options are internal to yargs, hence they are
// at the top of the help message no matter what order we specifiy
// at the top of the help message no matter what order we specify
.option("help", {
alias: "h",
})
Expand Down Expand Up @@ -91,7 +92,13 @@ const _argv = yargs(hideBin(process.argv))
alias: "p",
type: "string",
description:
"JSON RPC API provider URL. (e.g., https://eth-rinkeby.alchemyapi.io/v2/123abc123a...)",
"JSON RPC API provider URL (e.g., https://eth-sepolia.g.alchemy.com/v2/123abc123a...)",
})
.option("aliases", {
alias: "a",
type: "string",
description:
"Path to table aliases JSON file (e.g., ./tableland.aliases.json)",
})
.demandCommand(1, "")
.strict().argv;
23 changes: 15 additions & 8 deletions packages/cli/src/commands/controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type yargs from "yargs";
import type { Arguments, CommandBuilder } from "yargs";
import { Registry } from "@tableland/sdk";
import { init } from "@tableland/sqlparser";
import {
getTableNameWithAlias,
getWalletWithProvider,
getLink,
logger,
Expand All @@ -28,20 +30,22 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (
(yargs) =>
yargs.positional("name", {
type: "string",
description: "The target table name",
description: "The target table name (or alias, if enabled)",
}) as yargs.Argv<Options>,
async (argv) => {
const { name, privateKey, providerUrl } = argv;
await init();
const { privateKey, providerUrl } = argv;
const chain = getChainName(argv.chain);
const name = await getTableNameWithAlias(argv.aliases, argv.name);

try {
const signer = await getWalletWithProvider({
privateKey,
chain,
providerUrl,
});
const reg = new Registry({ signer });

const reg = new Registry({ signer });
const res = await reg.getController(name);

logger.log(res);
Expand All @@ -62,11 +66,13 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (
})
.positional("name", {
type: "string",
description: "The target table name",
description: "The target table name (or alias, if enabled)",
}) as yargs.Argv<Options>,
async (argv) => {
const { name, controller, privateKey, providerUrl } = argv;
await init();
const { controller, privateKey, providerUrl } = argv;
const chain = getChainName(argv.chain);
const name = await getTableNameWithAlias(argv.aliases, argv.name);

try {
const signer = await getWalletWithProvider({
Expand All @@ -93,11 +99,13 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (
(yargs) =>
yargs.positional("name", {
type: "string",
description: "The target table name",
description: "The target table name (or alias, if enabled)",
}) as yargs.Argv<Options>,
async (argv) => {
const { name, privateKey, providerUrl } = argv;
await init();
const { privateKey, providerUrl } = argv;
const chain = getChainName(argv.chain);
const name = await getTableNameWithAlias(argv.aliases, argv.name);

try {
const signer = await getWalletWithProvider({
Expand All @@ -107,7 +115,6 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (
});

const reg = new Registry({ signer });

const res = await reg.lockController(name);

const link = getLink(chain, res.hash);
Expand Down
29 changes: 19 additions & 10 deletions packages/cli/src/commands/info.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type yargs from "yargs";
import type { Arguments, CommandBuilder } from "yargs";
import { init } from "@tableland/sqlparser";
import { type GlobalOptions } from "../cli.js";
import { setupCommand } from "../lib/commandSetup.js";
import { logger } from "../utils.js";
import { getTableNameWithAlias, logger } from "../utils.js";

export interface Options extends GlobalOptions {
name: string;
Expand All @@ -20,10 +21,21 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (
}) as yargs.Argv<Options>;

export const handler = async (argv: Arguments<Options>): Promise<void> => {
await init();
try {
let { name } = argv;
const [tableId, chainId] = name.split("_").reverse();
let name = await getTableNameWithAlias(argv.aliases, argv.name);

// Check if the passed `name` uses ENS
// Note: duplicative `setupCommand` calls will occur with ENS, but this is
// required to properly parse the chainId from the table name
if (argv.enableEnsExperiment != null && argv.ensProviderUrl != null) {
const { ens } = await setupCommand({
...argv,
});
if (ens != null) name = await ens.resolveTable(name);
}

const [tableId, chainId] = name.split("_").reverse();
const parts = name.split("_");

if (parts.length < 3 && argv.enableEnsExperiment == null) {
Expand All @@ -33,18 +45,15 @@ export const handler = async (argv: Arguments<Options>): Promise<void> => {
return;
}

const { ens, validator } = await setupCommand({
const { validator } = await setupCommand({
...argv,
chain: parseInt(chainId) as any,
});

/* c8 ignore next 3 */
if (argv.enableEnsExperiment != null && ens != null) {
name = await ens.resolveTable(name);
}

// Get the table ID, now that the name comes from either an alias, ENS, or
// the standard naming convention
const res = await validator.getTableById({
tableId,
tableId: tableId.toString(),
chainId: parseInt(chainId),
});
logger.log(JSON.stringify(res));
Expand Down
45 changes: 36 additions & 9 deletions packages/cli/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { resolve, dirname } from "path";
import { mkdirSync, createWriteStream, type WriteStream } from "fs";
import {
mkdirSync,
createWriteStream,
type WriteStream,
writeFileSync,
} from "fs";
import type yargs from "yargs";
import type { Arguments, CommandBuilder } from "yargs";
import yaml from "js-yaml";
import inquirer from "inquirer";
import { getChains, logger } from "../utils.js";
import { getChains, logger, checkAliasesPath } from "../utils.js";
import { type GlobalOptions } from "../cli.js";

export interface Options extends GlobalOptions {
Expand Down Expand Up @@ -82,6 +87,12 @@ export const handler = async (argv: Arguments<Options>): Promise<void> => {
return resolve(`.${moduleName}rc.${answers.format as string}`);
},
},
{
type: "input",
name: "aliases",
message:
"Enter file path to existing table aliases file, or directory path to create a new one (optional)",
},
];

// Extract path and format as we don't include them in the config file
Expand All @@ -92,14 +103,30 @@ export const handler = async (argv: Arguments<Options>): Promise<void> => {
} else {
output = { ...defaults, ...answers };
}
const { path, format, ...rest } = output;
const filePath = resolve(
typeof path === "string" ? path : `.${moduleName}rc`
);
// Create the config file
const { path, format, aliases, ...rest } = output;
const configFilePath = resolve(path ?? `.${moduleName}rc`);
// Make sure the table aliases file or provided directory exists
if (aliases != null) {
try {
const type = checkAliasesPath(aliases);
if (type === "file") {
rest.aliases = resolve(aliases);
}
if (type === "dir") {
const aliasesFilePath = resolve(aliases, "tableland.aliases.json");
writeFileSync(aliasesFilePath, JSON.stringify({}));
rest.aliases = aliasesFilePath;
}
} catch (err: any) {
logger.error(err.message); // exit early since the input was invalid
return;
}
}
let stream = process.stdout as unknown as WriteStream;
if (path !== ".") {
mkdirSync(dirname(filePath), { recursive: true });
stream = createWriteStream(filePath, "utf-8");
mkdirSync(dirname(configFilePath), { recursive: true });
stream = createWriteStream(configFilePath, "utf-8");
}
try {
switch (format) {
Expand All @@ -113,7 +140,7 @@ export const handler = async (argv: Arguments<Options>): Promise<void> => {
break;
}
if (path !== ".") {
logger.log(`Config created at ${filePath}`);
logger.log(`Config created at ${configFilePath}`);
}
} catch (err: any) {
logger.error(err.message);
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ async function setHandler(
const valueRegex = /^[a-zA-Z_][a-zA-Z0-9_]*_[0-9]+_[0-9]+$/;

if (keyRegex.exec(key) === null) {
throw new Error("Only letters or underscores in key name");
throw new Error("only letters or underscores in key name");
}
if (valueRegex.exec(value) === null) {
throw new Error("Tablename is invalid");
throw new Error("table name is invalid");
}
return {
key,
Expand Down Expand Up @@ -84,7 +84,7 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (
yargs
.command(
"get <record>",
"Pass in a record to find it's table name",
"Pass in a record to find its table name",
(yargs) =>
yargs.positional("record", {
type: "string",
Expand Down
20 changes: 16 additions & 4 deletions packages/cli/src/commands/schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type yargs from "yargs";
import type { Arguments, CommandBuilder } from "yargs";
import { init } from "@tableland/sqlparser";
import { type GlobalOptions } from "../cli.js";
import { setupCommand } from "../lib/commandSetup.js";
import { logger } from "../utils.js";
import { logger, getTableNameWithAlias } from "../utils.js";

export interface Options extends GlobalOptions {
name: string;
Expand All @@ -21,9 +22,20 @@ export const builder: CommandBuilder<Record<string, unknown>, Options> = (

export const handler = async (argv: Arguments<Options>): Promise<void> => {
try {
const { name } = argv;
const [tableId, chainId] = name.split("_").reverse();
await init();
let name = await getTableNameWithAlias(argv.aliases, argv.name);

// Check if the passed `name` uses ENS
// Note: duplicative `setupCommand` calls will occur with ENS, but this is
// required to properly parse the chainId from the table name
if (argv.enableEnsExperiment != null && argv.ensProviderUrl != null) {
const { ens } = await setupCommand({
...argv,
});
if (ens != null) name = await ens.resolveTable(name);
}

const [tableId, chainId] = name.split("_").reverse();
const parts = name.split("_");

if (parts.length < 3 && argv.enableEnsExperiment == null) {
Expand All @@ -39,7 +51,7 @@ export const handler = async (argv: Arguments<Options>): Promise<void> => {
});

const res = await validator.getTableById({
tableId,
tableId: tableId.toString(),
chainId: parseInt(chainId),
});
logger.log(JSON.stringify(res.schema));
Expand Down
Loading

0 comments on commit 9cbc584

Please sign in to comment.