Skip to content

Instantly share code, notes, and snippets.

@Kattoor
Created June 7, 2025 20:17
Show Gist options
  • Save Kattoor/d9efe5c5e7b0964d3b70489c6bb85684 to your computer and use it in GitHub Desktop.
Save Kattoor/d9efe5c5e7b0964d3b70489c6bb85684 to your computer and use it in GitHub Desktop.
SpacetimeDB BitCraft example
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
import fs from 'fs';
import {WebSocket} from 'ws';
async function getIdentityToken() {
const response = await fetch('https://131.153.155.197/v1/identity', {method: 'POST'});
const {token: identityToken} = await response.json();
return identityToken;
}
const allowedTables = ['construction_recipe_desc', 'crafting_recipe_desc', 'item_desc', 'cargo_desc'];
function dumpTables(identityToken, tables) {
return new Promise((resolve) => {
const result = [];
const headers = {Authorization: `Bearer ${identityToken}`};
const ws = new WebSocket('wss://131.153.155.197/v1/database/bitcraft-global/subscribe', 'v1.json.spacetimedb', {headers});
ws.on('open', () => {
const subscriptionMessage = {
Subscribe: {
query_strings: tables.map((tableName) => `SELECT * FROM ${tableName}`),
request_id: 1
}
};
ws.send(JSON.stringify(subscriptionMessage));
});
ws.on('message', (data) => {
const message = JSON.parse(data.toString());
if (message.InitialSubscription) {
for (const {table_name, updates} of message.InitialSubscription.database_update.tables) {
const obj = {tableName: table_name, data: updates[0].inserts.map((insert) => JSON.parse(insert))};
result.push(obj);
}
resolve(result);
ws.close();
}
});
});
}
const identityToken = await getIdentityToken();
const tables = await dumpTables(identityToken, allowedTables);
for (const {tableName, data} of tables) {
const outputPath = `./out-tables`;
fs.mkdirSync(outputPath, {recursive: true});
fs.writeFileSync(`${outputPath}/${tableName}.json`, JSON.stringify(data, null, 2));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment