@mathrunet/masamune_cloudflare_turso
v3.4.1
Published
Server-side package of the Masamune framework for working with Turso via Cloudflare.
Maintainers
Readme
[GitHub] | [YouTube] | [Packages] | [X] | [LinkedIn] | [mathru.net]
Just load the package in index.ts and pass the predefined data to the methods to implement the server side.
Also, katana_functions_firebase can be used to execute server-side functions from methods defined on the client side, allowing for safe implementation.
Installation
Install the following packages
npm install @mathrunet/masamune_cloudflare_tursoImplementation
Pass the return value of the deploy function to export default. It is defined by passing various Workers to the deploy function.
import * as m from "@mathrunet/masamune_cloudflare_turso";
import rulesJson from "../rules.json";
export default m.deploy(
[
m.Functions.turso({
organization: "xxxx",
group: "xxxx",
autoCreateDatabase: true,
autoCreateTable: true,
autoMigrateAddColumns: true,
}),
m.Functions.tursoToken({
organization: "xxxx",
group: "xxxx",
}),
],
{
rules: rulesJson,
},
);Cloudflare bindings are also supported and take precedence over options:
TURSO_PLATFORM_API_TOKENTURSO_ORGANIZATIONTURSO_GROUP
For production, store the Platform API token as a secret:
wrangler secret put TURSO_PLATFORM_API_TOKENEndpoints
The package exposes Turso through a single provider path.
| Method | Path | Description |
| -------- | -------------- | --------------------------------- |
| GET | /turso/database/{database}/{table} | Read rows or count rows. |
| GET | /turso/database/{database}/{table}/{indexKey} | Read a row. |
| POST | /turso/database/{database}/{table} | Create a row. |
| POST | /turso/database/{database}/{table}/{indexKey} | Create a row with an explicit ID. |
| PUT | /turso/database/{database}/{table} | Update rows. |
| PUT | /turso/database/{database}/{table}/{indexKey} | Update a row. |
| DELETE | /turso/database/{database}/{table} | Delete rows. |
| DELETE | /turso/database/{database}/{table}/{indexKey} | Delete a row. |
| POST | /turso/token/database/{database} | Issue a database-scoped short-lived token. |
GET uses the path for database, table, and optional indexKey.
/turso/database/main/users/user_1Collection queries can pass where, orderBy, and limit.
/turso/database/main/users?where=[{"type":"equalTo","key":"name","value":"Alice"}]&orderBy=[{"key":"created_at","descending":true}]&limit=20Supported where types are equalTo, notEqualTo, lessThan,
lessThanOrEqualTo, greaterThan, greaterThanOrEqualTo, whereIn,
whereNotIn, isNull, isNotNull, and like.
POST / PUT / DELETE use the same path format and JSON bodies for
value or query filters.
{
"value": {
"name": "Alice"
}
}The previous query/body style is still accepted for compatibility:
/turso?database=main&table=users&indexKey=user_1Database and schema management
The worker can create Turso databases and tables automatically.
m.Functions.turso({
organization: TURSO_ORGANIZATION,
group: TURSO_GROUP,
platformApiToken: TURSO_PLATFORM_API_TOKEN,
autoCreateDatabase: true,
autoCreateTable: true,
autoMigrateAddColumns: true,
});groupName must point to an existing Turso group. The region/location is set
when the group is created, not when each database is created.
turso group create my-group --location aws-ap-northeast-1groupName can also be omitted when the runtime environment provides
TURSO_GROUP_NAME, such as through a local .env file or Cloudflare Worker
environment variables. When neither groupName nor TURSO_GROUP_NAME is
configured, database access that needs automatic database creation returns an
error.
Automatic migration is intentionally limited to additive field changes.
- New fields in
valueare added withALTER TABLE ADD COLUMN. - Existing fields are not migrated when their inferred type changes.
- Field rename, field deletion, primary key changes, unique constraints, and foreign keys are not automatically migrated.
PUTandDELETErequireindexKeyorwhereto avoid accidental full-table changes.
The default table shape is:
CREATE TABLE IF NOT EXISTS table_name (
id TEXT PRIMARY KEY,
created_at INTEGER,
updated_at INTEGER,
...
)Objects and arrays are stored as JSON strings.
Rules
Rules are provided by @mathrunet/masamune_cloudflare and are shared with
other Cloudflare database packages. Pass an imported rules.json to
WorkersOptions.rules on deploy, or pass the same config to each function
option.
{
"version": "1",
"rules": {
"database": {
"main": {
"read": "allow",
"write": "server"
},
"main/users/*": {
"read": "authenticated",
"write": { "type": "field", "field": "ownerId", "server": true }
}
}
}
}Database-scoped short-lived token
Use /turso/token/database/{database} to issue a Turso database token after
resolving read-only or full-access authorization through rules.
Token authorization is evaluated against the database path:
{
"version": "1",
"rules": {
"database": {
"main": {
"read": "authenticated",
"write": "deny"
}
}
}
}If read is allowed and write is denied, the worker issues a read-only
token. If both read and all write operations are allowed, the worker issues a
full-access token. If read is denied, the token request returns 403.
Named path parameters can be compared with the authenticated user ID:
{
"version": "1",
"rules": {
"database": {
"{uid}": {
"read": { "type": "path", "param": "uid" },
"write": { "type": "path", "param": "uid" }
}
}
}
}With this rule, only the authenticated user whose uid is equal to the
database name can access that database.
Read and write operations can be restricted to the Workers endpoint while issuing only the direct Turso token that is safe for the requested scope:
{
"version": "1",
"rules": {
"database": {
"{uid}": {
"read": { "type": "path", "param": "uid" },
"write": {
"type": "path",
"param": "uid",
"server": true
}
}
}
}
}server can also be used with read and field rules. A server-side rule
does not grant direct token access for that operation.
Table/document rules below the database path are also treated as server-side
rules for token issuance when they restrict read or write. This is
intentional because Turso Platform tokens are database-scoped and cannot enforce
document-level field or path checks on the client.
For a database-level Turso token, send operations without a table:
{
"ttlSeconds": 600,
"operations": ["read"]
}When the client also needs the Workers backend to decide whether a specific
table must use Functions fallback, send targets. targets are used only for
Masamune rules resolution; they are not passed to Turso as token scopes.
{
"ttlSeconds": 600,
"targets": [
{
"table": "users",
"operations": ["read", "write"]
}
]
}The response is:
{
"token": "<jwt>",
"expiresAt": 1760000000,
"url": "libsql://your-db.turso.io",
"readMode": "direct",
"writeMode": "functions",
"targets": [
{
"table": "users",
"operations": ["read", "write"],
"readMode": "direct",
"writeMode": "functions"
}
]
}If both read and write are functions-only, /turso/token/database/{database}
does not return token, expiresAt, or url; it returns only the resolved
modes and targets:
{
"readMode": "functions",
"writeMode": "functions",
"targets": [
{
"table": "users",
"operations": ["read", "write"],
"readMode": "functions",
"writeMode": "functions"
}
]
}The previous scope request field and scopes response field are still
accepted/returned for compatibility, but new clients should use operations
and targets.
url is resolved by the Workers backend. This lets clients use direct libSQL
access for dynamically created databases without building the Turso hostname on
the client.
ttlSeconds defaults to 600 seconds and is capped by maxTtlSeconds (default: 3600 seconds).
Tokens are generated with the Turso Platform API:
POST /v1/organizations/{organizationSlug}/databases/{databaseName}/auth/tokensGitHub Sponsors
Sponsors are always welcome. Thank you for your support!
