Skip to content

Commit

Permalink
migrate generateClient code to 'next'; build config updates to allow …
Browse files Browse the repository at this point in the history
…V6 to work with 'next'
  • Loading branch information
david-mcafee committed Aug 29, 2023
1 parent 3f26238 commit 92d3a74
Show file tree
Hide file tree
Showing 14 changed files with 929 additions and 253 deletions.
1 change: 1 addition & 0 deletions .github/workflows/push-preid-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
branches:
# Change this to your branch name where "example-preid" corresponds to the preid you want your changes released on
- feat/example-preid-branch/main
- next-api-v6

jobs:
e2e:
Expand Down
5 changes: 4 additions & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
"packages/auth",
"packages/analytics",
"packages/storage",
"packages/aws-amplify"
"packages/aws-amplify",
"packages/api",
"packages/api-graphql",
"packages/amplify-v6-types-package"
],
"exact": true,
"version": "independent",
Expand Down
77 changes: 77 additions & 0 deletions packages/amplify-v6-types-package/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

export declare const __modelMeta__: unique symbol;

export type ExtractModelMeta<T extends Record<any, any>> =
T[typeof __modelMeta__];

type Prettify<T> = T extends object
? {
[P in keyof T]: Prettify<T[P]>;
}
: T;

// tslint gets confused by template literal types
// tslint:disable:semicolon
type FlattenKeys<
T extends Record<string, unknown> = {},
Key = keyof T
> = Key extends string
? T[Key] extends Record<string, unknown>
? `${Key}.${FlattenKeys<T[Key]>}` | `${Key}.*`
: `${Key}`
: never;

type Model = Record<string, any>;
type Joined<
M extends Model,
Paths extends Array<FlattenKeys<M>>
> = Paths extends never[]
? M
: Prettify<
{
[k in Paths[number] | keyof M as k extends `${infer A}.${string}`
? A
: never]: k extends `${infer A}.${infer B}`
? B extends `${string}.${string}`
? Joined<M[A], B extends FlattenKeys<M[A]> ? [B] : never>
: B extends `*`
? M[A]
: Pick<M[A], B>
: never;
} & {
[k in Paths[number] as k extends `${string}.${string}`
? never
: k]: M[k];
}
>;

type ModelIdentifier<Model extends Record<any, any>> = Prettify<
Record<Model['identifier'] & string, string>
>;

export type ModelTypes<
T extends Record<any, any>,
ModelMeta extends Record<any, any> = ExtractModelMeta<T>
> = {
[K in keyof T]: K extends string
? T[K] extends Record<string, unknown>
? {
create: (model: T[K]) => Promise<T[K]>;
update: (
model: Prettify<
{
id: string;
} & Partial<T[K]>
>
) => Promise<T[K]>;
delete: (identifier: ModelIdentifier<ModelMeta[K]>) => Promise<T[K]>;
get: (identifier: ModelIdentifier<ModelMeta[K]>) => Promise<T[K]>;
list<SS extends FlattenKeys<T[K]>[]>(obj?: {
selectionSet?: SS;
}): Promise<Array<Joined<T[K], SS>>>;
}
: never
: never;
};
12 changes: 12 additions & 0 deletions packages/amplify-v6-types-package/index.v3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

export declare const __modelMeta__: unique symbol;

export type ExtractModelMeta<T extends Record<any, any>> =
T[typeof __modelMeta__];

