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 support for include directive in compile and run commands #235

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,8 @@ When you make changes to `myfunction.sql`, include it in your current migration
by adding `--!include functions/myfunction.sql` to your `current.sql` (or any
`current/*.sql`). This statement doesn't need to be at the top of the file,
wherever it is will be replaced by the content of
`migrations/fixtures/functions/myfunction.sql` when the migration is committed.
`migrations/fixtures/functions/myfunction.sql` when the migration is committed
(or compiled using `commit` or `run` commands).

```sql
--!include functions/myfunction.sql
Expand Down
26 changes: 18 additions & 8 deletions src/commands/compile.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as fsp from "fs/promises";
import { CommandModule } from "yargs";

import { compilePlaceholders } from "../migration";
import { compileIncludes, compilePlaceholders } from "../migration";
import { parseSettings, Settings } from "../settings";
import { CommonArgv, getSettings, readStdin } from "./_common";

Expand All @@ -11,11 +11,18 @@ interface CompileArgv extends CommonArgv {

export async function compile(
settings: Settings,
content: string,
rawContents: string,
filename: string | null = null,
shadow = false,
): Promise<string> {
const parsedSettings = await parseSettings(settings, shadow);
return compilePlaceholders(parsedSettings, content, shadow);
const contents = await compileIncludes(
parsedSettings,
rawContents,
filename ? new Set([filename]) : new Set(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm... This could allow including the same file twice because the path names may not match up. We should make it so that we resolve all paths to absolute paths.

);

return compilePlaceholders(parsedSettings, contents, shadow);
}

export const compileCommand: CommandModule<
Expand All @@ -25,7 +32,7 @@ export const compileCommand: CommandModule<
command: "compile [file]",
aliases: [],
describe: `\
Compiles a SQL file, inserting all the placeholders and returning the result to STDOUT`,
Compiles a SQL file, resolving includes, inserting all the placeholders and returning the result to STDOUT`,
builder: {
shadow: {
type: "boolean",
Expand All @@ -35,12 +42,15 @@ Compiles a SQL file, inserting all the placeholders and returning the result to
},
handler: async (argv) => {
const settings = await getSettings({ configFile: argv.config });
const content =
const { content, filename } =
typeof argv.file === "string"
? await fsp.readFile(argv.file, "utf8")
: await readStdin();
? {
filename: argv.file,
content: await fsp.readFile(argv.file, "utf8"),
}
: { filename: null, content: await readStdin() };

const compiled = await compile(settings, content, argv.shadow);
const compiled = await compile(settings, content, filename, argv.shadow);

// eslint-disable-next-line no-console
console.log(compiled);
Expand Down
14 changes: 9 additions & 5 deletions src/commands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CommandModule } from "yargs";

import { DO_NOT_USE_DATABASE_URL } from "../actions";
import { runQueryWithErrorInstrumentation } from "../instrumentation";
import { compilePlaceholders } from "../migration";
import { compileIncludes, compilePlaceholders } from "../migration";
import { withClient } from "../pgReal";
import {
makeRootDatabaseConnectionString,
Expand All @@ -19,10 +19,9 @@ interface RunArgv extends CommonArgv {
rootDatabase?: boolean;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function run<T extends QueryResultRow = QueryResultRow>(
settings: Settings,
content: string,
rawContents: string,
filename: string,
{
shadow = false,
Expand All @@ -35,7 +34,12 @@ export async function run<T extends QueryResultRow = QueryResultRow>(
} = {},
): Promise<T[] | undefined> {
const parsedSettings = await parseSettings(settings, shadow);
const sql = compilePlaceholders(parsedSettings, content, shadow);
const contents = await compileIncludes(
parsedSettings,
rawContents,
new Set([filename]),
);
const sql = compilePlaceholders(parsedSettings, contents, shadow);
const baseConnectionString = rootDatabase
? parsedSettings.rootConnectionString
: shadow
Expand All @@ -62,7 +66,7 @@ export const runCommand: CommandModule<Record<string, never>, RunArgv> = {
command: "run [file]",
aliases: [],
describe: `\
Compiles a SQL file, inserting all the placeholders, and then runs it against the database. Useful for seeding. If called from an action will automatically run against the same database (via GM_DBURL envvar) unless --shadow or --rootDatabase are supplied.`,
Compiles a SQL file, resolving includes and inserting all the placeholders, and then runs it against the database. Useful for seeding. If called from an action will automatically run against the same database (via GM_DBURL envvar) unless --shadow or --rootDatabase are supplied.`,
builder: {
shadow: {
type: "boolean",
Expand Down