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

Add .js file extensions to non-package imports for better ESM support #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
# ESLint and Prettier must be in `package.json`
- name: Install Node.js dependencies
run: yarn --frozen-lockfile
- run: cp -r tests/example-program-gen/{exp,act}
- run: cp -r tests/example-program-gen/**/{exp,act}
- name: Run eslint
run: yarn run lint
- name: Run tsc check
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
**/target/
tests/example-program-gen/act
tests/example-program-gen/**/act
node_modules/
.parcel-cache
.DS_Store
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Arguments:

Options:
--program-id <PROGRAM_ID> optional program ID to be included in the code
--file-extension <ext> file extension for generated import and export statements (default: "js") - use '' for no extension
-V, --version output the version number
-h, --help display help for command
```
Expand Down Expand Up @@ -249,6 +250,20 @@ These are then written into the `programId.ts` file.

The `PROGRAM_ID` constant inside `programId.ts` can be (and should be) modified to define the correct program ID as the client relies on it to do checks when fetching accounts etc. The `PROGRAM_ID` constant is safe to modify as it will be preserved across multiple code generations. The imports in this file are also preserved.

## File extension

The `--file-extension` flag can be used to specify the file extension for generated import and export statements. The default value is `js` (compatible with CJS and ESM). Use `''` for no extension.

- default:
```ts
export { State } from "./State.js"
```

- with `--file-extension ''`:
```ts
export { State } from "./State"
```

## Versioning

The package minor versions match anchor minor versions. So, for example, package version `v0.22.x` will match anchor `v0.22.y`. The earliest supported anchor version is `v0.22`, but the generator probably also works with older versions of anchor since the IDL format is mostly backwards compatible.
4 changes: 2 additions & 2 deletions examples/basic-2/generated-client/accounts/Counter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from "@solana/web3.js"
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import { borshAddress } from "../utils/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId.js"

export interface CounterFields {
authority: Address
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-2/generated-client/accounts/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { Counter } from "./Counter"
export type { CounterFields, CounterJSON } from "./Counter"
export { Counter } from "./Counter.js"
export type { CounterFields, CounterJSON } from "./Counter.js"
4 changes: 2 additions & 2 deletions examples/basic-2/generated-client/errors/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Address } from "@solana/web3.js"
import { PROGRAM_ID } from "../programId"
import * as anchor from "./anchor"
import { PROGRAM_ID } from "../programId.js"
import * as anchor from "./anchor.js"

export function fromCode(
code: number,
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-2/generated-client/instructions/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import { borshAddress } from "../utils/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId.js"

export interface CreateArgs {
authority: Address
Expand Down
4 changes: 2 additions & 2 deletions examples/basic-2/generated-client/instructions/increment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import { borshAddress } from "../utils/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId.js"

export interface IncrementAccounts {
counter: Address
Expand Down
8 changes: 4 additions & 4 deletions examples/basic-2/generated-client/instructions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { create } from "./create"
export type { CreateArgs, CreateAccounts } from "./create"
export { increment } from "./increment"
export type { IncrementAccounts } from "./increment"
export { create } from "./create.js"
export type { CreateArgs, CreateAccounts } from "./create.js"
export { increment } from "./increment.js"
export type { IncrementAccounts } from "./increment.js"
2 changes: 1 addition & 1 deletion examples/basic-2/generated-client/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./borshAddress"
export * from "./borshAddress.js"
6 changes: 3 additions & 3 deletions examples/tic-tac-toe/generated-client/accounts/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
} from "@solana/web3.js"
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import { borshAddress } from "../utils/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId.js"

export interface GameFields {
players: Array<Address>
Expand Down
4 changes: 2 additions & 2 deletions examples/tic-tac-toe/generated-client/accounts/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { Game } from "./Game"
export type { GameFields, GameJSON } from "./Game"
export { Game } from "./Game.js"
export type { GameFields, GameJSON } from "./Game.js"
6 changes: 3 additions & 3 deletions examples/tic-tac-toe/generated-client/errors/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Address } from "@solana/web3.js"
import { PROGRAM_ID } from "../programId"
import * as anchor from "./anchor"
import * as custom from "./custom"
import { PROGRAM_ID } from "../programId.js"
import * as anchor from "./anchor.js"
import * as custom from "./custom.js"

export function fromCode(
code: number,
Expand Down
8 changes: 4 additions & 4 deletions examples/tic-tac-toe/generated-client/instructions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { setupGame } from "./setupGame"
export type { SetupGameArgs, SetupGameAccounts } from "./setupGame"
export { play } from "./play"
export type { PlayArgs, PlayAccounts } from "./play"
export { setupGame } from "./setupGame.js"
export type { SetupGameArgs, SetupGameAccounts } from "./setupGame.js"
export { play } from "./play.js"
export type { PlayArgs, PlayAccounts } from "./play.js"
6 changes: 3 additions & 3 deletions examples/tic-tac-toe/generated-client/instructions/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
} from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import { borshAddress } from "../utils/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId.js"

export interface PlayArgs {
tile: types.TileFields
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
} from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId"
import { borshAddress } from "../utils/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import { PROGRAM_ID } from "../programId.js"

export interface SetupGameArgs {
playerTwo: Address
Expand Down
4 changes: 2 additions & 2 deletions examples/tic-tac-toe/generated-client/types/GameState.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { address, Address } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh"
import { borshAddress } from "../utils"
import { borshAddress } from "../utils/index.js"

export interface ActiveJSON {
kind: "Active"
Expand Down
4 changes: 2 additions & 2 deletions examples/tic-tac-toe/generated-client/types/Sign.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { address, Address } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh"
import { borshAddress } from "../utils"
import { borshAddress } from "../utils/index.js"

export interface XJSON {
kind: "X"
Expand Down
4 changes: 2 additions & 2 deletions examples/tic-tac-toe/generated-client/types/Tile.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { address, Address } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as types from "../types/index.js" // eslint-disable-line @typescript-eslint/no-unused-vars
import * as borsh from "@coral-xyz/borsh"
import { borshAddress } from "../utils"
import { borshAddress } from "../utils/index.js"

export interface TileFields {
row: number
Expand Down
8 changes: 4 additions & 4 deletions examples/tic-tac-toe/generated-client/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as GameState from "./GameState"
import * as Sign from "./Sign"
import * as GameState from "./GameState.js"
import * as Sign from "./Sign.js"

export { Tile } from "./Tile"
export type { TileFields, TileJSON } from "./Tile"
export { Tile } from "./Tile.js"
export type { TileFields, TileJSON } from "./Tile.js"
export { GameState }

export type GameStateKind = GameState.Active | GameState.Tie | GameState.Won
Expand Down
2 changes: 1 addition & 1 deletion examples/tic-tac-toe/generated-client/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./borshAddress"
export * from "./borshAddress.js"
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@
"watch": "tsc --project tsconfig.build.json --watch",
"build": "yarn build:cli && yarn build:test-fixture && yarn generate-examples",
"build:cli": "rimraf ./dist && tsup src/main.ts --format esm",
"build:test-fixture": "yarn build:example-program && yarn build:test-fixture:copy-idl && yarn build:test-fixture:generate-exp",
"build:test-fixture": "yarn build:example-program && yarn build:test-fixture:copy-idl && yarn build:test-fixture:generate-exp:default && yarn build:test-fixture:generate-exp:no-ext",
"build:test-fixture:copy-idl": "cp tests/example-program/target/idl/example_program.json tests/example-program-gen/idl.json",
"build:test-fixture:generate-exp": "rimraf tests/example-program-gen/exp && node ./dist/main.js tests/example-program-gen/idl.json tests/example-program-gen/exp --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8",
"build:test-fixture:generate-exp:default": "rimraf tests/example-program-gen/default/exp && node ./dist/main.js tests/example-program-gen/idl.json tests/example-program-gen/default/exp --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8",
"build:test-fixture:generate-exp:no-ext": "rimraf tests/example-program-gen/no-ext/exp && node ./dist/main.js tests/example-program-gen/idl.json tests/example-program-gen/no-ext/exp --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 --file-extension ''",
"build:example-program": "cd tests/example-program && npx anchor build",
"generate-examples": "rimraf ./examples/**/generated-client && yarn generate-examples:basic-2 && yarn generate-examples:tic-tac-toe",
"generate-examples:basic-2": "node ./dist/main.js examples/basic-2/idl.json examples/basic-2/generated-client --program-id Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
"generate-examples:tic-tac-toe": "node ./dist/main.js examples/tic-tac-toe/idl.json examples/tic-tac-toe/generated-client --program-id Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS",
"test": "yarn test:prepare && start-server-and-test test:start-validator http://127.0.0.1:8899/health 'vitest --watch'",
"test:no-watch": "yarn test:prepare && start-server-and-test test:start-validator http://127.0.0.1:8899/health 'vitest'",
"test:prepare": "yarn build:example-program && yarn test:generate-test-client",
"test:generate-test-client": "rimraf tests/example-program-gen/act && node dist/main.js tests/example-program/target/idl/example_program.json tests/example-program-gen/act --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8",
"test:prepare": "yarn build:example-program && yarn test:generate-test-client:default && yarn test:generate-test-client:no-ext",
"test:generate-test-client:default": "rimraf tests/example-program-gen/default/act && node dist/main.js tests/example-program/target/idl/example_program.json tests/example-program-gen/default/act --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8",
"test:generate-test-client:no-ext": "rimraf tests/example-program-gen/no-ext/act && node dist/main.js tests/example-program/target/idl/example_program.json tests/example-program-gen/no-ext/act --program-id 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 --file-extension ''",
"test:start-validator": "solana-test-validator --ledger tests/.test-ledger --bpf-program 3rTQ3R4B2PxZrAyx7EUefySPgZY8RhJf16cZajbmrzp8 tests/example-program/target/deploy/example_program.so --quiet --reset",
"lint": "eslint . ",
"lint:fix": "eslint . --fix",
Expand Down
23 changes: 13 additions & 10 deletions src/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,22 @@ import {
export function genAccounts(
project: Project,
idl: Idl,
outPath: (path: string) => string
outPath: (path: string) => string,
fileExtension: string
) {
if (idl.accounts === undefined || idl.accounts.length === 0) {
return
}

genIndexFile(project, idl, outPath)
genAccountFiles(project, idl, outPath)
genIndexFile(project, idl, outPath, fileExtension)
genAccountFiles(project, idl, outPath, fileExtension)
}

function genIndexFile(
project: Project,
idl: Idl,
outPath: (path: string) => string
outPath: (path: string) => string,
fileExtension: string
) {
const src = project.createSourceFile(outPath("accounts/index.ts"), "", {
overwrite: true,
Expand All @@ -38,20 +40,21 @@ function genIndexFile(
idl.accounts?.forEach((ix) => {
src.addExportDeclaration({
namedExports: [ix.name],
moduleSpecifier: `./${ix.name}`,
moduleSpecifier: `./${ix.name}${fileExtension}`,
})
src.addExportDeclaration({
namedExports: [fieldsInterfaceName(ix.name), jsonInterfaceName(ix.name)],
isTypeOnly: true,
moduleSpecifier: `./${ix.name}`,
moduleSpecifier: `./${ix.name}${fileExtension}`,
})
})
}

function genAccountFiles(
project: Project,
idl: Idl,
outPath: (path: string) => string
outPath: (path: string) => string,
fileExtension: string
) {
idl.accounts?.forEach((acc) => {
const src = project.createSourceFile(
Expand All @@ -67,13 +70,13 @@ function genAccountFiles(
`import { address, Address, fetchEncodedAccount, fetchEncodedAccounts, GetAccountInfoApi, GetMultipleAccountsApi, Rpc } from "@solana/web3.js"`,
`import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars`,
`import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars`,
`import { borshAddress } from "../utils" // eslint-disable-line @typescript-eslint/no-unused-vars`,
`import { borshAddress } from "../utils/index${fileExtension}" // eslint-disable-line @typescript-eslint/no-unused-vars`,
...(idl.types && idl.types.length > 0
? [
`import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars`,
`import * as types from "../types/index${fileExtension}" // eslint-disable-line @typescript-eslint/no-unused-vars`,
]
: []),
`import { PROGRAM_ID } from "../programId"`,
`import { PROGRAM_ID } from "../programId${fileExtension}"`,
])

