-
Notifications
You must be signed in to change notification settings - Fork 3
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 new schema endpoint and metadata operations #13
Changes from all commits
0df11ad
117dde9
e65f525
7e76eb2
ece40ef
8d5b5f4
7a88c64
1a7e0ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,9 +1,12 @@ | ||||||
import { Client, makeClient } from "./rest"; | ||||||
import type { TableProps, Row, ColumnSchema, RowID, FullRow, AppProps } from "./types"; | ||||||
|
||||||
import fetch from "cross-fetch"; | ||||||
|
||||||
type RowIdentifiable<T extends ColumnSchema> = RowID | FullRow<T>; | ||||||
|
||||||
type IDName = { id: string; name: string }; | ||||||
|
||||||
function rowID(row: RowIdentifiable<any>): RowID { | ||||||
return typeof row === "string" ? row : row.$rowID; | ||||||
} | ||||||
|
@@ -18,19 +21,32 @@ const defaultEndpoint = "https://api.glideapp.io/api/function"; | |||||
class Table<T extends ColumnSchema> { | ||||||
private props: TableProps<T>; | ||||||
|
||||||
private client: Client; | ||||||
|
||||||
public get app(): string { | ||||||
return this.props.app; | ||||||
} | ||||||
|
||||||
public get id(): string { | ||||||
return this.props.table; | ||||||
} | ||||||
|
||||||
public get table(): string { | ||||||
return this.props.table; | ||||||
} | ||||||
|
||||||
public get name() { | ||||||
return this.props.name; | ||||||
} | ||||||
|
||||||
constructor(props: TableProps<T>) { | ||||||
this.props = { | ||||||
token: process.env.GLIDE_TOKEN, | ||||||
...props, | ||||||
token: props.token ?? process.env.GLIDE_TOKEN, | ||||||
}; | ||||||
this.client = makeClient({ | ||||||
token: process.env.GLIDE_TOKEN!, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this just be
Suggested change
|
||||||
}); | ||||||
} | ||||||
|
||||||
private renameOutgoing(rows: Row<T>[]): Row<T>[] { | ||||||
|
@@ -159,6 +175,20 @@ class Table<T extends ColumnSchema> { | |||||
await this.deleteRows([row]); | ||||||
} | ||||||
|
||||||
public async getSchema(): Promise<{ | ||||||
data: { columns: Array<{ id: string; name: string; type: { kind: string } }> }; | ||||||
}> { | ||||||
const { app, table } = this.props; | ||||||
|
||||||
const response = await this.client.get(`/apps/${app}/tables/${table}/schema`); | ||||||
|
||||||
if (response.status !== 200) { | ||||||
throw new Error(`Failed to get schema: ${response.status} ${response.statusText}`); | ||||||
} | ||||||
|
||||||
return await response.json(); | ||||||
} | ||||||
|
||||||
public async getRows(): Promise<FullRow<T>[]> { | ||||||
const { token, app, table } = this.props; | ||||||
|
||||||
|
@@ -175,7 +205,12 @@ class Table<T extends ColumnSchema> { | |||||
}); | ||||||
|
||||||
if (!response.ok) { | ||||||
throw new Error(`Failed to get rows: ${response.status} ${response.statusText}`); | ||||||
throw new Error( | ||||||
`Failed to get rows: ${response.status} ${response.statusText} ${JSON.stringify({ | ||||||
app, | ||||||
table, | ||||||
})}` | ||||||
); | ||||||
} | ||||||
|
||||||
const [result] = await response.json(); | ||||||
|
@@ -189,7 +224,38 @@ class Table<T extends ColumnSchema> { | |||||
} | ||||||
|
||||||
class App { | ||||||
constructor(private props: AppProps) {} | ||||||
private props: AppProps; | ||||||
private client: Client; | ||||||
|
||||||
public get id() { | ||||||
return this.props.id; | ||||||
} | ||||||
|
||||||
public get name() { | ||||||
return this.props.name; | ||||||
} | ||||||
|
||||||
constructor(props: AppProps) { | ||||||
this.props = { ...props, token: props.token ?? process.env.GLIDE_TOKEN! }; | ||||||
this.client = makeClient({ | ||||||
token: process.env.GLIDE_TOKEN!, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same again?
Suggested change
|
||||||
}); | ||||||
} | ||||||
|
||||||
public async getTableNamed(name: string) { | ||||||
const tables = await this.getTables(); | ||||||
return tables?.find(t => t.name === name); | ||||||
} | ||||||
|
||||||
public async getTables() { | ||||||
const { id } = this.props; | ||||||
const result = await this.client.get(`/apps/${id}/tables`); | ||||||
|
||||||
if (result.status !== 200) return undefined; | ||||||
|
||||||
const { data: tables }: { data: IDName[] } = await result.json(); | ||||||
return tables.map(t => this.table({ table: t.id, name: t.name, columns: {} })); | ||||||
} | ||||||
|
||||||
public table<T extends ColumnSchema>(props: Omit<TableProps<T>, "app">) { | ||||||
return new Table<T>({ | ||||||
|
@@ -201,10 +267,29 @@ class App { | |||||
} | ||||||
} | ||||||
|
||||||
export function app(props: AppProps): App { | ||||||
export function app(props: AppProps | string): App { | ||||||
if (typeof props === "string") { | ||||||
props = { id: props }; | ||||||
} | ||||||
return new App(props); | ||||||
} | ||||||
|
||||||
export async function getApps(props: { token?: string } = {}): Promise<App[] | undefined> { | ||||||
const client = makeClient(props); | ||||||
const response = await client.get(`/apps`); | ||||||
if (response.status !== 200) return undefined; | ||||||
const { data: apps }: { data: IDName[] } = await response.json(); | ||||||
return apps.map(idName => app({ ...props, ...idName })); | ||||||
} | ||||||
|
||||||
export async function getAppNamed( | ||||||
name: string, | ||||||
props: { token?: string } = {} | ||||||
): Promise<App | undefined> { | ||||||
const apps = await getApps(props); | ||||||
return apps?.find(a => a.name === name); | ||||||
} | ||||||
|
||||||
export function table<T extends ColumnSchema>(props: TableProps<T>) { | ||||||
return new Table<T>(props); | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import fetch from "cross-fetch"; | ||
|
||
export function makeClient({ token = process.env.GLIDE_TOKEN! }: { token?: string } = {}) { | ||
return { | ||
get(route: string, r: RequestInit = {}) { | ||
return fetch(`https://functions.prod.internal.glideapps.com/api${route}`, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like we're sort of committing to this endpoint, at least for some period of time, by shipping it here.. Just making sure we're cool with that /cc @timwellswa There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am prepared to change it. We will need to coordinate when we do, yes. |
||
method: "GET", | ||
...r, | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
"Content-Type": "application/json", | ||
Accept: "application/json", | ||
...r.headers, | ||
}, | ||
}); | ||
}, | ||
}; | ||
} | ||
|
||
export type Client = ReturnType<typeof makeClient>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make it clear to me that it's actually fetching the schema from Glide. Earlier in this sample,
inventory
is created by specifying the columns and their types, so I'd assume this would just return that again:I'm assuming that is still needed to get strongly typed rows? Might be good just to clarify the relationship between these