Skip to content

Commit

Permalink
Use strict typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
mtranter committed Mar 1, 2023
1 parent dd2b7f3 commit ed34ac3
Show file tree
Hide file tree
Showing 8 changed files with 666 additions and 521 deletions.
45 changes: 36 additions & 9 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": { "project": "./tsconfig.json" },
"env": { "es6": true },
"ignorePatterns": ["node_modules", "build", "coverage"],
"plugins": ["import", "eslint-comments", "functional"],
"parserOptions": {
"project": "./tsconfig.json"
},
"env": {
"es6": true
},
"ignorePatterns": [
"node_modules",
"build",
"coverage"
],
"plugins": [
"import",
"eslint-comments",
"functional"
],
"extends": [
"eslint:recommended",
"plugin:eslint-comments/recommended",
Expand All @@ -14,21 +26,36 @@
"prettier",
"prettier/@typescript-eslint"
],
"globals": { "BigInt": true, "console": true, "WebAssembly": true },
"globals": {
"BigInt": true,
"console": true,
"WebAssembly": true
},
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"eslint-comments/disable-enable-pair": [
"error",
{ "allowWholeFile": true }
{
"allowWholeFile": true
}
],
"eslint-comments/no-unused-disable": "error",
"import/order": [
"error",
{ "newlines-between": "always", "alphabetize": { "order": "asc" } }
{
"newlines-between": "always",
"alphabetize": {
"order": "asc"
}
}
],
"sort-imports": [
"error",
{ "ignoreDeclarationSort": true, "ignoreCase": true }
{
"ignoreDeclarationSort": true,
"ignoreCase": true
}
]
}
}
}
21 changes: 12 additions & 9 deletions src/lib/conditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const comparatorOperators: DyanmoCompareOperator[] = [
'<>',
];

