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

Wrap types in default module in $default namespace and re-export them at top level #888

Merged
merged 2 commits into from Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions integration-tests/lts/dbschema/default.esdl
Expand Up @@ -197,6 +197,12 @@ module default {
type PgVectorTest {
test_embedding: embedding;
}

module nested {
type Test {
property prop: str;
}
}
};

module `💯💯💯` {
Expand All @@ -212,4 +218,6 @@ module extra {

module User {
scalar type Status extending enum<"Active", "Disabled">;

type User extending default::User;
}
9 changes: 9 additions & 0 deletions integration-tests/lts/dbschema/migrations/00024.edgeql
@@ -0,0 +1,9 @@
CREATE MIGRATION m13x34vijy2dlwl3x5jewnjcxb6tysyo7pr2zbbljadjdi2y5w3cja
ONTO m1tdrrz5jv7b4z7wo532wow2bdkq2oij5lkatt4vkqxfneise7j32q
{
CREATE MODULE default::nested IF NOT EXISTS;
CREATE TYPE User::User EXTENDING default::User;
CREATE TYPE default::nested::Test {
CREATE PROPERTY prop: std::str;
};
};
28 changes: 27 additions & 1 deletion integration-tests/lts/interfaces.test.ts
@@ -1,6 +1,15 @@
import * as tc from "conditional-type-checks";

import type { Movie, W, X, Y, Z } from "./dbschema/interfaces";
import type {
Movie,
W,
X,
Y,
Z,
User,
nested,
$default,
} from "./dbschema/interfaces";

export type Genre =
| "Horror"
Expand Down Expand Up @@ -34,10 +43,27 @@ export interface test_Profile extends BaseObject {
interface test_Z extends BaseObject {
xy?: W | X | Y | null;
}
interface test_User extends BaseObject {
username: string;
favourite_movies: Movie[];
}

describe("interfaces", () => {
test("check generated interfaces", () => {
tc.assert<tc.IsExact<Movie, test_Movie>>(true);
tc.assert<tc.IsExact<Z, test_Z>>(true);

// default module export
tc.assert<tc.IsExact<$default.Movie, Movie>>(true);

// test overlapping namespaces
// default::User type
tc.assert<tc.IsExact<User, test_User>>(true);
// user module
tc.assert<tc.IsExact<User.Status, "Active" | "Disabled">>(true);
tc.assert<tc.IsExact<User.User, User>>(true);

// module nested in default module
tc.assert<tc.IsExact<nested.Test["prop"], string | null | undefined>>(true);
});
});
54 changes: 32 additions & 22 deletions packages/generate/src/edgeql-js/generateInterfaces.ts
@@ -1,4 +1,4 @@
import { CodeBuffer, js, t } from "../builders";
import { CodeBuffer, t } from "../builders";
import type { GeneratorParams } from "../genutil";
import { $ } from "../genutil";
import { makePlainIdent, quote, splitName, toTSScalarType } from "../genutil";
Expand Down Expand Up @@ -32,8 +32,7 @@ export const generateInterfaces = (params: GenerateInterfacesParams) => {
const modName = modParts[modParts.length - 1];
const parentModName = modParts.slice(0, -1).join("::");
const parent = parentModName ? getModule(parentModName) : null;
const internalName =
modName === "default" && !parentModName ? "" : makePlainIdent(modName);
const internalName = makePlainIdent(modName);

module = {
name: modName,
Expand Down Expand Up @@ -73,9 +72,8 @@ export const generateInterfaces = (params: GenerateInterfacesParams) => {
(typeName: string, withModule: boolean = false): string => {
const { tMod, tName, module } = getPlainTypeModule(typeName);
return (
((mod !== tMod || withModule) && tMod !== "default"
? `${module.fullInternalName}.`
: "") + `${makePlainIdent(tName)}`
(mod !== tMod || withModule ? `${module.fullInternalName}.` : "") +
`${makePlainIdent(tName)}`
);
};

Expand All @@ -100,7 +98,7 @@ export const generateInterfaces = (params: GenerateInterfacesParams) => {
const isUnionType = Boolean(type.union_of?.length);
const isIntersectionType = Boolean(type.intersection_of?.length);

if (isIntersectionType) {
if (isIntersectionType || isUnionType) {
continue;
}

Expand Down Expand Up @@ -140,12 +138,10 @@ export const generateInterfaces = (params: GenerateInterfacesParams) => {
const { module: plainTypeModule } = getPlainTypeModule(type.name);
const pointers = type.pointers.filter((ptr) => ptr.name !== "__type__");

if (!isUnionType) {
plainTypeModule.types.set(name, getTypeName(type.name, true));
}
plainTypeModule.types.set(name, getTypeName(type.name, true));

plainTypeModule.buf.writeln([
t`${isUnionType ? "" : "export "}interface ${getTypeName(type.name)}${
t`export interface ${getTypeName(type.name)}${
type.bases.length
? ` extends ${type.bases
.map(({ id }) => {
Expand Down Expand Up @@ -178,12 +174,8 @@ export const generateInterfaces = (params: GenerateInterfacesParams) => {
const plainTypesExportBuf = new CodeBuffer();

const writeModuleExports = (module: ModuleData) => {
const wrapInNamespace = !(module.isRoot && module.name === "default");
if (wrapInNamespace) {
plainTypesCode.writeln([t`export namespace ${module.internalName} {`]);
plainTypesCode.writeln([js`const ${module.internalName} = {`]);
plainTypesCode.increaseIndent();
scotttrinh marked this conversation as resolved.
Show resolved Hide resolved
}
plainTypesCode.writeln([t`export namespace ${module.internalName} {`]);
plainTypesCode.increaseIndent();

plainTypesCode.writeBuf(module.buf);

Expand All @@ -200,11 +192,29 @@ export const generateInterfaces = (params: GenerateInterfacesParams) => {
plainTypesExportBuf.decreaseIndent();
plainTypesExportBuf.writeln([t`};`]);

if (wrapInNamespace) {
plainTypesCode.decreaseIndent();
plainTypesCode.writeln([t`}`]);
plainTypesCode.writeln([js`}`]);
plainTypesCode.addExport(module.internalName, { modes: ["js"] });
plainTypesCode.decreaseIndent();
plainTypesCode.writeln([t`}`]);
plainTypesCode.addExport(module.internalName, { modes: ["js"] });

if (module.isRoot && module.name === "default") {
const typeRefs = [
...module.types.values(),
...[...module.nestedModules.values()].map(
(nestedMod) => nestedMod.fullInternalName
),
];
for (const typeRef of typeRefs) {
plainTypesCode.writeln([
`import ${typeRef.slice(
module.internalName.length + 1
)} = ${typeRef};`,
]);
}
plainTypesCode.writeln([
`export {${typeRefs
.map((typeRef) => typeRef.slice(module.internalName.length + 1))
.join(", ")}};`,
]);
}
};

Expand Down