Skip to content

Commit

Permalink
remove relationships and fields items from EntitySchema (#61)
Browse files Browse the repository at this point in the history
* remove `relationships` field

* remove `fields` field from schema
  • Loading branch information
tantaman authored Apr 8, 2024
1 parent 8e2384f commit 46d3d6b
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 77 deletions.
2 changes: 1 addition & 1 deletion src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export function generate<T extends Entity>(
listIDsImpl(keyFromID, keyToID, firstKey, tx, options),
listEntries: (tx, options?) =>
listEntriesImpl(keyFromID, keyToID, firstKey, parse, tx, options),
// query: () => new QueryInstance<{fields: T}>(),
// query: () => new QueryInstance<T>(),
};
}

Expand Down
8 changes: 4 additions & 4 deletions src/zql/ast-to-ivm/pipeline-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type E1 = z.infer<typeof e1>;
const context = makeTestContext();
const comparator = (l: E1, r: E1) => compareUTF8(l.id, r.id);
test('A simple select', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');
const m = new Materialite();
let s = m.newSetSource<E1>(comparator);
let pipeline = buildPipeline(
Expand Down Expand Up @@ -69,7 +69,7 @@ test('A simple select', () => {
});

test('Count', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');
const m = new Materialite();
const s = m.newSetSource<E1>(comparator);
const pipeline = buildPipeline(
Expand Down Expand Up @@ -99,7 +99,7 @@ test('Count', () => {
});

test('Where', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');
const m = new Materialite();
const s = m.newSetSource<E1>(comparator);
const pipeline = buildPipeline(
Expand Down Expand Up @@ -133,7 +133,7 @@ describe('OR', () => {

type Case = {
name?: string | undefined;
where: WhereCondition<{fields: E}>;
where: WhereCondition<E>;
values?: (E | DeleteE)[] | undefined;
expected: (E | [v: E, multiplicity: number])[];
};
Expand Down
2 changes: 1 addition & 1 deletion src/zql/context/replicache-context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ test('ZQL query with Replicache', async () => {
const r = newRep();
const context = makeReplicacheContext(r);

const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

const view = q.select('id').where('str', '>', 'm').prepare().view();

Expand Down
6 changes: 5 additions & 1 deletion src/zql/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function sampleTenUniqueIssues() {
function setup() {
const r = newRep();
const c = makeReplicacheContext(r);
const q = new EntityQuery<{fields: Issue}>(c, 'issue');
const q = new EntityQuery<Issue>(c, 'issue');
return {r, c, q};
}

Expand Down Expand Up @@ -335,6 +335,7 @@ test('order by single field', async () => {
await r.close();
}
}),
{interruptAfterTimeLimit: 4000},
);
});

Expand All @@ -350,6 +351,7 @@ test('order by id', async () => {

await r.close();
}),
{interruptAfterTimeLimit: 4000},
);
});

Expand All @@ -373,6 +375,7 @@ test('order by compound fields', async () => {

await r.close();
}),
{interruptAfterTimeLimit: 4000},
);
});

Expand All @@ -391,6 +394,7 @@ test('order by optional field', async () => {

await r.close();
}),
{interruptAfterTimeLimit: 4000},
);
});