export type ModelTypes<
T extends Record<any, any> = never,
ModelMeta extends Record<any, any> = any
> = any;
30 changes: 30 additions & 0 deletions packages/amplify-v6-types-package/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@aws-amplify/types-package-alpha",
"version": "0.0.0",
"main": "./lib/index.js",
"module": "./lib-esm/index.js",
"types": "./lib-esm/index.d.ts",
"license": "UNLICENSED",
"typesVersions": {
"<5": {
"lib-esm/index.d.ts": [
"index.v3.ts"
]
}
},
"publishConfig": {
"access": "public"
},
"scripts": {
"lint": "eslint \"**/*.ts*\"",
"build:cjs": "rimraf lib && tsc -p ./tsconfig.build.json -m commonjs --outDir lib",
"build:esm": "rimraf lib-esm && tsc -p ./tsconfig.build.json -m esnext --outDir lib-esm",
"build": "npm run clean && npm run build:esm && npm run build:cjs",
"test": "echo \"No tests\"",
"clean": "npm run clean:size && rimraf lib-esm lib dist",
"clean:size": "rimraf dual-publish-tmp tmp*"
},
"devDependencies": {
"typescript": "^5.1.6"
}
}
4 changes: 4 additions & 0 deletions packages/amplify-v6-types-package/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {}
}
33 changes: 17 additions & 16 deletions packages/api-graphql/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "@aws-amplify/api-graphql",
"private": true,
"version": "4.0.0",
"version": "3.4.8",
"description": "Api-graphql category of aws-amplify",
"main": "./lib/index.js",
"module": "./lib-esm/index.js",
Expand Down Expand Up @@ -41,40 +40,38 @@
"url": "https://github.com/aws/aws-amplify/issues"
},
"homepage": "https://aws-amplify.github.io/",
"devDependencies": {
"@types/zen-observable": "^0.8.0"
},
"files": [
"lib",
"lib-esm",
"src",
"internals"
],
"dependencies": {
"@aws-amplify/api-rest": "4.0.0",
"@aws-amplify/auth": "6.0.0",
"@aws-amplify/pubsub": "6.0.0",
"@aws-amplify/api-rest": "3.5.2",
"@aws-amplify/auth": "5.6.2",
"@aws-amplify/cache": "5.1.8",
"@aws-amplify/core": "5.8.2",
"@aws-amplify/pubsub": "5.5.2",
"graphql": "15.8.0",
"tslib": "^2.5.0",
"uuid": "^9.0.0",
"tslib": "^1.8.0",
"uuid": "^3.2.1",
"zen-observable-ts": "0.8.19"
},
"peerDependencies": {
"@aws-amplify/core": "^6.0.0"
},
"devDependencies": {
"@aws-amplify/core": "6.0.0",
"@types/zen-observable": "^0.8.0"
},
"size-limit": [
{
"name": "API (GraphQL client)",
"path": "./lib-esm/index.js",
"import": "{ Amplify, GraphQLAPI }",
"limit": "90.35 kB"
"limit": "91.7 kB"
}
],
"jest": {
"globals": {
"ts-jest": {
"diagnostics": false,
"diagnostics": true,
"tsConfig": {
"lib": [
"es5",
Expand All @@ -91,6 +88,10 @@
"^.+\\.(js|jsx|ts|tsx)$": "ts-jest"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(tsx?|jsx?)$",
"testPathIgnorePatterns": [
"__tests__/fixtures",
"__tests__/utils"
],
"moduleFileExtensions": [
"ts",
"tsx",
Expand Down
2 changes: 2 additions & 0 deletions packages/api-graphql/src/internals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export {
InternalGraphQLAPI,
InternalGraphQLAPIClass,
} from './InternalGraphQLAPI';

export { graphql } from './v6';
106 changes: 106 additions & 0 deletions packages/api-graphql/src/internals/v6.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { GraphQLAPI } from '../GraphQLAPI';
import { GraphQLOptionsV6, GraphQLResponseV6 } from '../types';

/**
* Invokes graphql operations against a graphql service, providing correct input and
* output types if Amplify-generated graphql from a recent version of the CLI/codegen
* are used *or* correct typing is provided via the type argument.
*
* Amplify-generated "branded" graphql queries will look similar to this:
*
* ```ts
* //
* // |-- branding
* // v
* export const getModel = `...` as GeneratedQuery<
* GetModelQueryVariables,
* GetModelQuery
* >;
* ```
*
* If this branding is not in your generated graphql, update to a newer version of
* CLI/codegen and regenerate your graphql using `amplify codegen`.
*
* ## Using Amplify-generated graphql
*
* ```ts
* import * as queries from './graphql/queries';
*
* //
* // |-- correctly typed graphql response containing a Widget
* // v
* const queryResult = await graphql({
* query: queries.getWidget,
* variables: {
* id: "abc", // <-- type hinted/enforced
* },
* });
*
* //
* // |-- a correctly typed Widget
* // v
* const fetchedWidget = queryResult.data?.getWidget!;
* ```
*
* ## Custom input + result types
*
* To provide input types (`variables`) and result types:
*
* ```ts
* type GetById_NameOnly = {
* variables: {
* id: string
* },
* result: Promise<{
* data: { getWidget: { name: string } }
* }>
* }
*
* //
* // |-- type is GetById_NameOnly["result"]
* // v
* const result = graphql<GetById_NameOnly>({
* query: "...",
* variables: { id: "abc" } // <-- type of GetById_NameOnly["variables"]
* });
* ```
*
* ## Custom result type only
*
* To specify result types only, use a type that is *not* in the `{variables, result}` shape:
*
* ```ts
* type MyResultType = Promise<{
* data: {
* getWidget: { name: string }
* }
* }>
*
* //
* // |-- type is MyResultType
* // v
* const result = graphql<MyResultType>({query: "..."});
* ```
*
* @param options
* @param additionalHeaders
*/
export function graphql<
FALLBACK_TYPES = unknown,
TYPED_GQL_STRING extends string = string
>(
options: GraphQLOptionsV6<FALLBACK_TYPES, TYPED_GQL_STRING>,
additionalHeaders?: { [key: string]: string }
): GraphQLResponseV6<FALLBACK_TYPES, TYPED_GQL_STRING> {
/**
* The correctness of these typings depends on correct string branding or overrides.
* Neither of these can actually be validated at runtime. Hence, we don't perform
* any validation or type-guarding here.
*/
const result = GraphQLAPI.graphql(options, additionalHeaders);
return result as any;
}

export { GraphQLOptionsV6, GraphQLResponseV6 };
Loading

0 comments on commit 92d3a74

Please sign in to comment.