Skip to content
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ GITDB_GITHUB_TOKEN=github_token_with_contents_write_access

## Examples

The repository keeps exactly two live GitHub-backed examples. Both use the
browser-compatible `fetch` store so the same shape applies to extensions and
static apps:
The repository keeps exactly two live GitHub-backed examples. Both configure the
browser-compatible GitHub store adapter, then use only the GitDB table API so the
same shape applies to extensions and static apps:

- `examples/api-plaintext`
- `examples/api-encrypted`
Expand Down
4 changes: 2 additions & 2 deletions docs/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ GITDB_GITHUB_TOKEN=github_token_with_contents_write_access
## 예제

레포에는 실제 GitHub DB repository에 쓰는 예제를 두 개만 둡니다. 둘 다
browser-compatible `fetch` store를 써서 extension/static app과 같은 구조를
보여줍니다:
browser-compatible GitHub store adapter를 설정한 뒤 GitDB table API만 사용합니다.
그래서 extension/static app과 같은 구조를 보여줍니다:

- `examples/api-plaintext`
- `examples/api-encrypted`
Expand Down
38 changes: 1 addition & 37 deletions examples/api-encrypted/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,6 @@ await accounts.upsertMany([
{ id: "acct_2", status: "active", tier: "pro" },
])

const remoteManifestPath = `${config.prefix}/manifest.enc`
const remotePayload = await readGitHubFile(config, remoteManifestPath)
const leaksPlaintext = remotePayload.includes("acct_1") || remotePayload.includes("active")
if (leaksPlaintext) {
throw new Error("encrypted GitHub example leaked plaintext into the remote manifest")
}

const activeAccounts = await readRowsFromGitHub(async () => {
const verificationDb = await GitDb.open({
store: new GitHubFetchEncryptedStore(config, cipher),
Expand All @@ -55,11 +48,10 @@ const activeAccounts = await readRowsFromGitHub(async () => {
const summary = {
activeAccounts,
branch: config.branch,
encryption: "web-aes-gcm",
example: "api-encrypted",
leaksPlaintext,
mode: "github-encrypted",
prefix: config.prefix,
remoteManifestPath,
remoteVerified: true,
repo: `${config.owner}/${config.repo}`,
status: "ok",
Expand All @@ -86,34 +78,6 @@ function requiredEnv(name, fallback) {
return value
}

async function readGitHubFile(config, path) {
const response = await fetch(githubContentsUrl(config, path), {
headers: {
Accept: "application/vnd.github+json",
Authorization: `Bearer ${config.token}`,
"X-GitHub-Api-Version": "2022-11-28",
},
})
if (!response.ok) {
throw new Error(`GitHub path read failed for ${path}: ${response.status}`)
}

const payload = await response.json()
if (Array.isArray(payload) || payload.type !== "file" || typeof payload.content !== "string") {
throw new Error(`GitHub path is not a file: ${path}`)
}
return Buffer.from(payload.content, "base64").toString("utf8")
}

function githubContentsUrl(config, path) {
const encodedPath = path
.split("/")
.map((part) => encodeURIComponent(part))
.join("/")
const ref = encodeURIComponent(config.branch)
return `https://api.github.com/repos/${config.owner}/${config.repo}/contents/${encodedPath}?ref=${ref}`
}

async function readRowsFromGitHub(selectRows, expectedCount) {
for (let attempt = 0; attempt < 8; attempt += 1) {
const rows = await selectRows()
Expand Down
31 changes: 0 additions & 31 deletions examples/api-plaintext/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ await people.upsertMany([
{ id: "p3", name: "Grace", team: "storage" },
])

const remoteManifestPath = `${config.prefix}/manifest.json`
await readGitHubFile(config, remoteManifestPath)
const rows = await readRowsFromGitHub(async () => {
const verificationDb = await GitDb.open({
store: new GitHubFetchPlaintextStore(config),
Expand All @@ -47,7 +45,6 @@ const summary = {
example: "api-plaintext",
mode: "github-plaintext",
prefix: config.prefix,
remoteManifestPath,
remoteVerified: true,
repo: `${config.owner}/${config.repo}`,
rows,
Expand All @@ -74,34 +71,6 @@ function requiredEnv(name, fallback) {
return value
}

async function readGitHubFile(config, path) {
const response = await fetch(githubContentsUrl(config, path), {
headers: {
Accept: "application/vnd.github+json",
Authorization: `Bearer ${config.token}`,
"X-GitHub-Api-Version": "2022-11-28",
},
})
if (!response.ok) {
throw new Error(`GitHub path read failed for ${path}: ${response.status}`)
}

const payload = await response.json()
if (Array.isArray(payload) || payload.type !== "file" || typeof payload.content !== "string") {
throw new Error(`GitHub path is not a file: ${path}`)
}
return Buffer.from(payload.content, "base64").toString("utf8")
}

function githubContentsUrl(config, path) {
const encodedPath = path
.split("/")
.map((part) => encodeURIComponent(part))
.join("/")
const ref = encodeURIComponent(config.branch)
return `https://api.github.com/repos/${config.owner}/${config.repo}/contents/${encodedPath}?ref=${ref}`
}

async function readRowsFromGitHub(selectRows, expectedCount) {
for (let attempt = 0; attempt < 8; attempt += 1) {
const rows = await selectRows()
Expand Down
Loading