Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] Ability to define a stack. #1984

Draft
wants to merge 1 commit into
base: function-stacks-0
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions packages/backend-auth/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { AmazonProviderProps } from '@aws-amplify/auth-construct';
import { AmplifyStackResources } from '@aws-amplify/plugin-types';
import { AppleProviderProps } from '@aws-amplify/auth-construct';
import { AuthProps } from '@aws-amplify/auth-construct';
import { AuthResources } from '@aws-amplify/plugin-types';
Expand Down Expand Up @@ -39,6 +40,7 @@ export type AmplifyAuthProps = Expand<Omit<AuthProps, 'outputStorageStrategy' |
loginWith: Expand<AuthLoginWithFactoryProps>;
triggers?: Partial<Record<TriggerEvent, ConstructFactory<ResourceProvider<FunctionResources>>>>;
access?: AuthAccessGenerator;
scope?: ConstructFactory<ResourceProvider<AmplifyStackResources>>;
}>;

// @public
Expand Down
8 changes: 7 additions & 1 deletion packages/backend-auth/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
TriggerEvent,
} from '@aws-amplify/auth-construct';
import {
AmplifyStackResources,
AuthResources,
AuthRoleName,
ConstructContainerEntryGenerator,
Expand Down Expand Up @@ -58,6 +59,8 @@ export type AmplifyAuthProps = Expand<
* access: (allow) => [allow.resource(groupManager).to(["manageGroups"])]
*/
access?: AuthAccessGenerator;

scope?: ConstructFactory<ResourceProvider<AmplifyStackResources>>;
}
>;

Expand Down Expand Up @@ -110,7 +113,10 @@ export class AmplifyAuthFactory implements ConstructFactory<BackendAuth> {
if (!this.generator) {
this.generator = new AmplifyAuthGenerator(this.props, getInstanceProps);
}
return constructContainer.getOrCompute(this.generator) as BackendAuth;
return constructContainer.getOrCompute(
this.generator,
this.props.scope?.getInstance(getInstanceProps).resources.stack
) as BackendAuth;
};
}

Expand Down
3 changes: 3 additions & 0 deletions packages/backend-data/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@

import { AmplifyData } from '@aws-amplify/data-construct';
import { AmplifyFunction } from '@aws-amplify/plugin-types';
import { AmplifyStackResources } from '@aws-amplify/plugin-types';
import { ConstructFactory } from '@aws-amplify/plugin-types';
import { DerivedCombinedSchema } from '@aws-amplify/data-schema-types';
import { DerivedModelSchema } from '@aws-amplify/data-schema-types';
import { ResourceProvider } from '@aws-amplify/plugin-types';

// @public
export type ApiKeyAuthorizationModeProps = {
Expand All @@ -30,6 +32,7 @@ export type DataProps = {
name?: string;
authorizationModes?: AuthorizationModes;
functions?: Record<string, ConstructFactory<AmplifyFunction>>;
scope?: ConstructFactory<ResourceProvider<AmplifyStackResources>>;
};

// @public
Expand Down
5 changes: 4 additions & 1 deletion packages/backend-data/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ export class DataFactory implements ConstructFactory<AmplifyData> {
outputStorageStrategy
);
}
return constructContainer.getOrCompute(this.generator) as AmplifyData;
return constructContainer.getOrCompute(
this.generator,
this.props.scope?.getInstance(props).resources.stack
) as AmplifyData;
};
}

Expand Down
10 changes: 9 additions & 1 deletion packages/backend-data/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import {
DerivedCombinedSchema,
DerivedModelSchema,
} from '@aws-amplify/data-schema-types';
import { AmplifyFunction, ConstructFactory } from '@aws-amplify/plugin-types';
import {
AmplifyFunction,
AmplifyStackResources,
ConstructFactory,
ResourceProvider,
} from '@aws-amplify/plugin-types';
import { Stack } from 'aws-cdk-lib';

/**
* Authorization modes used in by client side Amplify represented in camelCase.
Expand Down Expand Up @@ -139,6 +145,8 @@ export type DataProps = {
* Functions invokable by the API. The specific input type of the function is subject to change or removal.
*/
functions?: Record<string, ConstructFactory<AmplifyFunction>>;

scope?: ConstructFactory<ResourceProvider<AmplifyStackResources>>;
};

export type AmplifyDataError =
Expand Down
2 changes: 2 additions & 0 deletions packages/backend-function/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

```ts

import { AmplifyStackResources } from '@aws-amplify/plugin-types';
import { BackendSecret } from '@aws-amplify/plugin-types';
import { ConstructFactory } from '@aws-amplify/plugin-types';
import { FunctionResources } from '@aws-amplify/plugin-types';
Expand All @@ -30,6 +31,7 @@ export type FunctionProps = {
environment?: Record<string, string | BackendSecret>;
runtime?: NodeVersion;
schedule?: FunctionSchedule | FunctionSchedule[];
scope?: ConstructFactory<ResourceProvider<AmplifyStackResources>>;
};

// @public (undocumented)
Expand Down
24 changes: 15 additions & 9 deletions packages/backend-function/src/factory.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AmplifyStackResources,
BackendOutputStorageStrategy,
BackendSecret,
BackendSecretResolver,
Expand Down Expand Up @@ -124,6 +125,8 @@ export type FunctionProps = {
* schedule: "0 9 ? * 2 *" // every Monday at 9am
*/
schedule?: FunctionSchedule | FunctionSchedule[];

scope?: ConstructFactory<ResourceProvider<AmplifyStackResources>>;
};

/**
Expand All @@ -142,18 +145,19 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
/**
* Creates an instance of AmplifyFunction within the provided Amplify context
*/
getInstance = ({
constructContainer,
outputStorageStrategy,
resourceNameValidator,
}: ConstructFactoryGetInstanceProps): AmplifyFunction => {
getInstance = (
getInstanceProps: ConstructFactoryGetInstanceProps
): AmplifyFunction => {
if (!this.generator) {
this.generator = new FunctionGenerator(
this.hydrateDefaults(resourceNameValidator),
outputStorageStrategy
this.hydrateDefaults(getInstanceProps.resourceNameValidator),
getInstanceProps.outputStorageStrategy
);
}
return constructContainer.getOrCompute(this.generator) as AmplifyFunction;
return getInstanceProps.constructContainer.getOrCompute(
this.generator,
this.props.scope?.getInstance(getInstanceProps).resources.stack
) as AmplifyFunction;
};

private hydrateDefaults = (
Expand All @@ -169,6 +173,7 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
environment: this.props.environment ?? {},
runtime: this.resolveRuntime(),
schedule: this.resolveSchedule(),
scope: this.props.scope,
};
};

Expand Down Expand Up @@ -276,7 +281,8 @@ class FunctionFactory implements ConstructFactory<AmplifyFunction> {
};
}

type HydratedFunctionProps = Required<FunctionProps>;
type HydratedFunctionProps = Required<Omit<FunctionProps, 'scope'>> &
Pick<FunctionProps, 'scope'>;

class FunctionGenerator implements ConstructContainerEntryGenerator {
readonly resourceGroupName = 'function';
Expand Down
4 changes: 4 additions & 0 deletions packages/backend/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { a } from '@aws-amplify/data-schema';
import { AmplifyStackResources } from '@aws-amplify/plugin-types';
import { AuthCfnResources } from '@aws-amplify/plugin-types';
import { AuthResources } from '@aws-amplify/plugin-types';
import { AuthRoleName } from '@aws-amplify/plugin-types';
Expand Down Expand Up @@ -81,6 +82,9 @@ export { defineData }

export { defineFunction }

// @public
export const defineStack: (name: string) => ConstructFactory<ResourceProvider<AmplifyStackResources>>;

export { defineStorage }

export { FunctionResources }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getBackendIdentifier } from '../backend_identifier.js';
import { DefaultBackendSecretResolver } from './backend-secret/backend_secret_resolver.js';
import { BackendIdScopedSsmEnvironmentEntriesGenerator } from './backend_id_scoped_ssm_environment_entries_generator.js';
import { BackendIdScopedStableBackendIdentifiers } from '../backend_id_scoped_stable_backend_identifiers.js';
import { Stack } from 'aws-cdk-lib';

/**
* Serves as a DI container and shared state store for initializing Amplify constructs
Expand All @@ -33,10 +34,13 @@ export class SingletonConstructContainer implements ConstructContainer {
* Otherwise, the generator is called and the value is cached and returned
*/
getOrCompute = (
generator: ConstructContainerEntryGenerator
generator: ConstructContainerEntryGenerator,
scope?: Stack
): ResourceProvider => {
if (!this.providerCache.has(generator)) {
const scope = this.stackResolver.getStackFor(generator.resourceGroupName);
if (!scope) {
scope = this.stackResolver.getStackFor(generator.resourceGroupName);
}
const backendId = getBackendIdentifier(scope);
const ssmEnvironmentEntriesGenerator =
new BackendIdScopedSsmEnvironmentEntriesGenerator(scope, backendId);
Expand Down
1 change: 1 addition & 0 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ if (isBrowser()) {
}

export { defineBackend } from './backend_factory.js';
export { defineStack } from './stack_factory.js';
export * from './backend.js';
export * from './secret.js';

Expand Down
56 changes: 56 additions & 0 deletions packages/backend/src/stack_factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
AmplifyStackResources,
ConstructContainerEntryGenerator,
ConstructFactory,
ConstructFactoryGetInstanceProps,
GenerateContainerEntryProps,
ResourceProvider,
} from '@aws-amplify/plugin-types';
import { Stack } from 'aws-cdk-lib';

class StackGenerator
implements ConstructContainerEntryGenerator<AmplifyStackResources>
{
readonly resourceGroupName: string;

constructor(name: string) {
this.resourceGroupName = name;
}

generateContainerEntry = ({
scope,
}: GenerateContainerEntryProps): ResourceProvider<AmplifyStackResources> => {
return {
resources: {
stack: scope as Stack,
},
};
};
}

class StackFactory
implements ConstructFactory<ResourceProvider<AmplifyStackResources>>
{
private generator: ConstructContainerEntryGenerator;

constructor(private readonly name: string) {}

getInstance(
props: ConstructFactoryGetInstanceProps
): ResourceProvider<AmplifyStackResources> {
if (!this.generator) {
this.generator = new StackGenerator(this.name);
}
return props.constructContainer.getOrCompute(
this.generator
) as ResourceProvider<AmplifyStackResources>;
}
}

/**
* TODO
*/
export const defineStack = (
name: string
): ConstructFactory<ResourceProvider<AmplifyStackResources>> =>
new StackFactory(name);
7 changes: 6 additions & 1 deletion packages/plugin-types/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ import { Stack } from 'aws-cdk-lib';
// @public (undocumented)
export type AmplifyFunction = ResourceProvider<FunctionResources>;

// @public (undocumented)
export type AmplifyStackResources = {
readonly stack: Stack;
};

// @public
export type AppId = string;

Expand Down Expand Up @@ -110,7 +115,7 @@ export type BranchName = string;

// @public
export type ConstructContainer = {
getOrCompute: (generator: ConstructContainerEntryGenerator) => ResourceProvider;
getOrCompute: (generator: ConstructContainerEntryGenerator, scope?: Stack) => ResourceProvider;
registerConstructFactory: (token: string, provider: ConstructFactory) => void;
getConstructFactory: <T extends ResourceProvider>(token: string) => ConstructFactory<T> | undefined;
};
Expand Down
5 changes: 4 additions & 1 deletion packages/plugin-types/src/construct_container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BackendSecretResolver } from './backend_secret_resolver.js';
import { ResourceProvider } from './resource_provider.js';
import { SsmEnvironmentEntriesGenerator } from './ssm_environment_entries_generator.js';
import { StableBackendIdentifiers } from './stable_backend_identifiers.js';
import { Stack } from 'aws-cdk-lib';
/**
* Initializes a CDK Construct in a given scope
*/
Expand Down Expand Up @@ -34,7 +35,9 @@ export type GenerateContainerEntryProps = {
*/
export type ConstructContainer = {
getOrCompute: (
generator: ConstructContainerEntryGenerator
generator: ConstructContainerEntryGenerator,
// TODO: are there better ways?
scope?: Stack
) => ResourceProvider;
registerConstructFactory: (token: string, provider: ConstructFactory) => void;
getConstructFactory: <T extends ResourceProvider>(
Expand Down
6 changes: 6 additions & 0 deletions packages/plugin-types/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Stack } from 'aws-cdk-lib';

export * from './backend_stack_creator.js';
export * from './backend_stack_resolver.js';
export * from './construct_container.js';
Expand All @@ -20,3 +22,7 @@ export * from './deep_partial.js';
export * from './stable_backend_identifiers.js';
export * from './resource_name_validator.js';
export * from './aws_client_provider.js';

export type AmplifyStackResources = {
readonly stack: Stack;
};
5 changes: 5 additions & 0 deletions test-projects/function-stack-1/amplify/data/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import {
a,
defineData,
defineFunction,
defineStack,
type ClientSchema,
} from "@aws-amplify/backend";

const stack = defineStack('awesome-stack');

const testHandler = defineFunction({
scope: stack
});

const schema = a
Expand All @@ -28,4 +32,5 @@ export const data = defineData({
defaultAuthorizationMode: "apiKey",
apiKeyAuthorizationMode: { expiresInDays: 30 },
},
scope: stack
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { defineFunction } from '@aws-amplify/backend';
import { defineFunction, defineStack } from '@aws-amplify/backend';

export const testFunction = defineFunction();
const stack1 = defineStack('awesome-stack1');
const stack2 = defineStack('awesome-stack2');


export const testFunction = defineFunction({scope: stack1});

export const myApiFunction = defineFunction({
name: 'api-function',
scope: stack2
});