Skip to content

Commit

Permalink
Merge pull request #1429 from ponder-sh/kjs/api-client
Browse files Browse the repository at this point in the history
inject clients into api file
  • Loading branch information
kyscott18 authored Jan 13, 2025
2 parents 7c15a61 + 260f7fa commit 1913fac
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 134 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/_test/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ export async function setupDatabaseServices(

const database = await createDatabase({
common: context.common,
namespace: "public",
preBuild: {
databaseConfig: context.databaseConfig,
namespace: "public",
},
schemaBuild: {
schema: config.schema,
Expand Down
18 changes: 14 additions & 4 deletions packages/core/src/bin/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { createLogger } from "@/internal/logger.js";
import { MetricsService } from "@/internal/metrics.js";
import { buildOptions } from "@/internal/options.js";
import { buildPayload, createTelemetry } from "@/internal/telemetry.js";
import type { IndexingBuild } from "@/internal/types.js";
import { createUi } from "@/ui/index.js";
import { type Result, mergeResults } from "@/utils/result.js";
import { createQueue } from "@ponder/common";
Expand Down Expand Up @@ -123,7 +124,7 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
return;
}

const schemaResult = await build.executeSchema();
const schemaResult = await build.executeSchema({ namespace });
if (schemaResult.status === "error") {
buildQueue.add({
status: "error",
Expand Down Expand Up @@ -173,12 +174,19 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
});
return;
}
indexingBuild = indexingBuildResult.result;

database = await createDatabase({ common, preBuild, schemaBuild });
database = await createDatabase({
common,
namespace,
preBuild,
schemaBuild,
});
await database.migrate(indexingBuildResult.result);
listenConnection = await database.getListenConnection();

const apiResult = await build.executeApi({
indexingBuild,
database,
listenConnection,
});
Expand Down Expand Up @@ -245,6 +253,7 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
metrics.resetApiMetrics();

const apiResult = await build.executeApi({
indexingBuild: indexingBuild!,
database: database!,
listenConnection: listenConnection!,
});
Expand Down Expand Up @@ -280,11 +289,12 @@ export async function dev({ cliOptions }: { cliOptions: CliOptions }) {
},
});

let indexingBuild: IndexingBuild | undefined;
let database: Database | undefined;
let listenConnection: ListenConnection | undefined;

build.initNamespace({ isSchemaRequired: false });
build.initNamespace({ isSchemaRequired: false });
const namespace =
cliOptions.schema ?? process.env.DATABASE_SCHEMA ?? "public";

build.startDev({
onReload: (kind) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/bin/commands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ export async function list({ cliOptions }: { cliOptions: CliOptions }) {

const shutdown = setupShutdown({ common, cleanup });

build.initNamespace({ isSchemaRequired: false });

const configResult = await build.executeConfig();
if (configResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
Expand All @@ -61,6 +59,8 @@ export async function list({ cliOptions }: { cliOptions: CliOptions }) {

const database = await createDatabase({
common,
// Note: `namespace` is not used in this command
namespace: "public",
preBuild: buildResult.result,
schemaBuild: emptySchemaBuild,
});
Expand Down
36 changes: 32 additions & 4 deletions packages/core/src/bin/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export async function serve({ cliOptions }: { cliOptions: CliOptions }) {
};

const shutdown = setupShutdown({ common, cleanup });
const namespaceResult = build.initNamespace({ isSchemaRequired: true });
const namespaceResult = build.namespaceCompile();

if (namespaceResult.status === "error") {
await shutdown({ reason: "Failed to initialize namespace", code: 1 });
Expand All @@ -63,7 +63,9 @@ export async function serve({ cliOptions }: { cliOptions: CliOptions }) {
return cleanup;
}

const schemaResult = await build.executeSchema();
const schemaResult = await build.executeSchema({
namespace: namespaceResult.result,
});
if (schemaResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
return cleanup;
Expand All @@ -89,11 +91,37 @@ export async function serve({ cliOptions }: { cliOptions: CliOptions }) {
return cleanup;
}

const database = await createDatabase({ common, preBuild, schemaBuild });
const indexingResult = await build.executeIndexingFunctions();
if (indexingResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
return cleanup;
}

const indexingBuildResult = await build.compileIndexing({
configResult: configResult.result,
schemaResult: schemaResult.result,
indexingResult: indexingResult.result,
});

if (indexingBuildResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
return cleanup;
}

const database = await createDatabase({
common,
namespace: namespaceResult.result,
preBuild,
schemaBuild,
});
// Note: this assumes that the _ponder_status table exists
const listenConnection = await database.getListenConnection();

const apiResult = await build.executeApi({ database, listenConnection });
const apiResult = await build.executeApi({
indexingBuild: indexingBuildResult.result,
database,
listenConnection,
});
if (apiResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
return cleanup;
Expand Down
19 changes: 15 additions & 4 deletions packages/core/src/bin/commands/start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export async function start({ cliOptions }: { cliOptions: CliOptions }) {

const shutdown = setupShutdown({ common, cleanup });

const namespaceResult = build.initNamespace({ isSchemaRequired: true });
const namespaceResult = build.namespaceCompile();
if (namespaceResult.status === "error") {
await shutdown({ reason: "Failed to initialize namespace", code: 1 });
return cleanup;
Expand All @@ -79,7 +79,9 @@ export async function start({ cliOptions }: { cliOptions: CliOptions }) {
return cleanup;
}

const schemaResult = await build.executeSchema();
const schemaResult = await build.executeSchema({
namespace: namespaceResult.result,
});
if (schemaResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
return cleanup;
Expand Down Expand Up @@ -114,11 +116,20 @@ export async function start({ cliOptions }: { cliOptions: CliOptions }) {
return cleanup;
}

database = await createDatabase({ common, preBuild, schemaBuild });
database = await createDatabase({
common,
namespace: namespaceResult.result,
preBuild,
schemaBuild,
});
await database.migrate(indexingBuildResult.result);
const listenConnection = await database.getListenConnection();

const apiResult = await build.executeApi({ database, listenConnection });
const apiResult = await build.executeApi({
indexingBuild: indexingBuildResult.result,
database,
listenConnection,
});
if (apiResult.status === "error") {
await shutdown({ reason: "Failed intial build", code: 1 });
return cleanup;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/bin/utils/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ test("run() setup", async (context) => {

const database = await createDatabase({
common: context.common,
namespace: "public",
preBuild: {
databaseConfig: context.databaseConfig,
namespace: "public",
},
schemaBuild: {
schema,
Expand Down Expand Up @@ -129,9 +129,9 @@ test("run() setup error", async (context) => {

const database = await createDatabase({
common: context.common,
namespace: "public",
preBuild: {
databaseConfig: context.databaseConfig,
namespace: "public",
},
schemaBuild: {
schema,
Expand Down
78 changes: 39 additions & 39 deletions packages/core/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import { BuildError } from "@/internal/errors.js";
import type {
ApiBuild,
IndexingBuild,
NamespaceBuild,
PreBuild,
RawIndexingFunctions,
Schema,
SchemaBuild,
} from "@/internal/types.js";
import type { Drizzle } from "@/types/db.js";
import { getNextAvailablePort } from "@/utils/port.js";
import type { Result } from "@/utils/result.js";
import { serialize } from "@/utils/serialize.js";
Expand All @@ -33,8 +33,9 @@ import { safeBuildSchema } from "./schema.js";
import { parseViteNodeError } from "./stacktrace.js";

declare global {
var PONDER_DATABASE_SCHEMA: string | undefined;
var PONDER_READONLY_DB: Drizzle<Schema>;
var PONDER_NAMESPACE_BUILD: NamespaceBuild;
var PONDER_INDEXING_BUILD: IndexingBuild;
var PONDER_DATABASE: Database;
var PONDER_LISTEN_CONNECTION: ListenConnection;
}

Expand All @@ -49,14 +50,17 @@ type IndexingResult = Result<{
type ApiResult = Result<{ app: Hono }>;

export type Build = {
initNamespace: (params: { isSchemaRequired: boolean }) => Result<never>;
executeConfig: () => Promise<ConfigResult>;
executeSchema: () => Promise<SchemaResult>;
executeSchema: (params: {
namespace: NamespaceBuild;
}) => Promise<SchemaResult>;
executeIndexingFunctions: () => Promise<IndexingResult>;
executeApi: (params: {
indexingBuild: IndexingBuild;
database: Database;
listenConnection: ListenConnection;
}) => Promise<ApiResult>;
namespaceCompile: () => Result<NamespaceBuild>;
preCompile: (params: { config: Config }) => Result<PreBuild>;
compileSchema: (params: { schema: Schema }) => Result<SchemaBuild>;
compileIndexing: (params: {
Expand All @@ -80,8 +84,6 @@ export const createBuild = async ({
common: Common;
cliOptions: CliOptions;
}): Promise<Build> => {
let namespace: string | undefined;

const escapeRegex = /[.*+?^${}()|[\]\\]/g;

const escapedIndexingDir = common.options.indexingDir
Expand Down Expand Up @@ -159,34 +161,6 @@ export const createBuild = async ({
};

const build = {
initNamespace: ({ isSchemaRequired }) => {
if (isSchemaRequired) {
if (
cliOptions.schema === undefined &&
process.env.DATABASE_SCHEMA === undefined
) {
const error = new BuildError(
"Database schema required. Specify with 'DATABASE_SCHEMA' env var or '--schema' CLI flag. Read more: https://ponder.sh/docs/getting-started/database#database-schema",
);
error.stack = undefined;
common.logger.error({
service: "build",
msg: "Failed build",
error,
});
return { status: "error", error } as const;
}

namespace = cliOptions.schema ?? process.env.DATABASE_SCHEMA;
} else {
namespace =
cliOptions.schema ?? process.env.DATABASE_SCHEMA ?? "public";
}

global.PONDER_DATABASE_SCHEMA = namespace;

return { status: "success" } as const;
},
async executeConfig(): Promise<ConfigResult> {
const executeResult = await executeFile({
file: common.options.configFile,
Expand Down Expand Up @@ -214,7 +188,8 @@ export const createBuild = async ({
result: { config, contentHash },
} as const;
},
async executeSchema(): Promise<SchemaResult> {
async executeSchema({ namespace }): Promise<SchemaResult> {
global.PONDER_NAMESPACE_BUILD = namespace;
const executeResult = await executeFile({
file: common.options.schemaFile,
});
Expand Down Expand Up @@ -296,8 +271,13 @@ export const createBuild = async ({
},
};
},
async executeApi({ database, listenConnection }): Promise<ApiResult> {
global.PONDER_READONLY_DB = database.qb.drizzleReadonly;
async executeApi({
indexingBuild,
database,
listenConnection,
}): Promise<ApiResult> {
global.PONDER_INDEXING_BUILD = indexingBuild;
global.PONDER_DATABASE = database;
global.PONDER_LISTEN_CONNECTION = listenConnection;

if (!fs.existsSync(common.options.apiFile)) {
Expand Down Expand Up @@ -352,6 +332,27 @@ export const createBuild = async ({
result: { app },
};
},
namespaceCompile() {
if (
cliOptions.schema === undefined &&
process.env.DATABASE_SCHEMA === undefined
) {
const error = new BuildError(
"Database schema required. Specify with 'DATABASE_SCHEMA' env var or '--schema' CLI flag. Read more: https://ponder.sh/docs/getting-started/database#database-schema",
);
error.stack = undefined;
common.logger.error({
service: "build",
msg: "Failed build",
error,
});
return { status: "error", error } as const;
}
return {
status: "success",
result: cliOptions.schema ?? process.env.DATABASE_SCHEMA!,
} as const;
},
preCompile({ config }): Result<PreBuild> {
const preBuild = safeBuildPre({
config,
Expand All @@ -375,7 +376,6 @@ export const createBuild = async ({
status: "success",
result: {
databaseConfig: preBuild.databaseConfig,
namespace: namespace!,
},
} as const;
},
Expand Down
14 changes: 13 additions & 1 deletion packages/core/src/build/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ export * from "${schemaPath}";
export default schema;
`;

const apiModule = () => `export const db = global.PONDER_READONLY_DB;
const apiModule = () => `import { createPublicClient } from "viem";
const clients = {};
for (const network of global.PONDER_INDEXING_BUILD.networks) {
clients[network.chainId] = createPublicClient({
chain: network.chain,
transport: () => network.transport
})
}
export const db = global.PONDER_DATABASE.qb.drizzleReadonly;
export { clients };
`;

export const vitePluginPonder = (options: Common["options"]): Plugin => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const client = ({ db }: { db: ReadonlyDrizzle<Schema> }) => {

let queryPromise: Promise<any>;

const channel = `${global.PONDER_DATABASE_SCHEMA}_status_channel`;
const channel = `${global.PONDER_NAMESPACE_BUILD}_status_channel`;

if (listenConnection.dialect === "pglite") {
queryPromise = listenConnection.connection.query(`LISTEN ${channel}`);
Expand Down
Loading

0 comments on commit 1913fac

Please sign in to comment.