Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Publish

on:
release:
types: [published]

permissions:
id-token: write
contents: read

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
- run: npm ci
- run: npm test
- run: npm run lint
- run: npm publish
67 changes: 0 additions & 67 deletions .github/workflows/release.yml

This file was deleted.

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
> **MONEI fork**, published as `@monei-js/serverless-appsync-plugin`. On top of upstream it converts GraphQL descriptions to comments (AppSync rejects descriptions) and uses the osls v4 AWS credentials.
>
> Releasing: bump `version` in `package.json`, merge to `master`, then publish a GitHub release for that version. The `Publish` workflow publishes to npm with trusted publishing.

<p>
<a href="https://www.npmjs.com/package/serverless-appsync-plugin"><img alt="npm downloads (weekly)" src="https://img.shields.io/npm/dw/serverless-appsync-plugin?label=downloads%2Fweek&color=blue"></a>
<a href="https://www.npmjs.com/package/serverless-appsync-plugin"><img alt="npm downloads (year)" src="https://img.shields.io/npm/dy/serverless-appsync-plugin?label=downloads%2Fyear&color=blue"></a>
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "serverless-appsync-plugin",
"version": "0.0.0-development",
"name": "@monei-js/serverless-appsync-plugin",
"version": "2.14.0",
"description": "AWS AppSync support for the Serverless Framework",
"main": "lib/index.js",
"types": "lib/types/index.d.ts",
"repository": "https://github.com/sid88in/serverless-appsync-plugin",
"repository": "https://github.com/MONEI/serverless-appsync-plugin",
"license": "MIT",
"files": [
"/lib"
Expand Down Expand Up @@ -95,5 +95,8 @@
"*.{json,md,yml,yaml}": [
"prettier --write"
]
},
"publishConfig": {
"access": "public"
}
}
59 changes: 59 additions & 0 deletions src/__tests__/credentials.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as given from './given';

jest.mock('@aws-sdk/credential-providers', () => ({
fromNodeProviderChain: () => async () => ({
accessKeyId: 'DEFAULT_CHAIN',
secretAccessKey: 'default-chain',
}),
}));

type CredentialProvider = () => Promise<Record<string, unknown>>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const resolveCredentials = (plugin: any): Promise<Record<string, unknown>> =>
(plugin.clientFactory.credentials as CredentialProvider)();

describe('AWS credentials', () => {
// osls 4 removed provider.getCredentials(); calling it throws
// AWS_SDK_V2_SURFACE_REMOVED. Falling back to the default chain would ignore
// provider.profile and --aws-profile, so the osls-resolved config must win.
it('uses the credentials osls 4 resolves via getAwsSdkV3Config()', async () => {
const plugin = given.plugin();
const identity = { accessKeyId: 'OSLS', secretAccessKey: 'osls' };
Object.assign(plugin['provider'], {
getAwsSdkV3Config: jest.fn().mockResolvedValue({
region: 'eu-west-1',
credentials: async () => identity,
}),
getCredentials: () => {
throw new Error('AWS_SDK_V2_SURFACE_REMOVED');
},
});

await expect(resolveCredentials(plugin)).resolves.toEqual(identity);
});

it('accepts static credentials from getAwsSdkV3Config()', async () => {
const plugin = given.plugin();
const identity = { accessKeyId: 'STATIC', secretAccessKey: 'static' };
Object.assign(plugin['provider'], {
getAwsSdkV3Config: jest.fn().mockResolvedValue({ credentials: identity }),
});

await expect(resolveCredentials(plugin)).resolves.toEqual(identity);
});

it('uses getCredentials() on Serverless 3 / osls 3', async () => {
const plugin = given.plugin();
Object.assign(plugin['provider'], {
getCredentials: () => ({
credentials: { accessKeyId: 'SLS3', secretAccessKey: 'sls3' },
}),
});

await expect(resolveCredentials(plugin)).resolves.toMatchObject({
accessKeyId: 'SLS3',
secretAccessKey: 'sls3',
});
});
});
9 changes: 8 additions & 1 deletion src/__tests__/fixtures/schemas/multiple/post.graphql
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
extend type Query {
getPost(id: ID!): Post!
getPost(
"This is an inline description"
id: ID!
): Post!
}

