Skip to content

Commit 2ecc2d5

Browse files
authored
Dataset graphql resolver (#5558)
* feat(datasets): change catalog graphql to dataset * chore(graphql): run codegen
1 parent 759a436 commit 2ecc2d5

File tree

5 files changed

+129
-44
lines changed

5 files changed

+129
-44
lines changed

apps/frontend/app/api/v1/osograph/schema.graphql

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,21 @@ type Invitation @key(fields: "id") {
8181
}
8282

8383
"""
84-
Catalog entity - represents a data catalog accessible to the user
84+
Dataset entity - represents a dataset within an organization
8585
"""
86-
type Catalog @key(fields: "name") {
87-
name: String!
88-
schemas: [Schema!]!
89-
}
90-
91-
"""
92-
Schema entity - represents a schema within a catalog
93-
"""
94-
type Schema {
86+
type Dataset @key(fields: "id") {
87+
id: ID!
88+
orgId: ID!
89+
createdAt: DateTime!
90+
updatedAt: DateTime!
91+
deletedAt: DateTime
9592
name: String!
93+
displayName: String!
94+
description: String
95+
catalog: String!
96+
schema: String!
97+
createdBy: ID!
98+
isPublic: Boolean!
9699
tables: [Table!]!
97100
}
98101

@@ -134,11 +137,11 @@ type Query {
134137
osoApp_invitation(id: ID!): Invitation
135138

136139
"""
137-
Get list of catalogs for the current user
140+
Get list of datasets for a given organization
138141
"""
139-
osoApp_myCatalogs(orgName: String!): [Catalog!]!
142+
osoApp_orgDatasets(orgName: String!): [Dataset!]!
140143

141-
osoApp_tableColumns(
144+
osoApp_datasetTableMetadata(
142145
orgName: String!
143146
catalogName: String!
144147
schemaName: String!

apps/frontend/app/api/v1/osograph/schema/resolvers/catalog.ts renamed to apps/frontend/app/api/v1/osograph/schema/resolvers/dataset.ts

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import {
55
requireOrgMembership,
66
type GraphQLContext,
77
} from "@/app/api/v1/osograph/utils/auth";
8-
import { ServerErrors } from "@/app/api/v1/osograph/utils/errors";
8+
import {
9+
ResourceErrors,
10+
ServerErrors,
11+
} from "@/app/api/v1/osograph/utils/errors";
912
import { signTrinoJWT } from "@/lib/auth/auth";
1013
import { getTrinoClient } from "@/lib/clients/trino";
1114
import {
@@ -17,10 +20,12 @@ import {
1720
} from "@/lib/types/catalog";
1821
import { logger } from "@/lib/logger";
1922
import { assert } from "@opensource-observer/utils";
23+
import { createAdminClient } from "@/lib/supabase/admin";
24+
import { DatasetsRow } from "@/lib/types/schema-types";
2025

21-
export const catalogResolvers: GraphQLResolverModule<GraphQLContext> = {
26+
export const datasetResolver: GraphQLResolverModule<GraphQLContext> = {
2227
Query: {
23-
osoApp_myCatalogs: async (
28+
osoApp_orgDatasets: async (
2429
_: unknown,
2530
{ orgName }: { orgName: string },
2631
context: GraphQLContext,
@@ -104,11 +109,36 @@ export const catalogResolvers: GraphQLResolverModule<GraphQLContext> = {
104109
},
105110
),
106111
);
107-
const filteredResults = results.filter((result) => result !== null);
108-
return filteredResults;
112+
const filteredResults = results.filter(
113+
(result): result is Catalog => result !== null,
114+
);
115+
116+
const datasets = await getOrganizationDatasets(organization.id);
117+
118+
const tablesByCatalogAndSchema = filteredResults.reduce(
119+
(acc, catalog) => {
120+
for (const schema of catalog.schemas) {
121+
const key = `${catalog.name}.${schema.name}`;
122+
acc[key] = schema.tables;
123+
}
124+
return acc;
125+
},
126+
{} as Record<string, { name: string }[]>,
127+
);
128+
129+
const response = datasets.map((dataset) => {
130+
const key = `${dataset.catalog}.${dataset.schema}`;
131+
return {
132+
...dataset,
133+
tables: tablesByCatalogAndSchema[key] ?? [],
134+
};
135+
});
136+
console.log("orgDatasets response:", response);
137+
138+
return response;
109139
},
110140

111-
osoApp_tableColumns: async (
141+
osoApp_datasetTableMetadata: async (
112142
_: unknown,
113143
{
114144
orgName,
@@ -174,4 +204,41 @@ export const catalogResolvers: GraphQLResolverModule<GraphQLContext> = {
174204
return filteredResults;
175205
},
176206
},
207+
Dataset: {
208+
id: (parent: DatasetsRow) => parent.id,
209+
orgId: (parent: DatasetsRow) => parent.org_id,
210+
createdAt: (parent: DatasetsRow) => parent.created_at,
211+
updatedAt: (parent: DatasetsRow) => parent.updated_at,
212+
deletedAt: (parent: DatasetsRow) => parent.deleted_at,
213+
name: (parent: DatasetsRow) => parent.name,
214+
displayName: (parent: DatasetsRow) => parent.display_name,
215+
description: (parent: DatasetsRow) => parent.description,
216+
catalog: (parent: DatasetsRow) => parent.catalog,
217+
schema: (parent: DatasetsRow) => parent.schema,
218+
createdBy: (parent: DatasetsRow) => parent.created_by,
219+
isPublic: (parent: DatasetsRow) => parent.is_public,
220+
},
177221
};
222+
223+
async function getOrganizationDatasets(orgId: string): Promise<DatasetsRow[]> {
224+
const supabase = createAdminClient();
225+
226+
const { data, error } = await supabase
227+
.from("datasets_by_organization")
228+
.select("datasets(*)")
229+
.eq("org_id", orgId);
230+
231+
if (error) {
232+
throw ResourceErrors.notFound("Datasets", `org_id: ${orgId}`);
233+
}
234+
235+
const { data: ownedDatasets, error: ownedError } = await supabase
236+
.from("datasets")
237+
.select("*")
238+
.eq("org_id", orgId);
239+
if (ownedError) {
240+
throw ResourceErrors.notFound("Datasets", `org_id: ${orgId}`);
241+
}
242+
243+
return data.map((d) => d.datasets).concat(ownedDatasets);
244+
}

apps/frontend/app/api/v1/osograph/schema/resolvers/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { organizationResolvers } from "@/app/api/v1/osograph/schema/resolvers/or
55
import { userResolvers } from "@/app/api/v1/osograph/schema/resolvers/user";
66
import { memberResolvers } from "@/app/api/v1/osograph/schema/resolvers/member";
77
import { invitationResolvers } from "@/app/api/v1/osograph/schema/resolvers/invitation";
8-
import { catalogResolvers } from "@/app/api/v1/osograph/schema/resolvers/catalog";
8+
import { datasetResolver } from "@/app/api/v1/osograph/schema/resolvers/dataset";
99

1010
const dateTimeScalar = new GraphQLScalarType({
1111
name: "DateTime",
@@ -39,7 +39,7 @@ export const resolvers: GraphQLResolverMap<GraphQLContext> = {
3939
...userResolvers.Query,
4040
...organizationResolvers.Query,
4141
...invitationResolvers.Query,
42-
...catalogResolvers.Query,
42+
...datasetResolver.Query,
4343
},
4444
Mutation: {
4545
...userResolvers.Mutation,
@@ -50,4 +50,5 @@ export const resolvers: GraphQLResolverMap<GraphQLContext> = {
5050
Organization: organizationResolvers.Organization,
5151
OrganizationMember: memberResolvers.OrganizationMember,
5252
Invitation: invitationResolvers.Invitation,
53+
Dataset: datasetResolver.Dataset,
5354
};

apps/frontend/lib/graphql/generated/graphql.ts

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -992,13 +992,6 @@ export type CapturedLogsMetadata = {
992992
stdoutLocation?: Maybe<Scalars["String"]["output"]>;
993993
};
994994

995-
/** Catalog entity - represents a data catalog accessible to the user */
996-
export type Catalog = {
997-
__typename?: "Catalog";
998-
name: Scalars["String"]["output"];
999-
schemas: Array<Schema>;
1000-
};
1001-
1002995
/**
1003996
* What change an asset has undergone between two deployments. Used
1004997
* in distinguishing asset definition changes in branch deployment and
@@ -1363,6 +1356,24 @@ export type DagsterTypeOrError =
13631356
| PythonError
13641357
| RegularDagsterType;
13651358

1359+
/** Dataset entity - represents a dataset within an organization */
1360+
export type Dataset = {
1361+
__typename?: "Dataset";
1362+
catalog: Scalars["String"]["output"];
1363+
createdAt: Scalars["DateTime"]["output"];
1364+
createdBy: Scalars["ID"]["output"];
1365+
deletedAt?: Maybe<Scalars["DateTime"]["output"]>;
1366+
description?: Maybe<Scalars["String"]["output"]>;
1367+
displayName: Scalars["String"]["output"];
1368+
id: Scalars["ID"]["output"];
1369+
isPublic: Scalars["Boolean"]["output"];
1370+
name: Scalars["String"]["output"];
1371+
orgId: Scalars["ID"]["output"];
1372+
schema: Scalars["String"]["output"];
1373+
tables: Array<Table>;
1374+
updatedAt: Scalars["DateTime"]["output"];
1375+
};
1376+
13661377
export type DefaultPartitionStatuses = {
13671378
__typename?: "DefaultPartitionStatuses";
13681379
failedPartitions: Array<Scalars["String"]["output"]>;
@@ -5256,17 +5267,17 @@ export type Query = {
52565267
locationStatusesOrError: WorkspaceLocationStatusEntriesOrError;
52575268
/** Retrieve event logs after applying a run id filter, cursor, and limit. */
52585269
logsForRun: EventConnectionOrError;
5270+
osoApp_datasetTableMetadata: Array<Column>;
52595271
/** Get a specific invitation by ID */
52605272
osoApp_invitation?: Maybe<Invitation>;
52615273
/** Get the current authenticated user's profile */
52625274
osoApp_me: User;
5263-
/** Get list of catalogs for the current user */
5264-
osoApp_myCatalogs: Array<Catalog>;
52655275
/** Get invitations sent to the current user's email */
52665276
osoApp_myInvitations: Array<Invitation>;
5277+
/** Get list of datasets for a given organization */
5278+
osoApp_orgDatasets: Array<Dataset>;
52675279
/** Get a specific organization by name */
52685280
osoApp_organization?: Maybe<Organization>;
5269-
osoApp_tableColumns: Array<Column>;
52705281
oso_artifactsByCollectionV1?: Maybe<Array<Oso_ArtifactsByCollectionV1>>;
52715282
oso_artifactsByProjectV1?: Maybe<Array<Oso_ArtifactsByProjectV1>>;
52725283
oso_artifactsByUserV1?: Maybe<Array<Oso_ArtifactsByUserV1>>;
@@ -5541,6 +5552,14 @@ export type QueryLogsForRunArgs = {
55415552
runId: Scalars["ID"]["input"];
55425553
};
55435554

5555+
/** The root for all queries to retrieve data from the Dagster instance. */
5556+
export type QueryOsoApp_DatasetTableMetadataArgs = {
5557+
catalogName: Scalars["String"]["input"];
5558+
orgName: Scalars["String"]["input"];
5559+
schemaName: Scalars["String"]["input"];
5560+
tableName: Scalars["String"]["input"];
5561+
};
5562+
55445563
/** The root for all queries to retrieve data from the Dagster instance. */
55455564
export type QueryOsoApp_InvitationArgs = {
55465565
id: Scalars["ID"]["input"];
@@ -5552,15 +5571,13 @@ export type QueryOsoApp_MyInvitationsArgs = {
55525571
};
55535572

55545573
/** The root for all queries to retrieve data from the Dagster instance. */
5555-
export type QueryOsoApp_OrganizationArgs = {
5574+
export type QueryOsoApp_OrgDatasetsArgs = {
55565575
orgName: Scalars["String"]["input"];
55575576
};
55585577

55595578
/** The root for all queries to retrieve data from the Dagster instance. */
5560-
export type QueryOsoApp_TableColumnsArgs = {
5561-
catalogName: Scalars["String"]["input"];
5562-
schemaName: Scalars["String"]["input"];
5563-
tableName: Scalars["String"]["input"];
5579+
export type QueryOsoApp_OrganizationArgs = {
5580+
orgName: Scalars["String"]["input"];
55645581
};
55655582

55665583
/** The root for all queries to retrieve data from the Dagster instance. */
@@ -6965,13 +6982,6 @@ export type SchedulesOrError =
69656982
| RepositoryNotFoundError
69666983
| Schedules;
69676984

6968-
/** Schema entity - represents a schema within a catalog */
6969-
export type Schema = {
6970-
__typename?: "Schema";
6971-
name: Scalars["String"]["output"];
6972-
tables: Array<Table>;
6973-
};
6974-
69756985
export type SelectorTypeConfigError = PipelineConfigValidationError & {
69766986
__typename?: "SelectorTypeConfigError";
69776987
incomingFields: Array<Scalars["String"]["output"]>;
@@ -7680,7 +7690,7 @@ export type WrappingDagsterType = {
76807690
};
76817691

76827692
export type _Entity =
7683-
| Catalog
7693+
| Dataset
76847694
| Invitation
76857695
| Organization
76867696
| OrganizationMember

apps/frontend/supabase/seed.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ VALUES
5050
((SELECT id FROM organizations WHERE org_name = 'oso' LIMIT 1), (SELECT id FROM auth.users WHERE email = '[email protected]' LIMIT 1), 'template-value-chain', '{"cells":[{"id":"1","type":"python","content":"print(\"Hello from value-chain notebook!\")"}]}');
5151

5252
INSERT INTO resource_permissions (permission_level, notebook_id) SELECT 'read', id FROM notebooks;
53+
54+
INSERT INTO datasets (org_id, created_by, name, display_name, description, catalog, "schema")
55+
VALUES
56+
((SELECT id FROM organizations WHERE org_name = 'oso' LIMIT 1), (SELECT id FROM auth.users WHERE email = '[email protected]' LIMIT 1), 'oso-dataset', 'oso-dataset', 'OSO dataset', 'iceberg', 'oso');

0 commit comments

Comments
 (0)