Created
February 7, 2023 21:26
-
-
Save onlybakam/fd68e5d0d192a7e0a2822d960067a6fe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
util, | |
DynamoDBGetItem, | |
DynamoDBExpression, | |
DynamoDBPutItemRequest, | |
DynamoDBUpdateItemRequest, | |
DynamoDBDeleteItemRequest, | |
LambdaRequest, | |
Context as _Context, | |
DynamoDBQueryRequest, | |
} from '@aws-appsync/utils' | |
export type ExpressionOperation<T> = | |
| { [k in 'contains' | 'notContains']?: T } | |
| { beginsWith: T } | |
| { attributeType: 'S' | 'SS' } | |
| { [k in 'eq' | 'ne' | 'gt' | 'ge' | 'lt' | 'le']?: T } | |
| { in?: T[] } | |
| { between?: [T, T] } | |
| { [k in 'attributeExists']: Boolean } | |
export type Expression<T> = { | |
[k in keyof T]?: ExpressionOperation<T[k]> | |
} & { | |
and?: Expression<T> | Expression<T>[] | |
or?: Expression<T> | Expression<T>[] | |
not?: Expression<T> | |
} | |
// type Todo = { | |
// id: string | |
// title: string | |
// upvotes?: number | |
// downvotes?: number | |
// percentageUp?: number | |
// value?: number | |
// isPublished?: boolean | |
// } | |
// const x: Expression<Todo> = { | |
// title: { contains: 'hihihi' }, | |
// upvotes: { eq: 5 }, | |
// downvotes: { eq: 1 }, | |
// percentageUp: { in: [77.7, 88.8] }, | |
// and: [ | |
// { isPublished: { eq: true } }, | |
// { | |
// percentageUp: { contains: 90.5 }, | |
// upvotes: { gt: 10 }, | |
// }, | |
// ], | |
// or: [ | |
// { isPublished: { eq: true } }, | |
// { | |
// percentageUp: { contains: 10.5 }, | |
// upvotes: { le: 5 }, | |
// and: { | |
// downvotes: { ge: 10 }, | |
// }, | |
// }, | |
// ], | |
// not: { | |
// title: { eq: 'Unpublished' }, | |
// }, | |
// } | |
// type DynamoDBExpression = { | |
// expression: string | |
// expressionNames: Record<string, string> | |
// expressionValues?: Record<string, any> | |
// } | |
export function getExpression<T, K = {}>(expression: Expression<T & K>) { | |
// if (!expression) return null | |
const filter = JSON.parse(util.transform.toDynamoDBFilterExpression(expression)) | |
if (filter && filter.expressionValues && !Object.keys(filter.expressionValues).length) { | |
delete filter.expressionValues | |
} | |
return filter as DynamoDBExpression | |
} | |
export function get<T = {}, K = {}>( | |
key: Partial<T> & K, | |
otherParams?: Omit<DynamoDBGetItem, 'operation' | 'key'> | |
): DynamoDBGetItem { | |
return { | |
operation: 'GetItem', | |
key: util.dynamodb.toMapValues(key), | |
...otherParams, | |
} | |
} | |
export function put<T extends {}, K extends {} | undefined = undefined>( | |
key: K extends undefined ? Partial<T> : K & Partial<T>, | |
item: K extends undefined ? T : Omit<T, keyof K>, | |
otherParams?: Pick< | |
DynamoDBPutItemRequest, | |
'condition' | 'customPartitionKey' | 'populateIndexFields' | '_version' | |
> | |
): DynamoDBPutItemRequest { | |
return { | |
operation: 'PutItem', | |
key: util.dynamodb.toMapValues(key), | |
attributeValues: util.dynamodb.toMapValues(item), | |
...otherParams, | |
} | |
} | |
type TempType<T> = { | |
sets: string[] | |
removes: string[] | |
// names?: { [P in keyof T as `#${string & P}`]?: P } | |
// values?: { [P in keyof T as `:${string & P}`]?: T[P] } | |
names: Record<string, string> | |
values: Record<string, any> | |
} | |
export function update<T extends {}, K = {}>( | |
key: K & Partial<T>, | |
values: Partial<T>, | |
otherParams?: Pick< | |
DynamoDBUpdateItemRequest, | |
'condition' | 'customPartitionKey' | 'populateIndexFields' | '_version' | |
> | |
): DynamoDBUpdateItemRequest { | |
const exp = Object.entries(values).reduce( | |
(prev, [k, v]) => { | |
prev.names[`#${k}`] = k | |
if (v) { | |
const a = prev.sets | |
a.push(`#${k} = :${k}`) | |
// prev.sets.push(`#${k} = :${k}`) | |
prev.values[`:${k}`] = v | |
} else { | |
const a = prev.removes | |
a.push(`#${k}`) | |
// prev.removes.push(`#${k}`) | |
} | |
return prev | |
}, | |
{ sets: [], removes: [], names: {}, values: {} } as TempType<T> | |
) | |
let expression = exp.sets.length ? `SET ${exp.sets.join(', ')}` : '' | |
expression += exp.removes.length ? ` REMOVE ${exp.removes.join(', ')}` : '' | |
return { | |
operation: 'UpdateItem', | |
key: util.dynamodb.toMapValues(key), | |
update: { | |
expression, | |
expressionNames: exp.names, | |
expressionValues: util.dynamodb.toMapValues(exp.values), | |
}, | |
...otherParams, | |
} | |
} | |
export function query<T, K = {}>( | |
expression: Expression<T & K>, | |
otherParams?: Omit<DynamoDBQueryRequest, 'query' | 'operation'> | |
): DynamoDBQueryRequest { | |
return { | |
operation: 'Query', | |
query: getExpression(expression), | |
...otherParams, | |
} | |
} | |
function _deleteOp<T extends {}, K = {}>( | |
key: K & Partial<T>, | |
otherParams?: Pick< | |
DynamoDBDeleteItemRequest, | |
'condition' | 'customPartitionKey' | 'populateIndexFields' | '_version' | |
> | |
): DynamoDBDeleteItemRequest { | |
return { | |
operation: 'DeleteItem', | |
key: util.dynamodb.toMapValues(key), | |
...otherParams, | |
} | |
} | |
export function invoke(payload: any): LambdaRequest { | |
return { | |
operation: 'Invoke', | |
payload, | |
} | |
} | |
export type Context<A> = Omit<_Context, 'args' | 'arguments'> & { | |
args: A | |
arguments: A | |
} | |
export type BlankContext = _Context | |
export { _deleteOp as delete } | |
// | |
export type AppSyncIdentityIAM = { | |
/** | |
* The AWS account ID of the caller. | |
*/ | |
accountId: string | |
/** | |
* The Amazon Cognito identity pool ID associated with the caller. | |
*/ | |
cognitoIdentityPoolId: string | |
/** | |
* The Amazon Cognito identity ID of the caller. | |
*/ | |
cognitoIdentityId: string | |
/** | |
* The source IP address of the caller that AWS AppSync receives. If the request doesn't | |
* include the `x-forwarded-for` header, the source IP value contains only a single IP address | |
* from the TCP connection. If the request includes a `x-forwarded-for` header, the source IP | |
* is a list of IP addresses from the `x-forwarded-for` header, in addition to the IP address | |
* from the TCP connection. | |
*/ | |
sourceIp: string[] | |
/** | |
* The user name of the authenticated user. In the case of `AMAZON_COGNITO_USER_POOLS` | |
* authorization, the value of username is the value of attribute `cognito:username`. In the | |
* case of `AWS_IAM` authorization, the value of username is the value of the AWS user | |
* principal. If you're using IAM authorization with credentials vended from Amazon Cognito | |
* identity pools, we recommend that you use `cognitoIdentityId`. | |
*/ | |
username: string | |
/** | |
* The Amazon Resource Name (ARN) of the IAM user. | |
*/ | |
userArn: string | |
/** | |
* Either authenticated or unauthenticated based on the identity type. | |
*/ | |
cognitoIdentityAuthType: string | |
/** | |
* A comma-separated list of external identity provider information used in obtaining the | |
* credentials used to sign the request. | |
*/ | |
cognitoIdentityAuthProvider: string | |
} | |
export type AppSyncIdentityCognito = { | |
/** | |
* The source IP address of the caller that AWS AppSync receives. If the request doesn't | |
* include the `x-forwarded-for` header, the source IP value contains only a single IP address | |
* from the TCP connection. If the request includes a `x-forwarded-for` header, the source IP | |
* is a list of IP addresses from the `x-forwarded-for` header, in addition to the IP address | |
* from the TCP connection. | |
*/ | |
sourceIp: string[] | |
/** | |
* The user name of the authenticated user. In the case of `AMAZON_COGNITO_USER_POOLS` | |
* authorization, the value of username is the value of attribute `cognito:username`. In the | |
* case of `AWS_IAM` authorization, the value of username is the value of the AWS user | |
* principal. If you're using IAM authorization with credentials vended from Amazon Cognito | |
* identity pools, we recommend that you use `cognitoIdentityId`. | |
*/ | |
username: string | |
/** | |
* The groups the authenticated user belongs to. | |
*/ | |
groups: string[] | null | |
/** | |
* The UUID of the authenticated user. | |
*/ | |
sub: string | |
/** | |
* The token issuer. | |
*/ | |
issuer: string | |
/** | |
* The claims that the user has. | |
*/ | |
claims: any | |
/** | |
* The default authorization strategy for this caller (ALLOW or DENY). | |
*/ | |
defaultAuthStrategy: string | |
} | |
export type AppSyncIdentityOIDC = { | |
/** | |
* The UUID of the authenticated user. | |
*/ | |
sub: string | |
/** | |
* The token issuer. | |
*/ | |
issuer: string | |
/** | |
* The claims that the user has. | |
*/ | |
claims: any | |
} | |
export type AppSyncIdentityLambda = { | |
/** | |
* content returned by the Lambda function authorizing the request. | |
*/ | |
resolverContext: any | |
} | |
export type Result<T> = Omit<T, '__typename'> | |
export function redactItem<T>(item: T, redact: Array<keyof T>) { | |
redact.forEach((r) => delete item[r]) | |
return item | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment