Platform
Resources
Pricing
Sign in
Get started
Endpoint Services
Extending Observable to the backend with a custom serverless runtime. Innovative live-coding workflows against production traffic.
Workspace
Fork
Public
documentation
By
Tom Larkworthy
Edited
Jul 2, 2023
1 fork
9 stars
4
Insert cell
Insert cell
Insert cell
Insert cell
encrypted_service_account_credentials
=
(
{
name
:
"AES-GCM"
,
salt
:
"x4gEPgJOp9brBg=="
,
iv
:
"Hwoo2XyMFSJT5FLq"
,
ciphertext
:
"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"
})
Insert cell
Insert cell
Insert cell
viewof
service_account_credentials
=
decrypt
(
encrypted_service_account_credentials
)
Insert cell
Insert cell
service_account_credentials
Insert cell
Insert cell
Insert cell
gapi_config
=
(
{
apiKey
:
"AIzaSyC-Uh-7CtBwhlZrXvAr1gmnUaZzixeVG84"
,
discoveryDocs
:
[
"https://bigquery.googleapis.com/discovery/v1/apis/bigquery/v2/rest"
]
,
service_account_key
:
JSON
.
parse
(
service_account_credentials
)
}
)
Insert cell
Insert cell
bqClient
=
await
createGapi
(
gapi_config
)
Insert cell
Insert cell
bqResponse
=
bqClient
.
bigquery
.
jobs
.
query
(
{
projectId
:
"larkworthy-dfb11"
,
resource
:
{
// See https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query#QueryRequest
query
:
"SELECT title FROM [bigquery-public-data:hacker_news.stories] WHERE title != 'Placeholder' LIMIT 20"
,
useLegacySql
:
true
}
}
)
Insert cell
Insert cell
Insert cell
data
=
bqResponse
.
result
.
rows
.
map
(
col
=>
col
.
f
[
0
]
)
Insert cell
Table
(
data
)
Insert cell
Insert cell
Insert cell
Insert cell
firebaseConfig
=
(
{
// I don't configure everything, we jsut want Auth and storage for this notebook
apiKey
:
"AIzaSyBN4bxw6d0cM0CGPNzRrkRlBqwFQnPLdN4"
,
authDomain
:
"larkworthy-dfb11.firebaseapp.com"
,
projectId
:
"larkworthy-dfb11"
,
appId
:
"1:786910701676:web:8d7dd002acf3b78c74d049"
,
storageBucket
:
"larkworthy-dfb11.appspot.com"
}
)
Insert cell
Insert cell
import
{
firebase
}
with
{
firebaseConfig
}
from
'@tomlarkworthy/firebase'
Insert cell
import
{
getAccessTokenFromServiceAccount
,
signinWithAccessToken
}
from
'@tomlarkworthy/firebase-admin'
Insert cell
Insert cell
service_account_user
=
{
const
token
=
await
getAccessTokenFromServiceAccount
(
service_account_credentials
)
;
await
signinWithAccessToken
(
firebase
,
token
)
;
return
firebase
.
auth
(
)
.
currentUser
;
}
Insert cell
Insert cell
service_account_user
.
uid
Insert cell
Insert cell
Insert cell
{
service_account_user
;
// Make sure this cell depends on the service_account_user logging in
// See https://medium.com/@dorathedev/uploading-json-objects-as-json-files-to-firebase-storage-without-having-or-creating-a-json-file-38ad323af3c4
// convert your object into a JSON-string
const
string
=
JSON
.
stringify
(
data
)
;
// create a Blob from the JSON-string
const
blob
=
new
Blob
(
[
string
]
,
{
type
:
"application/json"
}
)
;
// create a reference to the storage
var
ref
=
firebase
.
storage
(
)
.
ref
(
"/examples/cache-bigquery/data.json"
)
;
// upload you blob into the storage
return
ref
.
put
(
blob
)
;
}
Insert cell
Insert cell
// Use the "authenticated url" as the REST API
uploadToBucket
=
{
return
(
await
fetch
(
`https://www.googleapis.com/upload/storage/v1/b/larkworthy-dfb11.appspot.com/o?name=examples/cache-bigquery/dataalt.json`
,
{
headers
:
{
'Authorization'
:
`Bearer ${
await
getAccessTokenFromServiceAccount
(
service_account_credentials
)
}`
}
,
method
:
"POST"
,
body
:
JSON
.
stringify
(
data
)
}
)
)
.
text
(
)
}
Insert cell
import
{
fetchp
}
from
'@tomlarkworthy/fetchp'
Insert cell
Insert cell
cached_data_ref
=
firebase
.
storage
(
)
.
ref
(
)
.
child
(
"/examples/cache-bigquery/data.json"
)
Insert cell
1
cached_data
=
(
await
fetch
(
await
cached_data_ref
.
getDownloadURL
(
)
)
)
.
json
(
)
Insert cell
Insert cell
Table
(
cached_data
)
Insert cell
Insert cell
Insert cell
Purpose-built for displays of data
Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Try it for free
Learn more
Fork
View
Export
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
encrypted_service_account_credentials
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
service_account_credentials
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
gapi_config
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
bqClient
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
bqResponse
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
data
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
firebaseConfig
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
service_account_user
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
uploadToBucket
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
cached_data_ref
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
cached_data
Show 1 comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Copy import
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML
Edit
Add comment
Select
Duplicate
Copy link
Embed
Delete
JavaScript
Markdown
HTML