Skip to content

Commit

Permalink
Transform class references in connect-migrate
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Stamm <[email protected]>
  • Loading branch information
timostamm committed Nov 26, 2024
1 parent dfe3b4f commit a169560
Show file tree
Hide file tree
Showing 6 changed files with 490 additions and 10 deletions.
17 changes: 11 additions & 6 deletions packages/connect-migrate/src/lib/migrate-source-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface MigrateSourceFilesResult {

export function migrateSourceFiles(
scanned: Scanned,
transform: j.Transform,
transform: j.Transform | j.Transform[],
print: PrintFn,
logger?: Logger,
updateSourceFileFn: typeof updateSourceFile = updateSourceFile,
Expand Down Expand Up @@ -68,19 +68,24 @@ interface UpdateSourceFileResult {
}

export function updateSourceFile(
transform: Transform,
transform: Transform | Transform[],
path: string,
logger?: Logger,
): UpdateSourceFileResult {
logger?.log(`transform ${path}`);
try {
const source = readFileSync(path, "utf8");
const result = updateSourceFileInMemory(transform, source, path);
if (!result.modified) {
let source = readFileSync(path, "utf8");
let modified = false;
for (const t of Array.isArray(transform) ? transform : [transform]) {
const result = updateSourceFileInMemory(t, source, path);
source = result.source;
modified = modified || result.modified;
}
if (!modified) {
logger?.log(`skipped`);
return { ok: true, modified: false };
}
writeFileSync(path, result.source, "utf-8");
writeFileSync(path, source, "utf-8");
logger?.log(`modified`);
return { ok: true, modified: true };
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { updateSourceFileInMemory } from "../lib/migrate-source-files";
import transform from "./v2.0.0-transform-class-refs";

describe("v2.0.0 transform class references", () => {
it("transforms new", () => {
const input = [`import {Foo} from "./x_pb.js";`, `new Foo();`].join("\n");
const output = [
`import { FooSchema } from "./x_pb.js";`,
`import { create } from "@bufbuild/protobuf";`,
`create(FooSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("transforms new with init object", () => {
const input = [`import {Foo} from "./x_pb.js";`, `new Foo({x:123});`].join(
"\n",
);
const output = [
`import { FooSchema } from "./x_pb.js";`,
`import { create } from "@bufbuild/protobuf";`,
`create(FooSchema, {x:123});`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toBe(output);
});
it("adds type import when transforming new", () => {
const input = [
`import {Foo} from "./x_pb.js";`,
`const foo: Foo = new Foo();`,
].join("\n");
const output = [
`import { FooSchema } from "./x_pb.js";`,
`import { create } from "@bufbuild/protobuf";`,
`import type { Foo } from "./x_pb.js";`,
`const foo: Foo = create(FooSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("adds create import to existing when transforming new", () => {
const input = [
`import {fake} from "@bufbuild/protobuf";`,
`import {Foo} from "./x_pb.js";`,
`new Foo();`,
].join("\n");
const output = [
`import { fake, create } from "@bufbuild/protobuf";`,
`import { FooSchema } from "./x_pb.js";`,
`create(FooSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("transforms isMessage()", () => {
const input = [
`import {isMessage} from "@bufbuild/protobuf";`,
`import {Foo} from "./x_pb.js";`,
`isMessage(1, Foo);`,
].join("\n");
const output = [
`import {isMessage} from "@bufbuild/protobuf";`,
`import { FooSchema } from "./x_pb.js";`,
`isMessage(1, FooSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("does not transform isMessage() without schema argument", () => {
const input = [
`import {isMessage} from "@bufbuild/protobuf";`,
`import {Foo} from "./x_pb.js";`,
`isMessage(1);`,
].join("\n");
const output = [
`import {isMessage} from "@bufbuild/protobuf";`,
`import {Foo} from "./x_pb.js";`,
`isMessage(1);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("adds type import when transforming isMessage()", () => {
const input = [
`import {isMessage} from "@bufbuild/protobuf";`,
`import {Foo} from "./x_pb.js";`,
`type X = Foo;`,
`isMessage(1, Foo);`,
].join("\n");
const output = [
`import {isMessage} from "@bufbuild/protobuf";`,
`import { FooSchema } from "./x_pb.js";`,
`import type { Foo } from "./x_pb.js";`,
`type X = Foo;`,
`isMessage(1, FooSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("transforms wkt", () => {
const input = [
`import {Timestamp} from "@bufbuild/protobuf";`,
`new Timestamp();`,
].join("\n");
const output = [
`import { TimestampSchema } from "@bufbuild/protobuf/wkt";`,
`import { create } from "@bufbuild/protobuf";`,
`create(TimestampSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("adds type import when transforming wkt", () => {
const input = [
`import {Timestamp} from "@bufbuild/protobuf";`,
`const ts: Timestamp = new Timestamp();`,
].join("\n");
const output = [
`import { TimestampSchema } from "@bufbuild/protobuf/wkt";`,
`import { create } from "@bufbuild/protobuf";`,
`import type { Timestamp } from "@bufbuild/protobuf/wkt";`,
`const ts: Timestamp = create(TimestampSchema);`,
].join("\n");
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toEqual(output);
});
it("does not transform new when identifier is not imported from _pb", () => {
const input = `import {Foo} from "./x.js"; new Foo()`;
const output = `import {Foo} from "./x.js"; new Foo()`;
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toBe(output);
});
it("does not transform isMessage when identifier is not imported from _pb", () => {
const input = `import {Foo} from "./x.js"; isMessage(1, Foo);`;
const output = `import {Foo} from "./x.js"; isMessage(1, Foo);`;
const result = updateSourceFileInMemory(transform, input, "foo.ts");
expect(result.source).toBe(output);
});
});
Loading

0 comments on commit a169560

Please sign in to comment.