Skip to content

Commit

Permalink
Remove row_pk from the client API (#34)
Browse files Browse the repository at this point in the history
Re: clockworklabs/SpacetimeDB#840

This commit updates the TypeScript SDK to no longer use the `row_pk` field
in the client API,
as that field no longer exists.

As in the other SDKs, we replace our use of the `row_pk`
with the serialized representation of the row,
as this saves our needing to have objects/dicts/hash-maps keyed on domain types.

Unlike the other SDKs, we support either the binary (protobuf) or JSON APIs.
When using the binary API, we convert the BSATN row to a string,
and use that as the `rowPk`.
When using the JSON API, we `JSON.stringify` the row itself, and use that as the `rowPk`.
The latter is ugly and not performant,
but we don't care because the JSON API is slow anyways.

This commit also removes some uses of `any` from the deserialization code,
because I wanted the compiler to double-check my work.
  • Loading branch information
gefjon authored Feb 28, 2024
1 parent a149e44 commit b1488a0
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 158 deletions.
31 changes: 31 additions & 0 deletions DEVELOP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Notes for maintainers

The file `client_api.ts` is generated by [ts-proto](https://github.com/stephenh/ts-proto)
from [the SpacetimeDB client-api-messages proto definition](https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/client-api-messages/protobuf/client_api.proto).
This is not automated.
Whenever the `client_api.proto` changes, you'll have to manually re-run `protoc` to re-generate the definitions.

```sh
cd spacetimedb-typescript-sdk
npm i # get the dev-dependencies
cd ~/path/to/SpacetimeDB/crates/client-api-messages/protobuf
protoc --plugin=/absolute/path/to/spacetimedb-typescript-sdk/node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out=/absolute/path/to/spacetimedb-typescript-sdk/src \
./client_api.proto
```

Note that `protoc` cannot understand paths that start with `~`;
you must write the absolute path starting from `/`.

For reasons that escape me, `protoc-gen-ts` emits an incorrect import for `Long`.
After generating, you may have to manually edit `client_api.ts` by replacing:

```ts
import Long = require("long");
```

with:

```ts
import Long from "long";
```
26 changes: 2 additions & 24 deletions src/client_api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable */
import * as _m0 from "protobufjs/minimal";
import Long from "long";
import _m0 from "protobufjs/minimal";

export const protobufPackage = "client_api";

Expand Down Expand Up @@ -223,15 +223,10 @@ export interface TableUpdate {
* / - `op` of `INSERT` means that the row in question has been either newly inserted or
* / updated, and is resident in the table.
* /
* / - `row_pk` is a hash of the row computed by the database. As of 2023-06-13, even for
* / tables with a `#[primarykey]` annotation on one column, the `row_pk` is not
* / that primary key.
* /
* / - `row` is the row itself, encoded as BSATN.
*/
export interface TableRowOperation {
op: TableRowOperation_OperationType;
rowPk: Uint8Array;
row: Uint8Array;
}

Expand Down Expand Up @@ -1198,7 +1193,7 @@ export const TableUpdate = {
};

function createBaseTableRowOperation(): TableRowOperation {
return { op: 0, rowPk: new Uint8Array(0), row: new Uint8Array(0) };
return { op: 0, row: new Uint8Array(0) };
}

export const TableRowOperation = {
Expand All @@ -1209,9 +1204,6 @@ export const TableRowOperation = {
if (message.op !== 0) {
writer.uint32(8).int32(message.op);
}
if (message.rowPk.length !== 0) {
writer.uint32(18).bytes(message.rowPk);
}
if (message.row.length !== 0) {
writer.uint32(26).bytes(message.row);
}
Expand All @@ -1233,13 +1225,6 @@ export const TableRowOperation = {

message.op = reader.int32() as any;
continue;
case 2:
if (tag !== 18) {
break;
}

message.rowPk = reader.bytes();
continue;
case 3:
if (tag !== 26) {
break;
Expand All @@ -1261,9 +1246,6 @@ export const TableRowOperation = {
op: isSet(object.op)
? tableRowOperation_OperationTypeFromJSON(object.op)
: 0,
rowPk: isSet(object.rowPk)
? bytesFromBase64(object.rowPk)
: new Uint8Array(0),
row: isSet(object.row) ? bytesFromBase64(object.row) : new Uint8Array(0),
};
},
Expand All @@ -1273,9 +1255,6 @@ export const TableRowOperation = {
if (message.op !== 0) {
obj.op = tableRowOperation_OperationTypeToJSON(message.op);
}
if (message.rowPk.length !== 0) {
obj.rowPk = base64FromBytes(message.rowPk);
}
if (message.row.length !== 0) {
obj.row = base64FromBytes(message.row);
}
Expand All @@ -1292,7 +1271,6 @@ export const TableRowOperation = {
): TableRowOperation {
const message = createBaseTableRowOperation();
message.op = object.op ?? 0;
message.rowPk = object.rowPk ?? new Uint8Array(0);
message.row = object.row ?? new Uint8Array(0);
return message;
},
Expand Down
46 changes: 46 additions & 0 deletions src/json_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export interface Message {
IdentityToken?: IdentityToken | undefined;
SubscriptionUpdate?: SubscriptionUpdate | undefined;
TransactionUpdate?: TransactionUpdate | undefined;
}

export interface IdentityToken {
identity: string;
token: string;
address: string;
}

export interface SubscriptionUpdate {
table_updates: TableUpdate[];
}

export interface TableUpdate {
table_id: number;
table_name: string;
table_row_operations: TableRowOperation[];
}

export interface TableRowOperation {
op: "insert" | "delete";
row: any[];
}

export interface TransactionUpdate {
event: Event;
subscription_update: SubscriptionUpdate;
}

export interface Event {
timestamp: number;
status: "committed" | "failed" | "out_of_energy";
caller_identity: string;
caller_address: string;
function_call: FunctionCall;
energy_quanta_used: number;
message: string;
}

export interface FunctionCall {
reducer: string;
args: string;
}
Loading

0 comments on commit b1488a0

Please sign in to comment.