const fields = acc.type.fields
Expand Down
14 changes: 8 additions & 6 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ import {
export function genErrors(
project: Project,
idl: Idl,
outPath: (path: string) => string
outPath: (path: string) => string,
fileExtension: string
) {
genIndex(project, idl, outPath)
genIndex(project, idl, outPath, fileExtension)
genCustomErrors(project, idl, outPath)
genAnchorErrors(project, idl, outPath)
}

export function genIndex(
project: Project,
idl: Idl,
outPath: (path: string) => string
outPath: (path: string) => string,
fileExtension: string
) {
const src = project.createSourceFile(outPath("errors/index.ts"), "", {
overwrite: true,
Expand All @@ -29,16 +31,16 @@ export function genIndex(
src.addStatements([`import { Address } from "@solana/web3.js"`])
src.addImportDeclaration({
namedImports: ["PROGRAM_ID"],
moduleSpecifier: "../programId",
moduleSpecifier: `../programId${fileExtension}`,
})
src.addImportDeclaration({
namespaceImport: "anchor",
moduleSpecifier: "./anchor",
moduleSpecifier: `./anchor${fileExtension}`,
})
if (hasCustomErrors) {
src.addImportDeclaration({
namespaceImport: "custom",
moduleSpecifier: "./custom",
moduleSpecifier: `./custom${fileExtension}`,
})
}

Expand Down
Loading
Loading