Expand Down
52 changes: 22 additions & 30 deletions src/zql/query/entity-query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ test('query types', () => {
[sym]: boolean;
};

const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

// @ts-expect-error - selecting fields that do not exist in the schema is a type error
q.select('does-not-exist');
Expand Down Expand Up @@ -123,15 +123,13 @@ test('query types', () => {

test('FieldValue type', () => {
type E = {
fields: {
id: string;
n: number;
s: string;
b: boolean;
optN?: number | undefined;
optS?: string | undefined;
optB?: boolean | undefined;
};
id: string;
n: number;
s: string;
b: boolean;
optN?: number | undefined;
optS?: string | undefined;
optB?: boolean | undefined;
};
expectTypeOf<FieldValue<E, 'id', '='>>().toEqualTypeOf<string>();
expectTypeOf<FieldValue<E, 'n', '='>>().toEqualTypeOf<number>();
Expand Down Expand Up @@ -251,7 +249,7 @@ const dummyObject: E1 = {
};
describe('ast', () => {
test('select', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

// each individual field is selectable on its own
Object.keys(dummyObject).forEach(k => {
Expand Down Expand Up @@ -282,7 +280,7 @@ describe('ast', () => {
});

test('where', () => {
let q = new EntityQuery<{fields: E1}>(context, 'e1');
let q = new EntityQuery<E1>(context, 'e1');

// where is applied
q = q.where('id', '=', 'a');
Expand Down Expand Up @@ -367,7 +365,7 @@ describe('ast', () => {
});

test('limit', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');
expect(ast(q.limit(10))).toEqual({
orderBy: [['id'], 'asc'],
table: 'e1',
Expand All @@ -376,7 +374,7 @@ describe('ast', () => {
});

test('asc/desc', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

// order methods update the ast
expect(ast(q.asc('id'))).toEqual({
Expand All @@ -394,7 +392,7 @@ describe('ast', () => {
});

test('independent of method call order', () => {
const base = new EntityQuery<{fields: E1}>(context, 'e1');
const base = new EntityQuery<E1>(context, 'e1');

const calls = {
select(q: typeof base) {
Expand Down Expand Up @@ -433,7 +431,7 @@ describe('ast', () => {
});

test('or', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

expect(
ast(q.where(or(expression('a', '=', 123), expression('c', '=', 'abc')))),
Expand Down Expand Up @@ -478,9 +476,7 @@ describe('ast', () => {
});

test('flatten ands', () => {
type S = {
fields: {id: string; a: number; b: string; c: boolean; d: string};
};
type S = {id: string; a: number; b: string; c: boolean; d: string};

expect(
and<S>(
Expand Down Expand Up @@ -543,9 +539,7 @@ describe('ast', () => {
});

test('flatten ors', () => {
type S = {
fields: {id: string; a: number; b: string; c: boolean; d: string};
};
type S = {id: string; a: number; b: string; c: boolean; d: string};

expect(
or<S>(
Expand All @@ -564,7 +558,7 @@ describe('ast', () => {
});

test('consecutive wheres/ands should be merged', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

expect(
ast(
Expand Down Expand Up @@ -699,7 +693,7 @@ describe('ast', () => {
});

test('consecutive ors', () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

expect(
ast(q.where(or(expression('a', '=', 123), expression('a', '=', 456))))
Expand Down Expand Up @@ -804,7 +798,7 @@ describe('NOT', () => {

for (const c of cases) {
test(`${c.in} -> ${c.out}`, () => {
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');
expect(ast(q.where(not(expression('a', c.in, 1)))).where).toEqual({
op: c.out,
field: 'a',
Expand All @@ -817,11 +811,9 @@ describe('NOT', () => {

describe("De Morgan's Law", () => {
type S = {
fields: {
id: string;
n: number;
s: string;
};
id: string;
n: number;
s: string;
};

const cases: {
Expand Down
32 changes: 12 additions & 20 deletions src/zql/query/entity-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,35 @@ export type FieldValue<
S extends EntitySchema,
K extends Selectable<S>,
Op extends SimpleOperator,
> = S['fields'][K] extends Primitive | undefined
> = S[K] extends Primitive | undefined
? Op extends InOps
? NotUndefined<S['fields'][K]>[]
? NotUndefined<S[K]>[]
: Op extends LikeOps
? S['fields'][K] extends string | undefined
? NotUndefined<S['fields'][K]>
? S[K] extends string | undefined
? NotUndefined<S[K]>
: never
: Op extends OrderOps
? S['fields'][K] extends boolean | undefined
? S[K] extends boolean | undefined
? never
: NotUndefined<S['fields'][K]>
: NotUndefined<S[K]>
: Op extends EqualityOps
? NotUndefined<S['fields'][K]>
? NotUndefined<S[K]>
: never
: never;

type AggregateValue<S extends EntitySchema, K extends Aggregable<S>> =
K extends Count<string>
? number
: K extends AggArray<string, string>
? S['fields'][K['field']][]
? S[K['field']][]
: K extends Exclude<Aggregable<S>, Count<string>>
? S['fields'][K['field']]
? S[K['field']]
: never;

export type SelectedFields<
S extends EntitySchema,
Fields extends Selectable<EntitySchema>[],
> = Pick<
S['fields'],
Fields[number] extends keyof S['fields'] ? Fields[number] : never
>;
> = Pick<S, Fields[number] extends keyof S ? Fields[number] : never>;

type SelectedAggregates<
S extends EntitySchema,
Expand All @@ -67,14 +64,9 @@ type SelectedAggregates<

type AsString<T> = T extends string ? T : never;

export type Selectable<S extends EntitySchema> =
| AsString<keyof S['fields']>
| 'id';
export type Selectable<S extends EntitySchema> = AsString<keyof S> | 'id';

type Aggregable<S extends EntitySchema> = Aggregate<
AsString<keyof S['fields']>,
string
>;
type Aggregable<S extends EntitySchema> = Aggregate<AsString<keyof S>, string>;

type ToSelectableOnly<T, S extends EntitySchema> = T extends (infer U)[]
? U extends Selectable<S>
Expand Down
8 changes: 4 additions & 4 deletions src/zql/query/statement.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const e1 = z.object({
type E1 = z.infer<typeof e1>;
test('basic materialization', () => {
const context = makeTestContext();
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

const stmt = q.select('id', 'n').where('n', '>', 100).prepare();

Expand Down Expand Up @@ -43,7 +43,7 @@ test('basic materialization', () => {
test('sorted materialization', () => {
const context = makeTestContext();
type E1 = z.infer<typeof e1>;
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');
const ascView = q.select('id').asc('n').prepare().view();
const descView = q.select('id').desc('n').prepare().view();

Expand All @@ -67,7 +67,7 @@ test('sorted materialization', () => {
test('sorting is stable via suffixing the primary key to the order', () => {
const context = makeTestContext();
type E1 = z.infer<typeof e1>;
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

const ascView = q.select('id').asc('n').prepare().view();
const descView = q.select('id').desc('n').prepare().view();
Expand Down Expand Up @@ -115,7 +115,7 @@ test('ascComparator', () => {

test('destroying the statement stops updating the view', async () => {
const context = makeTestContext();
const q = new EntityQuery<{fields: E1}>(context, 'e1');
const q = new EntityQuery<E1>(context, 'e1');

const stmt = q.select('id', 'n').prepare();

Expand Down
17 changes: 1 addition & 16 deletions src/zql/schema/entity-schema.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
export type Relationship<Src extends EntitySchema, Dst extends EntitySchema> = {
src: Src;
srcField: keyof Src['fields'];
dst: Dst;
dstField: keyof Dst['fields'];
};

export type Relationships = {
[key: string]: Relationship<EntitySchema, EntitySchema>;
};
export type Fields = {
export type EntitySchema = {
id: string;
} & {
[key: string]: unknown;
};

export interface EntitySchema {
readonly fields: Fields;
readonly relationships?: Relationships;
}

0 comments on commit 46d3d6b

Please sign in to comment.