apibara 2.1.0-beta.1 → 2.1.0-beta.10
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/dist/chunks/add.mjs +12 -7
- package/dist/chunks/dev.mjs +23 -5
- package/dist/chunks/init.mjs +3 -7
- package/dist/core/index.mjs +69 -40
- package/dist/create/index.d.mts +2 -1
- package/dist/create/index.d.ts +2 -1
- package/dist/create/index.mjs +185 -121
- package/dist/rolldown/index.d.mts +7 -0
- package/dist/rolldown/index.d.ts +7 -0
- package/dist/rolldown/index.mjs +90 -0
- package/dist/runtime/dev.mjs +3 -0
- package/dist/runtime/internal/app.d.ts +1 -1
- package/dist/runtime/internal/app.mjs +11 -3
- package/dist/runtime/start.mjs +5 -0
- package/dist/types/index.d.mts +18 -15
- package/dist/types/index.d.ts +18 -15
- package/package.json +12 -15
- package/src/cli/commands/add.ts +12 -6
- package/src/cli/commands/dev.ts +26 -5
- package/src/cli/commands/init.ts +3 -7
- package/src/core/build/build.ts +13 -5
- package/src/core/build/dev.ts +44 -23
- package/src/core/build/error.ts +9 -14
- package/src/core/build/prod.ts +15 -10
- package/src/core/build/types.ts +8 -0
- package/src/core/config/defaults.ts +3 -0
- package/src/core/config/update.ts +1 -1
- package/src/create/add.ts +26 -12
- package/src/create/constants.ts +9 -10
- package/src/create/init.ts +28 -14
- package/src/create/templates.ts +154 -118
- package/src/create/utils.ts +10 -0
- package/src/rolldown/config.ts +83 -0
- package/src/rolldown/index.ts +2 -0
- package/src/{rollup → rolldown}/plugins/config.ts +2 -1
- package/src/{rollup → rolldown}/plugins/indexers.ts +3 -3
- package/src/runtime/dev.ts +3 -0
- package/src/runtime/internal/app.ts +13 -5
- package/src/runtime/start.ts +5 -0
- package/src/types/config.ts +12 -7
- package/src/types/hooks.ts +8 -5
- package/src/types/index.ts +1 -1
- package/src/types/rolldown.ts +5 -0
- package/src/types/virtual/indexers.d.ts +4 -1
- package/dist/rollup/index.d.mts +0 -6
- package/dist/rollup/index.d.ts +0 -6
- package/dist/rollup/index.mjs +0 -150
- package/src/rollup/config.ts +0 -87
- package/src/rollup/index.ts +0 -2
- package/src/rollup/plugins/esm-shim.ts +0 -69
- package/src/types/rollup.ts +0 -8
package/src/create/add.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import consola from "consola";
|
|
2
3
|
import prompts from "prompts";
|
|
3
4
|
import { cyan, red, reset } from "./colors";
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
import type { Chain, IndexerOptions, Network, Storage } from "./types";
|
|
19
20
|
import {
|
|
20
21
|
cancelOperation,
|
|
22
|
+
checkFileExists,
|
|
21
23
|
convertKebabToCamelCase,
|
|
22
24
|
getApibaraConfigLanguage,
|
|
23
25
|
getPackageManager,
|
|
@@ -35,6 +37,7 @@ type Options = {
|
|
|
35
37
|
argNetwork?: string;
|
|
36
38
|
argStorage?: string;
|
|
37
39
|
argDnaUrl?: string;
|
|
40
|
+
argRootDir?: string;
|
|
38
41
|
};
|
|
39
42
|
|
|
40
43
|
export async function addIndexer({
|
|
@@ -43,8 +46,10 @@ export async function addIndexer({
|
|
|
43
46
|
argNetwork,
|
|
44
47
|
argStorage,
|
|
45
48
|
argDnaUrl,
|
|
49
|
+
argRootDir,
|
|
46
50
|
}: Options) {
|
|
47
|
-
const
|
|
51
|
+
const cwd = path.join(process.cwd(), argRootDir ?? ".");
|
|
52
|
+
const configExists = hasApibaraConfig(cwd);
|
|
48
53
|
|
|
49
54
|
if (!configExists) {
|
|
50
55
|
consola.error("No apibara.config found in the current directory.");
|
|
@@ -72,7 +77,7 @@ export async function addIndexer({
|
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
const language = getApibaraConfigLanguage(
|
|
80
|
+
const language = getApibaraConfigLanguage(cwd);
|
|
76
81
|
|
|
77
82
|
validateIndexerId(argIndexerId, true);
|
|
78
83
|
validateChain(argChain, true);
|
|
@@ -88,8 +93,19 @@ export async function addIndexer({
|
|
|
88
93
|
message: reset("Indexer ID:"),
|
|
89
94
|
initial: argIndexerId ?? "my-indexer",
|
|
90
95
|
validate: (id) =>
|
|
91
|
-
validateIndexerId(id)
|
|
92
|
-
|
|
96
|
+
validateIndexerId(id)
|
|
97
|
+
? checkFileExists(
|
|
98
|
+
path.join(
|
|
99
|
+
cwd,
|
|
100
|
+
"indexers",
|
|
101
|
+
`${id}.indexer.${language === "typescript" ? "ts" : "js"}`,
|
|
102
|
+
),
|
|
103
|
+
).then(({ exists }) =>
|
|
104
|
+
exists
|
|
105
|
+
? `Indexer ${cyan(`${id}.indexer.${language === "typescript" ? "ts" : "js"}`)} already exists`
|
|
106
|
+
: true,
|
|
107
|
+
)
|
|
108
|
+
: "Invalid indexer ID, it cannot be empty and must be in kebab-case format",
|
|
93
109
|
},
|
|
94
110
|
{
|
|
95
111
|
type: argChain ? null : "select",
|
|
@@ -184,7 +200,7 @@ export async function addIndexer({
|
|
|
184
200
|
const pkgManager = getPackageManager();
|
|
185
201
|
|
|
186
202
|
const options: IndexerOptions = {
|
|
187
|
-
cwd:
|
|
203
|
+
cwd: cwd,
|
|
188
204
|
indexerFileId,
|
|
189
205
|
indexerId: convertKebabToCamelCase(indexerFileId),
|
|
190
206
|
chain: (argChain as Chain) ?? prompt_chain?.name!,
|
|
@@ -195,13 +211,13 @@ export async function addIndexer({
|
|
|
195
211
|
packageManager: pkgManager.name,
|
|
196
212
|
};
|
|
197
213
|
|
|
198
|
-
updateApibaraConfigFile(options);
|
|
214
|
+
await updateApibaraConfigFile(options);
|
|
199
215
|
|
|
200
216
|
consola.success(
|
|
201
217
|
`Updated ${cyan("apibara.config." + (language === "typescript" ? "ts" : "js"))}`,
|
|
202
218
|
);
|
|
203
219
|
|
|
204
|
-
updatePackageJson(options);
|
|
220
|
+
await updatePackageJson(options);
|
|
205
221
|
|
|
206
222
|
consola.success(`Updated ${cyan("package.json")}`);
|
|
207
223
|
|
|
@@ -215,11 +231,9 @@ export async function addIndexer({
|
|
|
215
231
|
|
|
216
232
|
console.log();
|
|
217
233
|
|
|
234
|
+
const baseCommand = `${options.packageManager} install`;
|
|
235
|
+
const tsCommand = `${baseCommand} && ${options.packageManager} run prepare`;
|
|
218
236
|
consola.info(
|
|
219
|
-
`Before running the indexer, run ${cyan(
|
|
220
|
-
language === "typescript"
|
|
221
|
-
? " & " + cyan(`${options.packageManager} run prepare`)
|
|
222
|
-
: ""
|
|
223
|
-
}`,
|
|
237
|
+
`Before running the indexer, run ${cyan(language === "typescript" ? tsCommand : baseCommand)}`,
|
|
224
238
|
);
|
|
225
239
|
}
|
package/src/create/constants.ts
CHANGED
|
@@ -66,17 +66,17 @@ export const storages: StorageDataType[] = [
|
|
|
66
66
|
|
|
67
67
|
export const packageVersions = {
|
|
68
68
|
// Required Dependencies
|
|
69
|
-
apibara: "
|
|
70
|
-
"@apibara/indexer": "
|
|
71
|
-
"@apibara/protocol": "
|
|
69
|
+
apibara: "next",
|
|
70
|
+
"@apibara/indexer": "next",
|
|
71
|
+
"@apibara/protocol": "next",
|
|
72
72
|
// Chain Dependencies
|
|
73
|
-
"@apibara/evm": "
|
|
74
|
-
"@apibara/beaconchain": "
|
|
75
|
-
"@apibara/starknet": "
|
|
73
|
+
"@apibara/evm": "next",
|
|
74
|
+
"@apibara/beaconchain": "next",
|
|
75
|
+
"@apibara/starknet": "next",
|
|
76
76
|
// Storage Dependencies
|
|
77
|
-
"@apibara/plugin-drizzle": "
|
|
78
|
-
"@apibara/plugin-mongo": "
|
|
79
|
-
"@apibara/plugin-sqlite": "
|
|
77
|
+
"@apibara/plugin-drizzle": "next",
|
|
78
|
+
"@apibara/plugin-mongo": "next",
|
|
79
|
+
"@apibara/plugin-sqlite": "next",
|
|
80
80
|
// Postgres Dependencies
|
|
81
81
|
"@electric-sql/pglite": "^0.2.17",
|
|
82
82
|
"drizzle-orm": "^0.37.0",
|
|
@@ -85,7 +85,6 @@ export const packageVersions = {
|
|
|
85
85
|
"drizzle-kit": "^0.29.0",
|
|
86
86
|
// Typescript Dependencies
|
|
87
87
|
typescript: "^5.6.2",
|
|
88
|
-
"@rollup/plugin-typescript": "^11.1.6",
|
|
89
88
|
"@types/node": "^20.5.2",
|
|
90
89
|
};
|
|
91
90
|
|
package/src/create/init.ts
CHANGED
|
@@ -5,6 +5,7 @@ import prompts from "prompts";
|
|
|
5
5
|
import { addIndexer } from "./add";
|
|
6
6
|
import { cyan, green } from "./colors";
|
|
7
7
|
import {
|
|
8
|
+
createGitIgnoreFile,
|
|
8
9
|
generateApibaraConfig,
|
|
9
10
|
generatePackageJson,
|
|
10
11
|
generateTsConfig,
|
|
@@ -13,6 +14,7 @@ import type { Language } from "./types";
|
|
|
13
14
|
import {
|
|
14
15
|
cancelOperation,
|
|
15
16
|
emptyDir,
|
|
17
|
+
formatFile,
|
|
16
18
|
getLanguageFromAlias,
|
|
17
19
|
getPackageManager,
|
|
18
20
|
isEmpty,
|
|
@@ -121,30 +123,42 @@ export async function initializeProject({
|
|
|
121
123
|
consola.info(`Initializing project in ${argTargetDir}\n\n`);
|
|
122
124
|
|
|
123
125
|
// Generate package.json
|
|
126
|
+
const packageJsonPath = path.join(root, "package.json");
|
|
124
127
|
const packageJson = generatePackageJson(isTs);
|
|
125
128
|
fs.writeFileSync(
|
|
126
|
-
|
|
129
|
+
packageJsonPath,
|
|
127
130
|
JSON.stringify(packageJson, null, 2) + "\n",
|
|
128
131
|
);
|
|
129
|
-
|
|
132
|
+
await formatFile(packageJsonPath);
|
|
133
|
+
consola.success("Created", cyan("package.json"));
|
|
130
134
|
|
|
131
135
|
// Generate tsconfig.json if TypeScript
|
|
132
136
|
if (isTs) {
|
|
137
|
+
const tsConfigPath = path.join(root, "tsconfig.json");
|
|
133
138
|
const tsConfig = generateTsConfig();
|
|
134
|
-
fs.writeFileSync(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
);
|
|
138
|
-
consola.success("Created ", cyan("tsconfig.json"));
|
|
139
|
+
fs.writeFileSync(tsConfigPath, JSON.stringify(tsConfig, null, 2) + "\n");
|
|
140
|
+
await formatFile(tsConfigPath);
|
|
141
|
+
consola.success("Created", cyan("tsconfig.json"));
|
|
139
142
|
}
|
|
140
143
|
|
|
144
|
+
const apibaraConfigPath = path.join(root, `apibara.config.${configExt}`);
|
|
141
145
|
// Generate apibara.config
|
|
142
146
|
const apibaraConfig = generateApibaraConfig(isTs);
|
|
143
|
-
fs.writeFileSync(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
fs.writeFileSync(apibaraConfigPath, apibaraConfig);
|
|
148
|
+
await formatFile(apibaraConfigPath);
|
|
149
|
+
consola.success("Created", cyan(`apibara.config.${configExt}`));
|
|
150
|
+
|
|
151
|
+
// Create "indexers" directory if not exists
|
|
152
|
+
const indexersDir = path.join(root, "indexers");
|
|
153
|
+
if (!fs.existsSync(indexersDir)) {
|
|
154
|
+
fs.mkdirSync(indexersDir, { recursive: true });
|
|
155
|
+
consola.success(`Created ${cyan("indexers")} directory`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
await createGitIgnoreFile(root);
|
|
159
|
+
|
|
160
|
+
console.log("\n");
|
|
161
|
+
|
|
148
162
|
consola.ready(green("Project initialized successfully"));
|
|
149
163
|
|
|
150
164
|
console.log();
|
|
@@ -152,12 +166,12 @@ export async function initializeProject({
|
|
|
152
166
|
if (!argNoCreateIndexer) {
|
|
153
167
|
consola.info("Let's create an indexer\n");
|
|
154
168
|
|
|
155
|
-
await addIndexer({});
|
|
169
|
+
await addIndexer({ argRootDir: argTargetDir });
|
|
156
170
|
} else {
|
|
157
171
|
const pkgManager = getPackageManager();
|
|
158
172
|
consola.info(
|
|
159
173
|
"Run ",
|
|
160
|
-
green(`${pkgManager.name}
|
|
174
|
+
green(`${pkgManager.name} install`),
|
|
161
175
|
" to install all dependencies",
|
|
162
176
|
);
|
|
163
177
|
}
|
package/src/create/templates.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { consola } from "consola";
|
|
4
|
+
import prompts from "prompts";
|
|
4
5
|
import { type ObjectLiteralExpression, Project, SyntaxKind } from "ts-morph";
|
|
5
6
|
import { cyan, green, magenta, yellow } from "./colors";
|
|
6
7
|
import { packageVersions } from "./constants";
|
|
7
8
|
import type { IndexerOptions } from "./types";
|
|
8
|
-
import { checkFileExists, getDnaUrl } from "./utils";
|
|
9
|
+
import { checkFileExists, formatFile, getDnaUrl } from "./utils";
|
|
9
10
|
|
|
10
11
|
export function generatePackageJson(isTypeScript: boolean) {
|
|
11
12
|
return {
|
|
@@ -14,7 +15,7 @@ export function generatePackageJson(isTypeScript: boolean) {
|
|
|
14
15
|
private: true,
|
|
15
16
|
type: "module",
|
|
16
17
|
scripts: {
|
|
17
|
-
prepare: "apibara prepare",
|
|
18
|
+
...(isTypeScript && { prepare: "apibara prepare" }),
|
|
18
19
|
dev: "apibara dev",
|
|
19
20
|
start: "apibara start",
|
|
20
21
|
build: "apibara build",
|
|
@@ -27,8 +28,6 @@ export function generatePackageJson(isTypeScript: boolean) {
|
|
|
27
28
|
},
|
|
28
29
|
devDependencies: {
|
|
29
30
|
...(isTypeScript && {
|
|
30
|
-
"@rollup/plugin-typescript":
|
|
31
|
-
packageVersions["@rollup/plugin-typescript"],
|
|
32
31
|
"@types/node": packageVersions["@types/node"],
|
|
33
32
|
typescript: packageVersions.typescript,
|
|
34
33
|
}),
|
|
@@ -58,17 +57,10 @@ export function generateTsConfig() {
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
export function generateApibaraConfig(isTypeScript: boolean) {
|
|
61
|
-
return
|
|
60
|
+
return `import { defineConfig } from "apibara/config";
|
|
62
61
|
|
|
63
62
|
export default defineConfig({
|
|
64
|
-
runtimeConfig: {}
|
|
65
|
-
isTypeScript
|
|
66
|
-
? `
|
|
67
|
-
rollupConfig: {
|
|
68
|
-
plugins: [typescript()${isTypeScript ? " as Plugin" : ""}],
|
|
69
|
-
},`
|
|
70
|
-
: ""
|
|
71
|
-
}
|
|
63
|
+
runtimeConfig: {},
|
|
72
64
|
});\n`;
|
|
73
65
|
}
|
|
74
66
|
|
|
@@ -78,24 +70,21 @@ export function generateIndexer({
|
|
|
78
70
|
chain,
|
|
79
71
|
language,
|
|
80
72
|
}: IndexerOptions) {
|
|
81
|
-
return
|
|
82
|
-
chain === "ethereum"
|
|
83
|
-
? `import { EvmStream } from "@apibara/evm";`
|
|
84
|
-
: chain === "beaconchain"
|
|
85
|
-
? `import { BeaconChainStream } from "@apibara/beaconchain";`
|
|
86
|
-
: chain === "starknet"
|
|
87
|
-
? `import { StarknetStream } from "@apibara/starknet";`
|
|
88
|
-
: ""
|
|
89
|
-
}
|
|
90
|
-
import { defineIndexer } from "@apibara/indexer";
|
|
91
|
-
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
92
|
-
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
73
|
+
return `import { defineIndexer } from "@apibara/indexer";
|
|
93
74
|
import { useLogger } from "@apibara/indexer/plugins";
|
|
75
|
+
${storage === "postgres" ? `import { drizzleStorage } from "@apibara/plugin-drizzle";` : ""}
|
|
76
|
+
${storage === "postgres" ? `import { drizzle } from "@apibara/plugin-drizzle";` : ""}
|
|
94
77
|
${
|
|
95
|
-
|
|
96
|
-
? `import {
|
|
97
|
-
: ""
|
|
78
|
+
chain === "ethereum"
|
|
79
|
+
? `import { EvmStream } from "@apibara/evm";`
|
|
80
|
+
: chain === "beaconchain"
|
|
81
|
+
? `import { BeaconChainStream } from "@apibara/beaconchain";`
|
|
82
|
+
: chain === "starknet"
|
|
83
|
+
? `import { StarknetStream } from "@apibara/starknet";`
|
|
84
|
+
: ""
|
|
98
85
|
}
|
|
86
|
+
${language === "typescript" ? `import type { ApibaraRuntimeConfig } from "apibara/types";` : ""}
|
|
87
|
+
${storage === "postgres" ? `import * as schema from "../lib/schema";` : ""}
|
|
99
88
|
|
|
100
89
|
|
|
101
90
|
export default function (runtimeConfig${language === "typescript" ? ": ApibaraRuntimeConfig" : ""}) {
|
|
@@ -103,7 +92,10 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
103
92
|
const { startingBlock, streamUrl${storage === "postgres" ? ", postgresConnectionString" : ""} } = runtimeConfig[indexerId];
|
|
104
93
|
${
|
|
105
94
|
storage === "postgres"
|
|
106
|
-
?
|
|
95
|
+
? `const db = drizzle({
|
|
96
|
+
schema,
|
|
97
|
+
connectionString: postgresConnectionString,
|
|
98
|
+
});`
|
|
107
99
|
: ""
|
|
108
100
|
}
|
|
109
101
|
|
|
@@ -122,7 +114,7 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
122
114
|
filter: {
|
|
123
115
|
header: "always",
|
|
124
116
|
},
|
|
125
|
-
plugins: [${storage === "postgres" ? "drizzleStorage({ db,
|
|
117
|
+
plugins: [${storage === "postgres" ? "drizzleStorage({ db, migrate: { migrationsFolder: './drizzle' } })" : ""}],
|
|
126
118
|
async transform({ endCursor, finality }) {
|
|
127
119
|
const logger = useLogger();
|
|
128
120
|
|
|
@@ -136,14 +128,12 @@ export default function (runtimeConfig${language === "typescript" ? ": ApibaraRu
|
|
|
136
128
|
${
|
|
137
129
|
storage === "postgres"
|
|
138
130
|
? `// Example snippet to insert data into db using drizzle with postgres
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
// });
|
|
146
|
-
// }`
|
|
131
|
+
// const { db: database } = useDrizzleStorage();
|
|
132
|
+
|
|
133
|
+
// await database.insert(schema.cursorTable).values({
|
|
134
|
+
// endCursor: Number(endCursor?.orderKey),
|
|
135
|
+
// uniqueKey: \`\${endCursor?.uniqueKey}\`,
|
|
136
|
+
// });`
|
|
147
137
|
: ""
|
|
148
138
|
}
|
|
149
139
|
},
|
|
@@ -169,17 +159,19 @@ export async function createIndexerFile(options: IndexerOptions) {
|
|
|
169
159
|
|
|
170
160
|
fs.mkdirSync(path.dirname(indexerFilePath), { recursive: true });
|
|
171
161
|
fs.writeFileSync(indexerFilePath, indexerContent);
|
|
162
|
+
|
|
163
|
+
await formatFile(indexerFilePath);
|
|
172
164
|
}
|
|
173
165
|
|
|
174
|
-
export function updatePackageJson({
|
|
166
|
+
export async function updatePackageJson({
|
|
175
167
|
cwd,
|
|
176
168
|
chain,
|
|
177
169
|
storage,
|
|
178
170
|
language,
|
|
179
171
|
}: IndexerOptions) {
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
);
|
|
172
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
173
|
+
|
|
174
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
183
175
|
|
|
184
176
|
if (chain === "ethereum") {
|
|
185
177
|
packageJson.dependencies["@apibara/evm"] = packageVersions["@apibara/evm"];
|
|
@@ -212,13 +204,12 @@ export function updatePackageJson({
|
|
|
212
204
|
}
|
|
213
205
|
}
|
|
214
206
|
|
|
215
|
-
fs.writeFileSync(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
);
|
|
207
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
208
|
+
|
|
209
|
+
await formatFile(packageJsonPath);
|
|
219
210
|
}
|
|
220
211
|
|
|
221
|
-
export function updateApibaraConfigFile({
|
|
212
|
+
export async function updateApibaraConfigFile({
|
|
222
213
|
indexerId,
|
|
223
214
|
cwd,
|
|
224
215
|
chain,
|
|
@@ -279,15 +270,11 @@ export function updateApibaraConfigFile({
|
|
|
279
270
|
// Save the changes
|
|
280
271
|
sourceFile.saveSync();
|
|
281
272
|
|
|
282
|
-
|
|
283
|
-
tabSize: 2,
|
|
284
|
-
insertSpaceAfterOpeningAndBeforeClosingEmptyBraces: true,
|
|
285
|
-
insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
|
|
286
|
-
});
|
|
273
|
+
await formatFile(pathToConfig);
|
|
287
274
|
}
|
|
288
275
|
|
|
289
276
|
export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
290
|
-
const { cwd, language, storage } = options;
|
|
277
|
+
const { cwd, language, storage, indexerId } = options;
|
|
291
278
|
|
|
292
279
|
if (storage !== "postgres") return;
|
|
293
280
|
|
|
@@ -315,16 +302,18 @@ export async function createDrizzleStorageFiles(options: IndexerOptions) {
|
|
|
315
302
|
const drizzleConfigContent = `${language === "typescript" ? 'import type { Config } from "drizzle-kit";' : ""}
|
|
316
303
|
|
|
317
304
|
export default {
|
|
318
|
-
schema: "./lib/schema
|
|
305
|
+
schema: "./lib/schema.${fileExtension}",
|
|
319
306
|
out: "./drizzle",
|
|
320
307
|
dialect: "postgresql",
|
|
321
308
|
dbCredentials: {
|
|
322
|
-
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "",
|
|
309
|
+
url: process.env["POSTGRES_CONNECTION_STRING"] ?? "memory://${indexerId}",
|
|
323
310
|
},
|
|
324
311
|
}${language === "typescript" ? " satisfies Config" : ""};`;
|
|
325
312
|
|
|
326
313
|
fs.writeFileSync(drizzleConfigPath, drizzleConfigContent);
|
|
327
314
|
|
|
315
|
+
await formatFile(drizzleConfigPath);
|
|
316
|
+
|
|
328
317
|
consola.success(`Created ${cyan(drizzleConfigFileName)}`);
|
|
329
318
|
}
|
|
330
319
|
|
|
@@ -348,14 +337,14 @@ export default {
|
|
|
348
337
|
});
|
|
349
338
|
|
|
350
339
|
if (!schemaExists || schemaOverwrite) {
|
|
351
|
-
const schemaContent = `// --- Add your pg table schemas here ----
|
|
340
|
+
const schemaContent = `// --- Add your pg table schemas here ----
|
|
352
341
|
|
|
353
342
|
// import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
354
343
|
|
|
355
|
-
// export const
|
|
344
|
+
// export const cursorTable = pgTable("cursor_table", {
|
|
356
345
|
// id: uuid("id").primaryKey().defaultRandom(),
|
|
357
|
-
//
|
|
358
|
-
//
|
|
346
|
+
// endCursor: bigint("end_cursor", { mode: "number" }),
|
|
347
|
+
// uniqueKey: text("unique_key"),
|
|
359
348
|
// });
|
|
360
349
|
|
|
361
350
|
export {};
|
|
@@ -365,62 +354,9 @@ export {};
|
|
|
365
354
|
fs.mkdirSync(path.dirname(schemaPath), { recursive: true });
|
|
366
355
|
fs.writeFileSync(schemaPath, schemaContent);
|
|
367
356
|
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
* DB File
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*/
|
|
378
|
-
const dbFileName = `db.${fileExtension}`;
|
|
379
|
-
|
|
380
|
-
const dbPath = path.join(cwd, "lib", dbFileName);
|
|
357
|
+
await formatFile(schemaPath);
|
|
381
358
|
|
|
382
|
-
|
|
383
|
-
dbPath,
|
|
384
|
-
{
|
|
385
|
-
askPrompt: true,
|
|
386
|
-
fileName: `lib/${dbFileName}`,
|
|
387
|
-
allowIgnore: true,
|
|
388
|
-
},
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
if (!dbExists || dbOverwrite) {
|
|
392
|
-
const dbContent = `import * as schema from "./schema";
|
|
393
|
-
import { drizzle as nodePgDrizzle } from "drizzle-orm/node-postgres";
|
|
394
|
-
import { drizzle as pgLiteDrizzle } from "drizzle-orm/pglite";
|
|
395
|
-
import pg from "pg";
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
export function getDrizzlePgDatabase(connectionString${language === "typescript" ? ": string" : ""}) {
|
|
399
|
-
// Create pglite instance
|
|
400
|
-
if (connectionString.includes("memory")) {
|
|
401
|
-
return {
|
|
402
|
-
db: pgLiteDrizzle({
|
|
403
|
-
schema,
|
|
404
|
-
connection: {
|
|
405
|
-
dataDir: connectionString,
|
|
406
|
-
},
|
|
407
|
-
}),
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Create node-postgres instance
|
|
412
|
-
const pool = new pg.Pool({
|
|
413
|
-
connectionString,
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
return { db: nodePgDrizzle(pool, { schema }) };
|
|
417
|
-
}`;
|
|
418
|
-
|
|
419
|
-
// create directory if it doesn't exist
|
|
420
|
-
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
421
|
-
fs.writeFileSync(dbPath, dbContent);
|
|
422
|
-
|
|
423
|
-
consola.success(`Created ${cyan(`lib/${dbFileName}`)}`);
|
|
359
|
+
consola.success(`Created ${cyan("lib/schema.ts")}`);
|
|
424
360
|
}
|
|
425
361
|
|
|
426
362
|
console.log("\n");
|
|
@@ -442,17 +378,17 @@ ${yellow(`
|
|
|
442
378
|
|
|
443
379
|
import { bigint, pgTable, text, uuid } from "drizzle-orm/pg-core";
|
|
444
380
|
|
|
445
|
-
export const
|
|
381
|
+
export const cursorTable = pgTable("cursor_table", {
|
|
446
382
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
447
|
-
|
|
448
|
-
|
|
383
|
+
endCursor: bigint("end_cursor", { mode: "number" }),
|
|
384
|
+
uniqueKey: text("unique_key"),
|
|
449
385
|
});`)}`);
|
|
450
386
|
|
|
451
387
|
console.log("\n");
|
|
452
388
|
}
|
|
453
389
|
|
|
454
390
|
consola.info(
|
|
455
|
-
`Run ${green(`${options.packageManager} run drizzle:generate`)} & ${green(`${options.packageManager} run drizzle:migrate`)} to generate and apply migrations.`,
|
|
391
|
+
`Run ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:generate`)} & ${green(`${options.packageManager}${options.packageManager === "npm" ? " run" : ""} drizzle:migrate`)} to generate and apply migrations.`,
|
|
456
392
|
);
|
|
457
393
|
}
|
|
458
394
|
|
|
@@ -463,3 +399,103 @@ export async function createStorageRelatedFiles(options: IndexerOptions) {
|
|
|
463
399
|
await createDrizzleStorageFiles(options);
|
|
464
400
|
}
|
|
465
401
|
}
|
|
402
|
+
|
|
403
|
+
const gitIgnoreItems: {
|
|
404
|
+
isRecommended: boolean;
|
|
405
|
+
description?: string;
|
|
406
|
+
value: string;
|
|
407
|
+
}[] = [
|
|
408
|
+
{
|
|
409
|
+
isRecommended: false,
|
|
410
|
+
value: "node_modules",
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
isRecommended: false,
|
|
414
|
+
value: "dist",
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
isRecommended: true,
|
|
418
|
+
description: "build and dev files of apibara",
|
|
419
|
+
value: ".apibara",
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
isRecommended: false,
|
|
423
|
+
value: ".env",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
isRecommended: false,
|
|
427
|
+
description: "for mac users",
|
|
428
|
+
value: ".DS_Store",
|
|
429
|
+
},
|
|
430
|
+
];
|
|
431
|
+
|
|
432
|
+
export async function createGitIgnoreFile(cwd: string) {
|
|
433
|
+
const gitIgnorePath = path.join(cwd, ".gitignore");
|
|
434
|
+
|
|
435
|
+
if (fs.existsSync(gitIgnorePath)) {
|
|
436
|
+
const result = await prompts([
|
|
437
|
+
{
|
|
438
|
+
type: "select",
|
|
439
|
+
name: "overwrite",
|
|
440
|
+
message: `${cyan(".gitignore")} already exists. Please choose how to proceed:`,
|
|
441
|
+
initial: 0,
|
|
442
|
+
choices: [
|
|
443
|
+
{
|
|
444
|
+
title: "Choose items to append in your .gitignore",
|
|
445
|
+
value: "append",
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
title: "Keep original",
|
|
449
|
+
value: "ignore",
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
title: "Overwrite",
|
|
453
|
+
value: "overwrite",
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
type: (overwrite: "append" | "ignore" | "overwrite") =>
|
|
459
|
+
overwrite === "append" ? "multiselect" : null,
|
|
460
|
+
name: "ignoreItems",
|
|
461
|
+
message: "Choose items to append in your .gitignore",
|
|
462
|
+
choices: gitIgnoreItems.map((item) => ({
|
|
463
|
+
title: `${yellow(item.value)}${
|
|
464
|
+
item.description ? ` - ${item.description}` : ""
|
|
465
|
+
}${item.isRecommended ? ` ${green("(recommended)")}` : ""}`,
|
|
466
|
+
value: item.value,
|
|
467
|
+
})),
|
|
468
|
+
},
|
|
469
|
+
]);
|
|
470
|
+
|
|
471
|
+
const { overwrite, ignoreItems } = result as {
|
|
472
|
+
overwrite: "append" | "ignore" | "overwrite";
|
|
473
|
+
ignoreItems: string[];
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
if (overwrite === "append" && ignoreItems.length > 0) {
|
|
477
|
+
const gitIgnoreContent = fs.readFileSync(gitIgnorePath, "utf8");
|
|
478
|
+
fs.writeFileSync(
|
|
479
|
+
gitIgnorePath,
|
|
480
|
+
`${gitIgnoreContent}\n${result.ignoreItems.join("\n")}`,
|
|
481
|
+
);
|
|
482
|
+
consola.success(`Updated ${cyan(".gitignore")}`);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (overwrite === "overwrite") {
|
|
487
|
+
fs.writeFileSync(
|
|
488
|
+
gitIgnorePath,
|
|
489
|
+
gitIgnoreItems.map((item) => item.value).join("\n"),
|
|
490
|
+
);
|
|
491
|
+
consola.success(`Updated ${cyan(".gitignore")}`);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
fs.writeFileSync(
|
|
497
|
+
gitIgnorePath,
|
|
498
|
+
gitIgnoreItems.map((item) => item.value).join("\n"),
|
|
499
|
+
);
|
|
500
|
+
consola.success(`Created ${cyan(".gitignore")}`);
|
|
501
|
+
}
|
package/src/create/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path, { basename } from "node:path";
|
|
3
|
+
import * as prettier from "prettier";
|
|
3
4
|
import prompts from "prompts";
|
|
4
5
|
import { blue, cyan, red, yellow } from "./colors";
|
|
5
6
|
import { dnaUrls, networks } from "./constants";
|
|
@@ -410,3 +411,12 @@ function pkgFromUserAgent(userAgent: string | undefined): PkgInfo | undefined {
|
|
|
410
411
|
version: pkgSpecArr[1],
|
|
411
412
|
};
|
|
412
413
|
}
|
|
414
|
+
|
|
415
|
+
export async function formatFile(path: string) {
|
|
416
|
+
const file = fs.readFileSync(path, "utf8");
|
|
417
|
+
const formatted = await prettier.format(file, {
|
|
418
|
+
filepath: path,
|
|
419
|
+
tabWidth: 2,
|
|
420
|
+
});
|
|
421
|
+
fs.writeFileSync(path, formatted);
|
|
422
|
+
}
|