const isComparator = <V>(a: unknown): a is Comparator<V> => {
const isComparator = <V>(a: {}): a is Comparator<V> => {
const keys = Object.keys(a);
return (
keys.length === 1 &&
Expand Down Expand Up @@ -205,8 +205,9 @@ const serializeComparator = (
attributes: ExpressionAttributes
) => `${Object.keys(c)[0]} ${attributes.addValue(Object.values(c)[0])}`;

const _serializeConditionExpression = <A>(
expression: ConditionExpression<A>,
const _serializeConditionExpression = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expression: ConditionExpression<any>,
attributes: ExpressionAttributes,
path: AttributePath,
combinator = 'AND'
Expand Down Expand Up @@ -245,8 +246,9 @@ const _serializeConditionExpression = <A>(
...path.elements,
{ type: 'AttributeName' as const, name: key },
]);
const queryObject = expression as ConditionObject<A>;
const operator = queryObject[key as keyof A];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const queryObject = expression as ConditionObject<any>;
const operator = queryObject[key];
if (isBetweenFunction(operator)) {
return `${attributes.addName(
attributePath
Expand All @@ -259,7 +261,7 @@ const _serializeConditionExpression = <A>(
)} in (${operator.values
.map((a) => attributes.addValue(a))
.join(', ')})`;
} else if (isComparator(operator)) {
} else if (!!operator && isComparator(operator)) {
return `${attributes.addName(attributePath)} ${serializeComparator(
operator,
attributes
Expand Down Expand Up @@ -291,9 +293,10 @@ const _serializeConditionExpression = <A>(
}
};

export const serializeConditionExpression = <A>(
expression: ConditionExpression<A>,
export const serializeConditionExpression = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expression: ConditionExpression<any>,
attributes: ExpressionAttributes
) =>
): string | undefined =>
expression &&
_serializeConditionExpression(expression, attributes, new AttributePath([]));
5 changes: 2 additions & 3 deletions src/lib/marshalling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const marshaller = new Marshaller({
});

export type DynamoMarshallerFor<T extends DynamoObject> = {
readonly [k in keyof T]: DynamoMarshaller<T[k]>;
readonly [k in keyof T]-?: DynamoMarshaller<T[k]>;
};

const buildMarshaller: <T extends DynamoPrimitive>(
Expand Down Expand Up @@ -56,8 +56,7 @@ export const Marshallers = {
arrayBufferView: buildMarshaller<ArrayBufferView>(),
};

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const marshall = <TT, _T extends DynamoObject & TT>(t: TT) =>
export const marshall = <TT, _T extends DynamoObject & TT>(t: _T) =>
marshaller.marshallItem(t);
export const unmarshall = <T extends DynamoObject>(
schema: DynamoMarshallerFor<T>,
Expand Down
57 changes: 36 additions & 21 deletions src/lib/table-builder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable functional/no-method-signature */
import { MarshallingOptions } from '@aws/dynamodb-auto-marshaller';
import { DynamoDB } from 'aws-sdk';
Expand All @@ -17,8 +16,8 @@ export type Logger = {

export type IndexDefinition<
T extends DynamoObject,
PartitionKey extends string & keyof T = never,
SortKey extends string & keyof T = never
PartitionKey extends string & keyof T,
SortKey extends string & keyof T
> = {
readonly name: Name;
readonly partitionKey: PartitionKey;
Expand All @@ -30,7 +29,10 @@ export type IndexDefinition<
export type IndexDefinitions = Record<string, IndexDefinition<any, any, any>>;

type WithKey<T extends DynamoObject> = {
withKey<PK extends string & keyof T, SK extends string & keyof T = undefined>(
withKey<
PK extends string & keyof T,
SK extends (string & keyof T) | undefined = undefined
>(
pk: PK,
sk?: SK
): TableBuilder<T, PK, SK, {}>;
Expand All @@ -39,13 +41,13 @@ type WithKey<T extends DynamoObject> = {
type WithIndexes<
T extends DynamoObject,
PartitionKey extends string & keyof T,
SortKey extends string & keyof T,
SortKey extends (string & keyof T) | undefined,
Ixs extends IndexDefinitions
> = {
withGlobalIndex<
IxName extends Name,
PK extends string & Exclude<keyof T, PartitionKey> = never,
SK extends string & keyof T = never
PK extends string & Exclude<keyof T, PartitionKey>,
SK extends string & keyof T
>(
ixName: IxName,
pk: PK,
Expand Down Expand Up @@ -78,8 +80,8 @@ export type DynamodbTableConfig = MarshallingOptions &
};
type Build<
T extends DynamoObject,
PartitionKey extends string & keyof T = never,
SortKey extends string & keyof T = never,
PartitionKey extends string & keyof T,
SortKey extends (string & keyof T) | undefined,
Ixs extends IndexDefinitions = {}
> = {
readonly build: (
Expand All @@ -89,13 +91,13 @@ type Build<

export type TableBuilder<
T extends DynamoObject,
PartitionKey extends string & keyof T = undefined,
SortKey extends string & keyof T = undefined,
PartitionKey extends string & keyof T,
SortKey extends (string & keyof T) | undefined = undefined,
Ixs extends IndexDefinitions = {}
> = {} & (PartitionKey extends undefined ? WithKey<T> : {}) &
(SortKey extends undefined
? {}
: WithIndexes<T, PartitionKey, SortKey, Ixs>) &
: WithIndexes<T, PartitionKey, Exclude<SortKey, undefined>, Ixs>) &
(PartitionKey extends undefined ? {} : Build<T, PartitionKey, SortKey, Ixs>);

export type TableDefinition<
Expand All @@ -113,25 +115,38 @@ export type TableDefinition<
const _tableBuilder = <
T extends DynamoObject,
PartitionKey extends string & keyof T,
SortKey extends string & keyof T,
SortKey extends (string & keyof T) | undefined,
Ixs extends IndexDefinitions = {}
>(
tableDefinition: TableDefinition<T, PartitionKey, SortKey, Ixs>
): TableBuilder<T, PartitionKey, SortKey, Ixs> => {
const withKey: WithKey<T> = {
withKey: (pk, sk) =>
_tableBuilder<T, typeof pk, typeof sk>({
withKey: <
PK extends string & keyof T,
SK extends (string & keyof T) | undefined = undefined
>(
pk: PK,
sk?: SK
) =>
_tableBuilder<T, PK, SK>({
...tableDefinition,
...{ partitionKey: pk, sortKey: sk },
}),
};
const build: Build<T, PartitionKey, SortKey, Ixs> = {
build: (cfg) => Table<T, PartitionKey, SortKey, Ixs>(tableDefinition, cfg),
build: (cfg) =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Table(tableDefinition as any, cfg) as TableFactoryResult<
T,
PartitionKey,
SortKey,
Ixs
>,
};

const withIndex: WithIndexes<T, PartitionKey, SortKey, Ixs> = {
withGlobalIndex: (name, pk, sk) =>
_tableBuilder({
_tableBuilder<T, PartitionKey, SortKey, Ixs>({
...tableDefinition,
indexes: {
...tableDefinition.indexes,
Expand All @@ -146,7 +161,7 @@ const _tableBuilder = <
},
}),
withLocalIndex: (name, sk) =>
_tableBuilder({
_tableBuilder<T, PartitionKey, SortKey, Ixs>({
...tableDefinition,
indexes: {
...tableDefinition.indexes,
Expand All @@ -171,9 +186,9 @@ const _tableBuilder = <

export const tableBuilder = <T extends DynamoObject>(
name: string
): TableBuilder<T, undefined, undefined, {}> =>
_tableBuilder<T, undefined, undefined>({
): WithKey<T> =>
_tableBuilder<T, keyof T & string, never>({
name,
partitionKey: undefined,
partitionKey: undefined as never,
indexes: {},
});
27 changes: 15 additions & 12 deletions src/lib/table.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { DynamoDB } from 'aws-sdk';

Expand All @@ -12,7 +11,7 @@ import {
OR,
} from './conditions';
import { Marshallers } from './marshalling';
import { ifNotExists, QueryableTable } from './table';
import { ifNotExists, QueryableTable, Table } from './table';
import { IndexDefinition, tableBuilder } from './table-builder';

jest.setTimeout(60000); // in milliseconds
Expand Down Expand Up @@ -64,19 +63,19 @@ describe('Table', () => {
.describeTable({ TableName: tableName })
.promise();
expect(described.Table).toBeTruthy();
expect(described.Table.TableName).toEqual(tableName);
expect(described.Table.KeySchema).toEqual([
expect(described?.Table?.TableName).toEqual(tableName);
expect(described?.Table?.KeySchema).toEqual([
{ AttributeName: 'hash', KeyType: 'HASH' },
{ AttributeName: 'sort', KeyType: 'RANGE' },
]);
expect(described.Table.AttributeDefinitions).toEqual([
expect(described?.Table?.AttributeDefinitions).toEqual([
{ AttributeName: 'hash', AttributeType: 'S' },
{ AttributeName: 'sort', AttributeType: 'N' },
{ AttributeName: 'lsiSort', AttributeType: 'N' },
{ AttributeName: 'gsiHash', AttributeType: 'S' },
{ AttributeName: 'gsiSort', AttributeType: 'N' },
]);
expect(described.Table.GlobalSecondaryIndexes).toMatchObject([
expect(described?.Table?.GlobalSecondaryIndexes).toMatchObject([
{
IndexName: 'gsi1',
KeySchema: [
Expand All @@ -86,7 +85,7 @@ describe('Table', () => {
Projection: { ProjectionType: 'ALL' },
},
]);
expect(described.Table.LocalSecondaryIndexes).toMatchObject([
expect(described?.Table?.LocalSecondaryIndexes).toMatchObject([
{
IndexName: 'lsi1',
KeySchema: [
Expand All @@ -108,7 +107,7 @@ describe('Table', () => {
readonly age?: number;
};
// eslint-disable-next-line functional/no-let
let simpleTable: QueryableTable<SimpleKey, 'hash', undefined, {}>;
let simpleTable: Table<SimpleKey, 'hash', never, {}>;

beforeEach(async () => {
const randomTableName = `SimpleTable${randomAlphaNumeric(9)}`;
Expand Down Expand Up @@ -259,7 +258,11 @@ describe('Table', () => {
const result = await simpleTable.get(key, {
marshaller: {
hash: Marshallers.string,
name: Marshallers.string,
name: Marshallers.string.optional(),
age: Marshallers.number.optional(),
map: Marshallers.map({
name: Marshallers.string,
}).optional(),
},
});
expect(result).toEqual(key);
Expand Down Expand Up @@ -422,7 +425,7 @@ describe('Table', () => {
});
};
it('Should get selected keys', async () => {
const result = await setup();
const result: any = await setup();
expect(result?.gsihash).toEqual(key.gsihash);
expect(result?.sort).toEqual(key.sort);
expect(result?.complexSubDoc.subSubDoc.id).toEqual('123');
Expand Down Expand Up @@ -605,7 +608,7 @@ describe('Table', () => {
expect(result.records.length).toBe(11);
expect(
result.records.every(
(r) =>
(r: any) =>
r.lsirange === 5 ||
r.name === 'Fred' ||
!(7 > r.lsirange && r.lsirange > 13)
Expand Down Expand Up @@ -686,7 +689,7 @@ describe('Table', () => {
sortKeyExpression: { '>': 5 },
});
expect(
[...result.records].sort((a, b) => a.lsirange - b.lsirange)
[...result.records].sort((a: any, b: any) => a.lsirange - b.lsirange)
).toEqual(
[...testObjects.filter((a) => a.lsirange > 5)].sort(
(a, b) => a.lsirange - b.lsirange
Expand Down
Loading

0 comments on commit ed34ac3

Please sign in to comment.