DatasetteClient = {
async function DatasetteClient(baseUrl, options = {}) {
const { fetchInit = {} } = options;
const meta = await fetch(`${baseUrl}.json`, fetchInit)
.then(r => r.json())
.catch(() => null);
if (!meta)
throw Error(
'Error connecting to Datasette instance. Make sure you are passing in a valid URL, and that CORS is enabled on the Datasette instance (with the --cors flag).'
);
if (typeof meta.database !== 'string')
throw Error(
'DatasetteClient url must point to a specific database, not the entire Datasette instance.'
);
async function db(strings, ...values) {
const { sql, params } = parseTemplate(strings, ...values);
const fetchUrl = getFetchURL(baseUrl, sql, params);
const data = await fetch(fetchUrl, fetchInit).then(r => r.json());
return data;
}
db.info = async () => {
return fetch(`${baseUrl}.json`, fetchInit).then(r => r.json());
};
db.dry = (strings, ...values) => {
return parseTemplate(strings, ...values);
};
function tableRenderer(options = {}) {
const { renderCell, extraColumns = [] } = options;
return async function(a, ...b) {
const { sql, params } = parseTemplate(a, ...b);
const fetchUrl = getFetchURL(baseUrl, sql, params, 'objects');
const data = await fetch(fetchUrl, fetchInit).then(r => r.json());
const dsLink = `${baseUrl}?${(() => {
const sp = new URLSearchParams();
sp.append('sql', sql);
for (const key in params) {
sp.append(key, params[key]);
}
return sp.toString();
})()}`;
if (data.ok === false)
return _renderError(data.title, data.status, data.error);
if (data.rows.length === 0)
return Object.assign(html`<div>No results!`, { value: data.rows });
const table = html`
<div style="overflow: auto; max-height: 400px;">
<table>
<thead>
<tr>
${data.columns.map(c => html`<th>${DOM.text(c)}`)}
${extraColumns.map(c => html`<th>${DOM.text(c.name)}`)}
</tr>
</thead>
<tbody>
${data.rows.map(
row =>
html`<tr>
${data.columns.map(column => {
const result = renderCell && renderCell(row[column], column);
return html`<td>${result || DOM.text(row[column])}`;
})}
${extraColumns.map(c => html`<td>${c.render(row)}`)}
</tr>`
)}
</tbody>
</table>
</div>
${_renderTableFooter(
data.rows,
data.columns,
data.truncated,
data.query_ms,
dsLink
)}
`;
const value = Object.assign(data.rows, { columns: data.columns });
return Object.assign(table, { value });
};
}
db.table = tableRenderer();
db.table.options = tableRenderer;
db.render = function(render) {
return async function(a, ...b) {
const { sql, params } = parseTemplate(a, ...b);
const fetchUrl = getFetchURL(baseUrl, sql, params, 'objects');
const data = await fetch(fetchUrl, fetchInit).then(r => r.json());
if (data.ok === false)
return _renderError(data.title, data.status, data.error);
return Object.assign(render(data.rows, data.columns), {
value: Object.assign(data.rows, { columns: data.columns })
});
};
};
return db;
}
return DatasetteClient;
}