extend type Mutation {
"""
This is a description
that includes multiple lines
"""
createPost(post: PostInput!): Post!
}

Expand Down
48 changes: 32 additions & 16 deletions src/__tests__/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ describe('schema', () => {
createUser(post: UserInput!): User!
}

"""
A User
"""
#A User
type User {
id: ID!
name: String!
Expand All @@ -44,6 +42,7 @@ describe('schema', () => {
input UserInput {
name: String!
}

",
},
"Type": "AWS::AppSync::GraphQLSchema",
Expand All @@ -61,6 +60,8 @@ describe('schema', () => {
]);
expect(schema.generateSchema()).toMatchInlineSnapshot(`
"type Mutation {
#This is a description
#that includes multiple lines
createPost(post: PostInput!): Post!
createUser(post: UserInput!): User!
}
Expand All @@ -72,13 +73,16 @@ describe('schema', () => {
updatedAt: AWSDateTime!
}

"""This is a description"""
#This is a description
input PostInput {
title: String!
}

type Query {
getPost(id: ID!): Post!
getPost(
#This is an inline description
id: ID!
): Post!
getUser: User!
}

Expand All @@ -92,7 +96,8 @@ describe('schema', () => {

input UserInput {
name: String!
}"
}
"
`);
});

Expand All @@ -103,6 +108,8 @@ describe('schema', () => {
]);
expect(schema.generateSchema()).toMatchInlineSnapshot(`
"type Mutation {
#This is a description
#that includes multiple lines
createPost(post: PostInput!): Post!
createUser(post: UserInput!): User!
}
Expand All @@ -114,13 +121,16 @@ describe('schema', () => {
updatedAt: AWSDateTime!
}

"""This is a description"""
#This is a description
input PostInput {
title: String!
}

type Query {
getPost(id: ID!): Post!
getPost(
#This is an inline description
id: ID!
): Post!
getUser: User!
}

Expand All @@ -134,7 +144,8 @@ describe('schema', () => {

input UserInput {
name: String!
}"
}
"
`);
});

Expand All @@ -145,6 +156,8 @@ describe('schema', () => {
]);
expect(schema.generateSchema()).toMatchInlineSnapshot(`
"type Mutation {
#This is a description
#that includes multiple lines
createPost(post: PostInput!): Post!
createUser(post: UserInput!): User!
}
Expand All @@ -156,13 +169,16 @@ describe('schema', () => {
updatedAt: AWSDateTime!
}

"""This is a description"""
#This is a description
input PostInput {
title: String!
}

type Query {
getPost(id: ID!): Post!
getPost(
#This is an inline description
id: ID!
): Post!
getUser: User!
}

Expand All @@ -176,7 +192,8 @@ describe('schema', () => {

input UserInput {
name: String!
}"
}
"
`);
});

Expand Down Expand Up @@ -253,7 +270,7 @@ describe('schema', () => {
expect(schema.generateSchema()).toContain('type Query');
});

it('should return single files schemas as-is', () => {
it('should return single files schemas with converted descriptions', () => {
const api = new Api(given.appSyncConfig(), plugin);
const schema = new Schema(api, [
'src/__tests__/fixtures/schemas/single/schema.graphql',
Expand All @@ -267,9 +284,7 @@ describe('schema', () => {
createUser(post: UserInput!): User!
}

"""
A User
"""
#A User
type User {
id: ID!
name: String!
Expand All @@ -279,6 +294,7 @@ describe('schema', () => {
input UserInput {
name: String!
}

"
`);
});
Expand Down
11 changes: 11 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ const CONSOLE_BASE_URL = 'https://console.aws.amazon.com';
*/
const resolveCredentials = (provider: Provider): AwsCredentials => {
return async () => {
// osls 4 removed `getCredentials()` (it throws AWS_SDK_V2_SURFACE_REMOVED)
// and exposes its resolved SDK v3 client config instead.
if (typeof provider.getAwsSdkV3Config === 'function') {
const { credentials: v3Credentials } = await provider.getAwsSdkV3Config();
if (!v3Credentials) {
return fromNodeProviderChain()();
}
return typeof v3Credentials === 'function'
? v3Credentials()
: v3Credentials;
}
let credentials;
try {
({ credentials } = provider.getCredentials());
Expand Down
Loading