Skip to content

Instantly share code, notes, and snippets.

@tywalch
Last active January 3, 2026 19:36
Show Gist options
  • Select an option

  • Save tywalch/321e033a97026b4893bcff7e8117eebb to your computer and use it in GitHub Desktop.

Select an option

Save tywalch/321e033a97026b4893bcff7e8117eebb to your computer and use it in GitHub Desktop.
ElectroDB Issue 540
// THIS FILE USES THE SAME MODELS SPECIFIED IN THE PROVIDED PLAYGROUND
import { Entity as Entity0, Service as Service0 } from "threedotfivedotone";
import { Entity as Entity1, Service as Service1 } from "threedotfivedotzero";
import { Entity as Entity2, Service as Service2 } from "threedotfivedottwo";
import { DynamoDB } from "aws-sdk";
import { expect } from "chai";
const dynamodb = new DynamoDB({
region: "us-east-1",
endpoint: "http://localhost:8000",
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
});
const manager = {
async exists(tableName: string) {
let tables = await dynamodb.listTables().promise();
return !!(tables.TableNames || []).includes(tableName);
},
async drop(tableName: string) {
return dynamodb.deleteTable({ TableName: tableName }).promise();
},
async create(tableName: string, tableDefinition: any) {
return dynamodb
.createTable({ ...tableDefinition, TableName: tableName })
.promise();
},
};
const client = new DynamoDB.DocumentClient({
region: "us-east-1",
endpoint: "http://localhost:8000",
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
});
function createZeroService(tableName: string) {
/* Tasks Entity */
const tenancy = new Entity0(
{
model: {
entity: "tenancy",
version: "1",
service: "tenancy"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
name: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.0',
},
createdAt: {
type: "number",
default: () => Date.now(),
// cannot be modified after created
readOnly: true
},
updatedAt: {
type: "number",
// watch for changes to any attribute
watch: "*",
// set current timestamp when updated
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
field: "pk",
composite: ["tenancyId"]
},
sk: {
field: "sk",
// create composite keys for partial sort key queries
composite: []
}
},
settings: {
// collections allow for queries across multiple entities
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
// map to your GSI Hash/Partition key
field: "gsi1pk",
composite: ["tenancyId"]
},
sk: {
// map to your GSI Range/Sort key
field: "gsi1sk",
composite: []
}
},
}
},
{ table: tableName, client }
);
/* Users Entity */
const apiKey = new Entity0(
{
model: {
entity: "apiKey",
service: "tenancy",
version: "1"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
apiKeyId: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.0',
},
token: {
type: "string",
required: true
},
createdAt: {
type: "number",
default: () => Date.now(),
readOnly: true
},
updatedAt: {
type: "number",
watch: "*",
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
composite: ["tenancyId"],
field: "pk"
},
sk: {
composite: ["token"],
field: "sk"
}
},
settings: {
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
composite: ["tenancyId"],
field: "gsi1pk"
},
sk: {
field: "gsi1sk",
composite: []
}
}
}
},
{ table: tableName, client }
);
return new Service0({ tenancy, apiKey });
}
function createOneService(tableName: string) {
/* Tasks Entity */
const tenancy = new Entity1(
{
model: {
entity: "tenancy",
version: "1",
service: "tenancy"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
name: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.1',
},
createdAt: {
type: "number",
default: () => Date.now(),
// cannot be modified after created
readOnly: true
},
updatedAt: {
type: "number",
// watch for changes to any attribute
watch: "*",
// set current timestamp when updated
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
field: "pk",
composite: ["tenancyId"]
},
sk: {
field: "sk",
// create composite keys for partial sort key queries
composite: []
}
},
settings: {
// collections allow for queries across multiple entities
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
// map to your GSI Hash/Partition key
field: "gsi1pk",
composite: ["tenancyId"]
},
sk: {
// map to your GSI Range/Sort key
field: "gsi1sk",
composite: []
}
},
}
},
{ table: tableName, client }
);
/* Users Entity */
const apiKey = new Entity1(
{
model: {
entity: "apiKey",
service: "tenancy",
version: "1"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
apiKeyId: {
type: "string",
required: true
},
token: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.1',
},
createdAt: {
type: "number",
default: () => Date.now(),
readOnly: true
},
updatedAt: {
type: "number",
watch: "*",
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
composite: ["tenancyId"],
field: "pk"
},
sk: {
composite: ["token"],
field: "sk"
}
},
settings: {
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
composite: ["tenancyId"],
field: "gsi1pk"
},
sk: {
field: "gsi1sk",
composite: []
}
}
}
},
{ table: tableName, client }
);
return new Service1({ tenancy, apiKey });
}
function createTwoService(tableName: string) {
/* Tasks Entity */
const tenancy = new Entity2(
{
model: {
entity: "tenancy",
version: "1",
service: "tenancy"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
name: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.2',
},
createdAt: {
type: "number",
default: () => Date.now(),
// cannot be modified after created
readOnly: true
},
updatedAt: {
type: "number",
// watch for changes to any attribute
watch: "*",
// set current timestamp when updated
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
field: "pk",
composite: ["tenancyId"]
},
sk: {
field: "sk",
// create composite keys for partial sort key queries
composite: []
}
},
settings: {
// collections allow for queries across multiple entities
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
// map to your GSI Hash/Partition key
field: "gsi1pk",
composite: ["tenancyId"]
},
sk: {
// map to your GSI Range/Sort key
field: "gsi1sk",
composite: []
}
},
}
},
{ table: tableName, client }
);
/* Users Entity */
const apiKey = new Entity2(
{
model: {
entity: "apiKey",
service: "tenancy",
version: "1"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
apiKeyId: {
type: "string",
required: true
},
token: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.2',
},
createdAt: {
type: "number",
default: () => Date.now(),
readOnly: true
},
updatedAt: {
type: "number",
watch: "*",
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
composite: ["tenancyId"],
field: "pk"
},
sk: {
composite: ["token"],
field: "sk"
}
},
settings: {
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
composite: ["tenancyId"],
field: "gsi1pk"
},
sk: {
field: "gsi1sk",
composite: []
}
}
}
},
{ table: tableName, client }
);
return new Service2({ tenancy, apiKey });
}
const createTable = async (table: string) => {
if (await manager.exists(table)) {
console.log('table already exists, dropping...');
await manager.drop(table);
console.log('table dropped');
}
console.log('creating table...');
await manager.create(table, {
"KeySchema": [
{
"AttributeName": "pk",
"KeyType": "HASH"
},
{
"AttributeName": "sk",
"KeyType": "RANGE"
}
],
"AttributeDefinitions": [
{
"AttributeName": "pk",
"AttributeType": "S"
},
{
"AttributeName": "sk",
"AttributeType": "S"
},
{
"AttributeName": "gsi1pk",
"AttributeType": "S"
},
{
"AttributeName": "gsi1sk",
"AttributeType": "S"
}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "gsi1pk-gsi1sk-index",
"KeySchema": [
{
"AttributeName": "gsi1pk",
"KeyType": "HASH"
},
{
"AttributeName": "gsi1sk",
"KeyType": "RANGE"
}
],
"Projection": {
"ProjectionType": "ALL"
}
},
],
"BillingMode": "PAY_PER_REQUEST"
});
console.log('table created');
}
type ZeroService = ReturnType<typeof createZeroService>;
type OneService = ReturnType<typeof createOneService>;
type TwoService = ReturnType<typeof createTwoService>;
type TestService = ZeroService | OneService | TwoService;
async function run(mainService: TestService, otherServices: TestService[]) {
const tenancyId = 'myTenancyId';
const apiKeyId = 'myApiKeyId';
await mainService.entities.apiKey.put({ tenancyId, apiKeyId, token: 'myApiKey' }).go();
await mainService.entities.tenancy.put({ tenancyId, name: 'my tenancy' }).go();
const params = [
mainService.collections.settings({ tenancyId }).params(),
...otherServices.map(service => service.collections.settings({ tenancyId }).params())
]
const query = await Promise.all([
mainService.collections.settings({ tenancyId }).go(),
...otherServices.map(service => service.collections.settings({ tenancyId }).go())
]);
return {
params,
query,
};
}
function createServices(tablename: string) {
return {
zeroService: createZeroService(tablename),
oneService: createOneService(tablename),
twoService: createTwoService(tablename)
}
}
async function main() {
const table = "issuefivefourzero";
const services = createServices(table);
const testCases = [
{
description: 'create items with 3.5.0, query with 3.5.0, 3.5.1, 3.5.2',
mainService: services.zeroService,
otherServices: [services.oneService, services.twoService],
},
{
description: 'create items with 3.5.1, query with 3.5.0, 3.5.1, 3.5.2',
mainService: services.oneService,
otherServices: [services.zeroService, services.twoService],
},
{
description: 'create items with 3.5.2, query with 3.5.0, 3.5.1, 3.5.2',
mainService: services.twoService,
otherServices: [services.zeroService, services.oneService],
},
]
for (const testCase of testCases) {
await createTable(table);
console.log(`Running test case: ${testCase.description}`);
const results = await run(testCase.mainService, testCase.otherServices);
expect(results.params.length).to.equal(3);
expect(results.query.length).to.equal(3);
for (let i = 0; i < 3; i++) {
const leftParam = results.params[i];
const leftQuery = results.query[i];
for (let j = i + 1; j < 3; j++) {
const rightParam = results.params[j];
const rightQuery = results.query[j];
expect(leftParam).to.deep.equal(rightParam);
expect(leftQuery).to.deep.equal(rightQuery);
}
}
console.log('test case passed');
}
}
main().catch(console.error);
// THIS FILE USES THE A VARITION MODELS SPECIFIED IN THE PROVIDED PLAYGROUND: UNQUIE SORT KEY COMPOSITE ATTRIBUTES BETWEEN THE TENANCY AND APIKEY ENTITIES
import { Entity as Entity0, Service as Service0 } from "threedotfivedotone";
import { Entity as Entity1, Service as Service1 } from "threedotfivedotzero";
import { Entity as Entity2, Service as Service2 } from "threedotfivedottwo";
import { DynamoDB } from "aws-sdk";
import { expect } from "chai";
const dynamodb = new DynamoDB({
region: "us-east-1",
endpoint: "http://localhost:8000",
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
});
const manager = {
async exists(tableName: string) {
let tables = await dynamodb.listTables().promise();
return !!(tables.TableNames || []).includes(tableName);
},
async drop(tableName: string) {
return dynamodb.deleteTable({ TableName: tableName }).promise();
},
async create(tableName: string, tableDefinition: any) {
return dynamodb
.createTable({ ...tableDefinition, TableName: tableName })
.promise();
},
};
const client = new DynamoDB.DocumentClient({
region: "us-east-1",
endpoint: "http://localhost:8000",
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
});
function createZeroService(tableName: string) {
/* Tasks Entity */
const tenancy = new Entity0(
{
model: {
entity: "tenancy",
version: "1",
service: "tenancy"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
name: {
type: "string",
required: true
},
tenancyField: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.0',
},
createdAt: {
type: "number",
default: () => Date.now(),
// cannot be modified after created
readOnly: true
},
updatedAt: {
type: "number",
// watch for changes to any attribute
watch: "*",
// set current timestamp when updated
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
field: "pk",
composite: ["tenancyId"]
},
sk: {
field: "sk",
// create composite keys for partial sort key queries
composite: []
}
},
settings: {
// collections allow for queries across multiple entities
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
// map to your GSI Hash/Partition key
field: "gsi1pk",
composite: ["tenancyId"]
},
sk: {
// map to your GSI Range/Sort key
field: "gsi1sk",
composite: ["tenancyField"]
}
},
}
},
{ table: tableName, client }
);
/* Users Entity */
const apiKey = new Entity0(
{
model: {
entity: "apiKey",
service: "tenancy",
version: "1"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
apiKeyId: {
type: "string",
required: true
},
apiKeyField: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.0',
},
token: {
type: "string",
required: true
},
createdAt: {
type: "number",
default: () => Date.now(),
readOnly: true
},
updatedAt: {
type: "number",
watch: "*",
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
composite: ["tenancyId"],
field: "pk"
},
sk: {
composite: ["token"],
field: "sk"
}
},
settings: {
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
composite: ["tenancyId"],
field: "gsi1pk"
},
sk: {
field: "gsi1sk",
composite: ["apiKeyField"]
}
}
}
},
{ table: tableName, client }
);
return new Service0({ tenancy, apiKey });
}
function createOneService(tableName: string) {
/* Tasks Entity */
const tenancy = new Entity1(
{
model: {
entity: "tenancy",
version: "1",
service: "tenancy"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
name: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.1',
},
tenancyField: {
type: "string",
required: true
},
createdAt: {
type: "number",
default: () => Date.now(),
// cannot be modified after created
readOnly: true
},
updatedAt: {
type: "number",
// watch for changes to any attribute
watch: "*",
// set current timestamp when updated
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
field: "pk",
composite: ["tenancyId"]
},
sk: {
field: "sk",
// create composite keys for partial sort key queries
composite: []
}
},
settings: {
// collections allow for queries across multiple entities
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
// map to your GSI Hash/Partition key
field: "gsi1pk",
composite: ["tenancyId"]
},
sk: {
// map to your GSI Range/Sort key
field: "gsi1sk",
composite: ["tenancyField"]
}
},
}
},
{ table: tableName, client }
);
/* Users Entity */
const apiKey = new Entity1(
{
model: {
entity: "apiKey",
service: "tenancy",
version: "1"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
apiKeyId: {
type: "string",
required: true
},
apiKeyField: {
type: "string",
required: true
},
token: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.1',
},
createdAt: {
type: "number",
default: () => Date.now(),
readOnly: true
},
updatedAt: {
type: "number",
watch: "*",
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
composite: ["tenancyId"],
field: "pk"
},
sk: {
composite: ["token"],
field: "sk"
}
},
settings: {
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
composite: ["tenancyId"],
field: "gsi1pk"
},
sk: {
field: "gsi1sk",
composite: ["apiKeyField"]
}
}
}
},
{ table: tableName, client }
);
return new Service1({ tenancy, apiKey });
}
function createTwoService(tableName: string) {
/* Tasks Entity */
const tenancy = new Entity2(
{
model: {
entity: "tenancy",
version: "1",
service: "tenancy"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
name: {
type: "string",
required: true
},
tenancyField: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.2',
},
createdAt: {
type: "number",
default: () => Date.now(),
// cannot be modified after created
readOnly: true
},
updatedAt: {
type: "number",
// watch for changes to any attribute
watch: "*",
// set current timestamp when updated
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
field: "pk",
composite: ["tenancyId"]
},
sk: {
field: "sk",
// create composite keys for partial sort key queries
composite: []
}
},
settings: {
// collections allow for queries across multiple entities
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
// map to your GSI Hash/Partition key
field: "gsi1pk",
composite: ["tenancyId"]
},
sk: {
// map to your GSI Range/Sort key
field: "gsi1sk",
composite: ["tenancyField"]
}
},
}
},
{ table: tableName, client }
);
/* Users Entity */
const apiKey = new Entity2(
{
model: {
entity: "apiKey",
service: "tenancy",
version: "1"
},
attributes: {
tenancyId: {
type: "string",
required: true
},
apiKeyId: {
type: "string",
required: true
},
token: {
type: "string",
required: true
},
apiKeyField: {
type: "string",
required: true
},
version: {
type: "string",
default: () => '3.5.2',
},
createdAt: {
type: "number",
default: () => Date.now(),
readOnly: true
},
updatedAt: {
type: "number",
watch: "*",
set: () => Date.now(),
readOnly: true
}
},
indexes: {
primary: {
pk: {
composite: ["tenancyId"],
field: "pk"
},
sk: {
composite: ["token"],
field: "sk"
}
},
settings: {
collection: "settings",
index: "gsi1pk-gsi1sk-index",
pk: {
composite: ["tenancyId"],
field: "gsi1pk"
},
sk: {
field: "gsi1sk",
composite: ["apiKeyField"]
}
}
}
},
{ table: tableName, client }
);
return new Service2({ tenancy, apiKey });
}
const createTable = async (table: string) => {
if (await manager.exists(table)) {
console.log('table already exists, dropping...');
await manager.drop(table);
console.log('table dropped');
}
console.log('creating table...');
await manager.create(table, {
"KeySchema": [
{
"AttributeName": "pk",
"KeyType": "HASH"
},
{
"AttributeName": "sk",
"KeyType": "RANGE"
}
],
"AttributeDefinitions": [
{
"AttributeName": "pk",
"AttributeType": "S"
},
{
"AttributeName": "sk",
"AttributeType": "S"
},
{
"AttributeName": "gsi1pk",
"AttributeType": "S"
},
{
"AttributeName": "gsi1sk",
"AttributeType": "S"
}
],
"GlobalSecondaryIndexes": [
{
"IndexName": "gsi1pk-gsi1sk-index",
"KeySchema": [
{
"AttributeName": "gsi1pk",
"KeyType": "HASH"
},
{
"AttributeName": "gsi1sk",
"KeyType": "RANGE"
}
],
"Projection": {
"ProjectionType": "ALL"
}
},
],
"BillingMode": "PAY_PER_REQUEST"
});
console.log('table created');
}
type ZeroService = ReturnType<typeof createZeroService>;
type OneService = ReturnType<typeof createOneService>;
type TwoService = ReturnType<typeof createTwoService>;
type TestService = ZeroService | OneService | TwoService;
async function run(mainService: TestService, otherServices: TestService[]) {
const tenancyId = 'myTenancyId';
const apiKeyId = 'myApiKeyId';
await mainService.entities.apiKey.put({ tenancyId, apiKeyId, token: 'myApiKey', apiKeyField: 'myApiKeyField' }).go();
await mainService.entities.tenancy.put({ tenancyId, name: 'my tenancy', tenancyField: 'myTenancyField' }).go();
const params = [
mainService.collections.settings({ tenancyId }).params(),
...otherServices.map(service => service.collections.settings({ tenancyId }).params())
]
const query = await Promise.all([
mainService.collections.settings({ tenancyId }).go(),
...otherServices.map(service => service.collections.settings({ tenancyId }).go())
]);
return {
params,
query,
};
}
function createServices(tablename: string) {
return {
zeroService: createZeroService(tablename),
oneService: createOneService(tablename),
twoService: createTwoService(tablename)
}
}
async function main() {
const table = "issuefivefourzero";
const services = createServices(table);
const testCases = [
{
description: 'create items with 3.5.0, query with 3.5.0, 3.5.1, 3.5.2',
mainService: services.zeroService,
otherServices: [services.oneService, services.twoService],
},
{
description: 'create items with 3.5.1, query with 3.5.0, 3.5.1, 3.5.2',
mainService: services.oneService,
otherServices: [services.zeroService, services.twoService],
},
{
description: 'create items with 3.5.2, query with 3.5.0, 3.5.1, 3.5.2',
mainService: services.twoService,
otherServices: [services.zeroService, services.oneService],
},
]
for (const testCase of testCases) {
await createTable(table);
console.log(`Running test case: ${testCase.description}`);
const results = await run(testCase.mainService, testCase.otherServices);
expect(results.params.length).to.equal(3);
expect(results.query.length).to.equal(3);
for (let i = 0; i < 3; i++) {
const leftParam = results.params[i];
const leftQuery = results.query[i];
for (let j = i + 1; j < 3; j++) {
const rightParam = results.params[j];
const rightQuery = results.query[j];
expect(leftParam).to.deep.equal(rightParam);
expect(leftQuery).to.deep.equal(rightQuery);
}
}
console.log('test case passed');
}
}
main().catch(console.error);
{
"name": "issue-540",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "ts-node ./src/index.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"dependencies": {
"@types/aws-sdk": "^0.0.42",
"aws-sdk": "^2.1693.0",
"threedotfivedotone": "npm:electrodb@^3.5.1",
"threedotfivedottwo": "npm:electrodb@^3.5.2",
"threedotfivedotzero": "npm:electrodb@^3.5.0",
"ts-node": "^10.9.2",
"typescript": "^5.9.3"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment