Skip to content

Commit

Permalink
feat: Support for handler and transformer functions [EXT-5139] [EXT-5…
Browse files Browse the repository at this point in the history
…133] (#1936)

* fix:master->main

* feat: add appevents

* fix: gql typing
  • Loading branch information
mgoudy91 authored Apr 11, 2024
1 parent 970484c commit 481bc2b
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ workflows:
- vault
filters:
branches:
only: master
only: main
requires:
- test-built-app-18
- test-built-app-18-actions-functions
Expand Down
47 changes: 30 additions & 17 deletions packages/contentful--app-scripts/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import { ContentfulFunction, FunctionAppAction } from './types';

const DEFAULT_MANIFEST_PATH = './contentful-app-manifest.json';

const graphQLEvents = {
fieldMappingEvent: 'graphql.field.mapping',
queryEvent: 'graphql.query',
};

const appEvents = {
appEventFilter: 'appevent.filter',
appEventHandler: 'appevent.handler',
appEventTransformation: 'appevent.transformation',
};

export const throwValidationException = (subject: string, message?: string, details?: string) => {
console.log(`${chalk.red('Validation Error:')} Missing or invalid ${subject}.`);
message && console.log(message);
Expand Down Expand Up @@ -56,10 +67,10 @@ ${err.message}
throw err;
};

export const selectFromList = async <T extends (Definition | Organization)>(
export const selectFromList = async <T extends Definition | Organization>(
list: T[],
message: string,
cachedOptionEnvVar: string,
cachedOptionEnvVar: string
): Promise<T> => {
const cachedEnvVar = process.env[cachedOptionEnvVar];
const cachedElement = list.find((item) => item.value === cachedEnvVar);
Expand All @@ -86,9 +97,13 @@ export const selectFromList = async <T extends (Definition | Organization)>(
}
};

type Entities<Type> = Type extends 'actions' ? Omit<FunctionAppAction, 'entryFile'>[] : Omit<ContentfulFunction, 'entryFile'>[];
type Entities<Type> = Type extends 'actions'
? Omit<FunctionAppAction, 'entryFile'>[]
: Omit<ContentfulFunction, 'entryFile'>[];

export function getEntityFromManifest<Type extends 'actions' | 'functions'>(type: Type): Entities<Type> | undefined {
export function getEntityFromManifest<Type extends 'actions' | 'functions'>(
type: Type
): Entities<Type> | undefined {
const isManifestExists = fs.existsSync(DEFAULT_MANIFEST_PATH);

if (!isManifestExists) {
Expand All @@ -104,41 +119,39 @@ export function getEntityFromManifest<Type extends 'actions' | 'functions'>(type

logProgress(
`${type === 'actions' ? 'App Actions' : 'functions'} found in ${chalk.bold(
DEFAULT_MANIFEST_PATH,
)}.`,
DEFAULT_MANIFEST_PATH
)}.`
);

const fieldMappingEvent = "graphql.field.mapping";
const queryEvent = "graphql.query";
const appEventFilter = 'appevent.filter';

const items = (manifest[type] as FunctionAppAction[] | ContentfulFunction[]).map((item) => {
const allowNetworks = Array.isArray(item.allowNetworks)
? item.allowNetworks.map(stripProtocol)
: [];

const accepts = 'accepts' in item && Array.isArray(item.accepts) ? item.accepts : undefined;
const hasInvalidEvent = accepts?.some((event) => ![fieldMappingEvent, queryEvent, appEventFilter].includes(event));
const hasInvalidEvent = accepts?.some(
(event) => ![...Object.values(graphQLEvents), ...Object.values(appEvents)].includes(event)
);

const hasInvalidNetwork = allowNetworks.find((netWork) => !isValidNetwork(netWork));
if (hasInvalidNetwork) {
console.log(
`${chalk.red(
'Error:',
'Error:'
)} Invalid IP address ${hasInvalidNetwork} found in the allowNetworks array for ${type} "${
item.name
}".`,
}".`
);
// eslint-disable-next-line no-process-exit
process.exit(1);
}
if (hasInvalidEvent) {
console.log(
`${chalk.red(
'Error:',
'Error:'
)} Invalid events ${hasInvalidEvent} found in the accepts array for ${type} "${
item.name
}".`,
}".`
);
// eslint-disable-next-line no-process-exit
process.exit(1);
Expand All @@ -159,8 +172,8 @@ export function getEntityFromManifest<Type extends 'actions' | 'functions'>(type
} catch {
console.log(
`${chalk.red('Error:')} Invalid JSON in manifest file at ${chalk.bold(
DEFAULT_MANIFEST_PATH,
)}.`,
DEFAULT_MANIFEST_PATH
)}.`
);
// eslint-disable-next-line no-process-exit
process.exit(1);
Expand Down
2 changes: 1 addition & 1 deletion packages/contentful--create-contentful-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ To start developing your first app, run:
npx create-contentful-app my-first-app
```

![Screenshot of `npx create-contentful-app my-app`](https://raw.githubusercontent.com/contentful/create-contentful-app/master/packages/contentful--create-contentful-app/docs/screenshot.png)
![Screenshot of `npx create-contentful-app my-app`](https://raw.githubusercontent.com/contentful/create-contentful-app/main/packages/contentful--create-contentful-app/docs/screenshot.png)

## Bootstrap

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ const addBuildCommand = getAddBuildCommandFn({
command: 'node build-functions.js',
});

const VALID_FUNCTION_TEMPLATES_DIRS = ['templates', 'appevent-filter'];
const VALID_FUNCTION_TEMPLATES_DIRS = [
'templates',
'appevent-filter',
'appevent-handler',
'appevent-transformation',
];

function functionTemplateFromName(functionName: string) {
let dirName = functionName;
Expand Down

0 comments on commit 481bc2b

Please sign in to comment.