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

Support default datasources #691

Merged
merged 7 commits into from
Aug 11, 2022
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions packages/toolpad-app/src/appDom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import invariant from 'invariant';
import { ConnectionStatus, AppTheme } from './types';
import { omit, update, updateOrCreate } from './utils/immutability';
import { camelCase, generateUniqueString, removeDiacritics } from './utils/strings';
import { ExactEntriesOf } from './utils/types';
import { ExactEntriesOf, Maybe } from './utils/types';
import { filterValues } from './utils/collections';

export const RESERVED_NODE_PROPERTIES = [
Expand Down Expand Up @@ -107,7 +107,7 @@ export interface QueryNode<Q = any, P = any> extends AppDomNodeBase {
readonly params?: BindableAttrValues<P>;
readonly attributes: {
readonly dataSource?: ConstantAttrValue<string>;
readonly connectionId: ConstantAttrValue<NodeReference>;
readonly connectionId: ConstantAttrValue<NodeReference | null>;
readonly query: ConstantAttrValue<Q>;
readonly transform?: ConstantAttrValue<string>;
readonly transformEnabled?: ConstantAttrValue<boolean>;
Expand Down Expand Up @@ -811,12 +811,21 @@ export function createRenderTree(dom: AppDom): RenderTree {
};
}

export function ref(nodeId: NodeId): NodeReference {
return { $$ref: nodeId };
export function ref(nodeId: NodeId): NodeReference;
export function ref(nodeId: null | undefined): null;
export function ref(nodeId: Maybe<NodeId>): NodeReference | null;
export function ref(nodeId: Maybe<NodeId>): NodeReference | null {
return nodeId ? { $$ref: nodeId } : null;
}

export function deref(nodeRef: NodeReference): NodeId {
return nodeRef.$$ref;
export function deref(nodeRef: NodeReference): NodeId;
export function deref(nodeRef: null | undefined): null;
export function deref(nodeRef: Maybe<NodeReference>): NodeId | null;
export function deref(nodeRef: Maybe<NodeReference>): NodeId | null {
if (nodeRef) {
return nodeRef.$$ref;
}
return null;
}

export function fromLegacyQueryNode(node: QueryNode<any>): QueryNode<any> {
Expand Down
66 changes: 15 additions & 51 deletions packages/toolpad-app/src/server/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,42 +161,10 @@ export async function getApp(id: string) {
return prisma.app.findUnique({ where: { id } });
}

function createDefaultConnections(dom: appDom.AppDom): appDom.ConnectionNode[] {
if (process.env.TOOLPAD_DEMO) {
return [
appDom.createNode(dom, 'connection', {
name: 'movies',
attributes: {
dataSource: appDom.createConst('movies'),
params: appDom.createSecret({ apiKey: '12345' }),
status: appDom.createConst(null),
},
}),
];
}

return [
appDom.createNode(dom, 'connection', {
name: 'rest',
attributes: {
dataSource: appDom.createConst('rest'),
params: appDom.createSecret({}),
status: appDom.createConst(null),
},
}),
];
}

function createDefaultDom(): appDom.AppDom {
let dom = appDom.createDom();
const appNode = appDom.getApp(dom);

// Create default connections
const defaultConnections = createDefaultConnections(dom);
for (const connection of defaultConnections) {
dom = appDom.addNode(dom, connection, appNode, 'connections');
}

// Create default page
const newPageNode = appDom.createNode(dom, 'page', {
name: 'Page 1',
Expand Down Expand Up @@ -335,20 +303,16 @@ export async function loadReleaseDom(appId: string, version: number): Promise<ap
return JSON.parse(release.snapshot.toString('utf-8')) as appDom.AppDom;
}

async function getConnection<P = unknown>(
appId: string,
id: string,
): Promise<appDom.ConnectionNode<P>> {
const dom = await loadPreviewDom(appId);
return appDom.getNode(dom, id as NodeId, 'connection') as appDom.ConnectionNode<P>;
}

export async function getConnectionParams<P = unknown>(
appId: string,
id: string,
connectionId: string | null,
): Promise<P | null> {
const dom = await loadPreviewDom(appId);
const node = appDom.getNode(dom, id as NodeId, 'connection') as appDom.ConnectionNode<P>;
const node = appDom.getNode(
dom,
connectionId as NodeId,
'connection',
) as appDom.ConnectionNode<P>;
return node.attributes.params.value;
}

Expand Down Expand Up @@ -386,10 +350,9 @@ export async function execQuery<P, Q>(
);
}

const connectionParams = await getConnectionParams<P>(
appId,
appDom.deref(query.attributes.connectionId.value),
);
const connectionParams = query.attributes.connectionId.value
? await getConnectionParams<P>(appId, appDom.deref(query.attributes.connectionId.value))
: null;

const transformEnabled = query.attributes.transformEnabled?.value;
const transform = query.attributes.transform?.value;
Expand All @@ -406,22 +369,23 @@ export async function execQuery<P, Q>(

export async function dataSourceFetchPrivate<P, Q>(
appId: string,
connectionId: NodeId,
dataSourceId: string,
connectionId: NodeId | null,
query: Q,
): Promise<any> {
const connection: appDom.ConnectionNode<P> = await getConnection<P>(appId, connectionId);
const dataSourceId = connection.attributes.dataSource.value;
const dataSource: ServerDataSource<P, Q, any> | undefined = serverDataSources[dataSourceId];

if (!dataSource) {
throw new Error(`Unknown dataSource "${dataSourceId}" for connection "${connection.id}"`);
throw new Error(`Unknown dataSource "${dataSourceId}"`);
}

if (!dataSource.execPrivate) {
throw new Error(`No execPrivate available on datasource "${dataSourceId}"`);
}

const connectionParams = connection.attributes.params.value;
const connectionParams: P | null = connectionId
? await getConnectionParams<P>(appId, connectionId)
: null;

return dataSource.execPrivate(connectionParams, query);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ function ConnectionEditorContent<P>({
[connectionNode, domApi],
);

const dataSourceType = connectionNode.attributes.dataSource.value;
const dataSource = dataSources[dataSourceType];
const dataSourceId = connectionNode.attributes.dataSource.value;
const dataSource = dataSources[dataSourceId];
const connectionEditorContext = React.useMemo(
() => ({ appId, connectionId: connectionNode.id }),
[appId, connectionNode.id],
() => ({ appId, dataSourceId, connectionId: connectionNode.id }),
[appId, dataSourceId, connectionNode.id],
);

return (
Expand All @@ -77,7 +77,7 @@ function ConnectionEditorContent<P>({
dataSource={dataSource}
value={connectionNode.attributes.params.value}
onChange={handleConnectionChange}
handlerBasePath={`/api/dataSources/${dataSourceType}`}
handlerBasePath={`/api/dataSources/${dataSourceId}`}
appId={appId}
connectionId={connectionNode.id}
/>
Expand Down
Loading