Public
Script
Readme

Glide API 2.0

Effects and utility functions for working with Glide API 2.0.

Authentication

Set glide environment variable to authenticate. If using effect, you can also provide a layer constructed with Glide.layer.

Examples

Simplest case, use runIngest with an async fetch:

import * as Glide from "https://esm.town/v/dvdsgl/glide"; await Glide.importTable({ table: "abc123-def456-ghi789", getRows: async function*() { // yield Row[] to add them to the stash yield [{ Name: "David" }]; }, });

Load 20k pull requests:

import * as Glide from "https://esm.town/v/dvdsgl/glide"; await Glide.importTable({ table: "abc123-def456-ghi789", getRows: async function*() { const octokit = new Octokit({ auth: "..." }); for await ( const { data: prs } of octokit.paginate.iterator(octokit.rest.pulls.list, { owner: "glideapps", repo: "glide", state: "all" }) ) yield prs; }, });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { withTimeLog } from "https://esm.town/v/dvdsgl/effect";
import { Chunk, Context, Data, Effect, Layer, Logger, LogLevel, Option, Stream } from "npm:effect";
import { UnknownException } from "npm:effect/Cause";
import { v4 as uuidv4 } from "npm:uuid";
const baseUrl = `https://api.glideapps.com`;
type Stash = { $stashID: string };
type PutResult = { data: { rowIDs: string[] } };
export type GlideInfo = { token: string };
export class Glide extends Context.Tag("Glide")<Glide, GlideInfo>() {}
export class GlideError extends Data.TaggedError("GlideError")<{
type?: string;
message: string;
}> {}
export const layer = (info: GlideInfo) => Layer.succeed(Glide, Glide.of(info));
const getGlide: Effect.Effect<GlideInfo, GlideError> = Effect.gen(function*() {
const provided = yield* Effect.serviceOption(Glide);
if (Option.isSome(provided)) return provided.value;
const env = {
token: Deno.env.get("glide"),
};
if (typeof env.token === "string") return env;
yield* new GlideError({
message: "No Glide layer provided, and 'glide' secret not found in environment",
});
});
function removeUnsupportedColumnTypes(row: any): any {
const pr = { ...row };
for (const [k, v] of Object.entries(pr)) {
// Glide does not accept arrays or objects yet
if (Array.isArray(v) || typeof v === "object") {
delete pr[k];
}
}
return pr;
}
// Handles calling fetch, checking for API errors
function fetchGlide<A>(
method: "GET" | "POST" | "PUT",
url: string,
body: unknown,
): Effect.Effect<A, GlideError> {
return Effect.gen(function*() {
const { token } = yield* getGlide;
const result = yield* Effect.tryPromise(() =>
fetch(url, {
method,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
})
).pipe(
Effect.tap(Effect.annotateCurrentSpan({ method, url })),
Effect.withLogSpan("fetchGlide"),
);
if (!result.ok) {
yield* new GlideError({ message: result.statusText });
}
const json = yield* Effect.tryPromise(() => result.json());
if ("error" in json) {
yield* new GlideError(json.error);
}
return json;
}).pipe(
Effect.catchTag(
"UnknownException",
() => new GlideError({ message: "Could not fetch" }),
),
);
}
export const putTable = (
id: string,
rows: Stash | any[],
): Effect.Effect<PutResult, GlideError> =>
Effect.gen(function*() {
// Some tables have a prefix, e.g. "native-table-" but this API
// does not accept it.
id = id.replace("native-table-", "");
const url = `${baseUrl}/tables/${id}?onSchemaError=updateSchema`;
yield* Effect.logDebug(`putTable ${url}`);
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
July 29, 2024