create-aws-project 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -0
- package/dist/__tests__/generator/replace-tokens.spec.d.ts +1 -0
- package/dist/__tests__/generator/replace-tokens.spec.js +281 -0
- package/dist/__tests__/generator.spec.d.ts +1 -0
- package/dist/__tests__/generator.spec.js +162 -0
- package/dist/__tests__/validation/project-name.spec.d.ts +1 -0
- package/dist/__tests__/validation/project-name.spec.js +57 -0
- package/dist/__tests__/wizard.spec.d.ts +1 -0
- package/dist/__tests__/wizard.spec.js +232 -0
- package/dist/aws/iam.d.ts +75 -0
- package/dist/aws/iam.js +264 -0
- package/dist/aws/organizations.d.ts +79 -0
- package/dist/aws/organizations.js +168 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +206 -0
- package/dist/commands/setup-github.d.ts +4 -0
- package/dist/commands/setup-github.js +185 -0
- package/dist/generator/copy-file.d.ts +15 -0
- package/dist/generator/copy-file.js +56 -0
- package/dist/generator/generate-project.d.ts +14 -0
- package/dist/generator/generate-project.js +81 -0
- package/dist/generator/index.d.ts +4 -0
- package/dist/generator/index.js +3 -0
- package/dist/generator/replace-tokens.d.ts +29 -0
- package/dist/generator/replace-tokens.js +68 -0
- package/dist/github/secrets.d.ts +109 -0
- package/dist/github/secrets.js +275 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/dist/prompts/auth.d.ts +3 -0
- package/dist/prompts/auth.js +23 -0
- package/dist/prompts/aws-config.d.ts +2 -0
- package/dist/prompts/aws-config.js +14 -0
- package/dist/prompts/features.d.ts +2 -0
- package/dist/prompts/features.js +10 -0
- package/dist/prompts/github-setup.d.ts +53 -0
- package/dist/prompts/github-setup.js +208 -0
- package/dist/prompts/org-structure.d.ts +9 -0
- package/dist/prompts/org-structure.js +93 -0
- package/dist/prompts/platforms.d.ts +2 -0
- package/dist/prompts/platforms.js +12 -0
- package/dist/prompts/project-name.d.ts +2 -0
- package/dist/prompts/project-name.js +8 -0
- package/dist/prompts/theme.d.ts +2 -0
- package/dist/prompts/theme.js +14 -0
- package/dist/templates/index.d.ts +4 -0
- package/dist/templates/index.js +2 -0
- package/dist/templates/manifest.d.ts +11 -0
- package/dist/templates/manifest.js +99 -0
- package/dist/templates/tokens.d.ts +39 -0
- package/dist/templates/tokens.js +37 -0
- package/dist/templates/types.d.ts +52 -0
- package/dist/templates/types.js +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.js +1 -0
- package/dist/validation/project-name.d.ts +1 -0
- package/dist/validation/project-name.js +12 -0
- package/dist/wizard.d.ts +2 -0
- package/dist/wizard.js +81 -0
- package/package.json +68 -0
- package/templates/.github/actions/build-and-test/action.yml +24 -0
- package/templates/.github/actions/deploy-cdk/action.yml +46 -0
- package/templates/.github/actions/deploy-web/action.yml +72 -0
- package/templates/.github/actions/setup/action.yml +29 -0
- package/templates/.github/pull_request_template.md +15 -0
- package/templates/.github/workflows/deploy-dev.yml +80 -0
- package/templates/.github/workflows/deploy-prod.yml +67 -0
- package/templates/.github/workflows/deploy-stage.yml +77 -0
- package/templates/.github/workflows/pull-request.yml +72 -0
- package/templates/.vscode/extensions.json +7 -0
- package/templates/.vscode/settings.json +67 -0
- package/templates/apps/api/.eslintrc.json +18 -0
- package/templates/apps/api/cdk/app.ts +93 -0
- package/templates/apps/api/cdk/auth/cognito-stack.ts +164 -0
- package/templates/apps/api/cdk/cdk.json +73 -0
- package/templates/apps/api/cdk/deployment-user-stack.ts +187 -0
- package/templates/apps/api/cdk/org-stack.ts +67 -0
- package/templates/apps/api/cdk/static-stack.ts +361 -0
- package/templates/apps/api/cdk/tsconfig.json +39 -0
- package/templates/apps/api/cdk/user-stack.ts +255 -0
- package/templates/apps/api/jest.config.ts +38 -0
- package/templates/apps/api/lambdas.yml +84 -0
- package/templates/apps/api/project.json.template +58 -0
- package/templates/apps/api/src/__tests__/setup.ts +10 -0
- package/templates/apps/api/src/handlers/users/create-user.ts +52 -0
- package/templates/apps/api/src/handlers/users/delete-user.ts +45 -0
- package/templates/apps/api/src/handlers/users/get-me.ts +72 -0
- package/templates/apps/api/src/handlers/users/get-user.ts +45 -0
- package/templates/apps/api/src/handlers/users/get-users.ts +23 -0
- package/templates/apps/api/src/handlers/users/index.ts +17 -0
- package/templates/apps/api/src/handlers/users/update-user.ts +72 -0
- package/templates/apps/api/src/lib/dynamo/dynamo-model.ts +504 -0
- package/templates/apps/api/src/lib/dynamo/index.ts +12 -0
- package/templates/apps/api/src/lib/dynamo/utils.ts +39 -0
- package/templates/apps/api/src/middleware/auth0-auth.ts +97 -0
- package/templates/apps/api/src/middleware/cognito-auth.ts +90 -0
- package/templates/apps/api/src/models/UserModel.ts +109 -0
- package/templates/apps/api/src/schemas/user.schema.ts +44 -0
- package/templates/apps/api/src/services/user-service.ts +108 -0
- package/templates/apps/api/src/utils/auth-context.ts +60 -0
- package/templates/apps/api/src/utils/common/helpers.ts +26 -0
- package/templates/apps/api/src/utils/lambda-handler.ts +148 -0
- package/templates/apps/api/src/utils/response.ts +52 -0
- package/templates/apps/api/src/utils/validator.ts +75 -0
- package/templates/apps/api/tsconfig.app.json +15 -0
- package/templates/apps/api/tsconfig.json +19 -0
- package/templates/apps/api/tsconfig.spec.json +17 -0
- package/templates/apps/mobile/.env.example +5 -0
- package/templates/apps/mobile/.eslintrc.json +33 -0
- package/templates/apps/mobile/app.json +33 -0
- package/templates/apps/mobile/assets/.gitkeep +0 -0
- package/templates/apps/mobile/babel.config.js +19 -0
- package/templates/apps/mobile/index.js +7 -0
- package/templates/apps/mobile/jest.config.ts +22 -0
- package/templates/apps/mobile/metro.config.js +35 -0
- package/templates/apps/mobile/package.json +22 -0
- package/templates/apps/mobile/project.json.template +64 -0
- package/templates/apps/mobile/src/App.tsx +367 -0
- package/templates/apps/mobile/src/__tests__/App.spec.tsx +46 -0
- package/templates/apps/mobile/src/__tests__/store/user-store.spec.ts +156 -0
- package/templates/apps/mobile/src/config/api.ts +16 -0
- package/templates/apps/mobile/src/store/user-store.ts +56 -0
- package/templates/apps/mobile/src/test-setup.ts +10 -0
- package/templates/apps/mobile/tsconfig.json +22 -0
- package/templates/apps/web/.env.example +13 -0
- package/templates/apps/web/.eslintrc.json +26 -0
- package/templates/apps/web/index.html +13 -0
- package/templates/apps/web/jest.config.ts +24 -0
- package/templates/apps/web/package.json +15 -0
- package/templates/apps/web/project.json.template +66 -0
- package/templates/apps/web/src/App.tsx +352 -0
- package/templates/apps/web/src/__mocks__/config/api.ts +41 -0
- package/templates/apps/web/src/__tests__/App.spec.tsx +240 -0
- package/templates/apps/web/src/__tests__/store/user-store.spec.ts +185 -0
- package/templates/apps/web/src/auth/auth0-provider.tsx +103 -0
- package/templates/apps/web/src/auth/cognito-provider.tsx +143 -0
- package/templates/apps/web/src/auth/index.ts +7 -0
- package/templates/apps/web/src/auth/use-auth.ts +16 -0
- package/templates/apps/web/src/config/amplify-config.ts +31 -0
- package/templates/apps/web/src/config/api.ts +38 -0
- package/templates/apps/web/src/config/auth0-config.ts +17 -0
- package/templates/apps/web/src/main.tsx +41 -0
- package/templates/apps/web/src/store/user-store.ts +56 -0
- package/templates/apps/web/src/styles.css +165 -0
- package/templates/apps/web/src/test-setup.ts +1 -0
- package/templates/apps/web/src/theme/index.ts +30 -0
- package/templates/apps/web/src/vite-env.d.ts +19 -0
- package/templates/apps/web/tsconfig.app.json +24 -0
- package/templates/apps/web/tsconfig.json +22 -0
- package/templates/apps/web/tsconfig.spec.json +28 -0
- package/templates/apps/web/vite.config.ts +87 -0
- package/templates/manifest.json +28 -0
- package/templates/packages/api-client/.eslintrc.json +18 -0
- package/templates/packages/api-client/jest.config.ts +13 -0
- package/templates/packages/api-client/package.json +8 -0
- package/templates/packages/api-client/project.json.template +34 -0
- package/templates/packages/api-client/src/__tests__/api-client.spec.ts +408 -0
- package/templates/packages/api-client/src/api-client.ts +201 -0
- package/templates/packages/api-client/src/config.ts +193 -0
- package/templates/packages/api-client/src/index.ts +9 -0
- package/templates/packages/api-client/tsconfig.json +22 -0
- package/templates/packages/api-client/tsconfig.lib.json +11 -0
- package/templates/packages/api-client/tsconfig.spec.json +14 -0
- package/templates/packages/common-types/.eslintrc.json +18 -0
- package/templates/packages/common-types/package.json +6 -0
- package/templates/packages/common-types/project.json.template +26 -0
- package/templates/packages/common-types/src/api.types.ts +24 -0
- package/templates/packages/common-types/src/auth.types.ts +36 -0
- package/templates/packages/common-types/src/common.types.ts +46 -0
- package/templates/packages/common-types/src/index.ts +19 -0
- package/templates/packages/common-types/src/lambda.types.ts +39 -0
- package/templates/packages/common-types/src/user.types.ts +31 -0
- package/templates/packages/common-types/tsconfig.json +19 -0
- package/templates/packages/common-types/tsconfig.lib.json +11 -0
- package/templates/root/.editorconfig +23 -0
- package/templates/root/.nvmrc +1 -0
- package/templates/root/eslint.config.js +61 -0
- package/templates/root/jest.preset.js +16 -0
- package/templates/root/nx.json +29 -0
- package/templates/root/package.json +131 -0
- package/templates/root/tsconfig.base.json +29 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { PromptObject } from 'prompts';
|
|
2
|
+
/**
|
|
3
|
+
* GitHub setup prompts module
|
|
4
|
+
*
|
|
5
|
+
* Provides prompts for the setup-github command to collect
|
|
6
|
+
* configuration for IAM deployment users and GitHub secrets.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for an environment with AWS profile
|
|
10
|
+
*/
|
|
11
|
+
export interface EnvironmentConfig {
|
|
12
|
+
environment: string;
|
|
13
|
+
accountId: string;
|
|
14
|
+
awsProfile: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Complete configuration from the GitHub setup wizard
|
|
18
|
+
*/
|
|
19
|
+
export interface GitHubSetupConfig {
|
|
20
|
+
projectName: string;
|
|
21
|
+
awsRegion: string;
|
|
22
|
+
environments: EnvironmentConfig[];
|
|
23
|
+
github: {
|
|
24
|
+
owner: string;
|
|
25
|
+
repo: string;
|
|
26
|
+
token: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Project name prompt - used as prefix for IAM users
|
|
31
|
+
*/
|
|
32
|
+
export declare const projectNamePrompt: PromptObject;
|
|
33
|
+
/**
|
|
34
|
+
* AWS region selection prompt
|
|
35
|
+
*/
|
|
36
|
+
export declare const awsRegionPrompt: PromptObject;
|
|
37
|
+
/**
|
|
38
|
+
* Environments multiselect prompt
|
|
39
|
+
*/
|
|
40
|
+
export declare const environmentsPrompt: PromptObject;
|
|
41
|
+
/**
|
|
42
|
+
* GitHub repository prompt - accepts various formats
|
|
43
|
+
*/
|
|
44
|
+
export declare const githubRepoPrompt: PromptObject;
|
|
45
|
+
/**
|
|
46
|
+
* GitHub Personal Access Token prompt
|
|
47
|
+
*/
|
|
48
|
+
export declare const githubTokenPrompt: PromptObject;
|
|
49
|
+
/**
|
|
50
|
+
* Runs the complete GitHub setup wizard
|
|
51
|
+
* @returns Configuration object or null if cancelled
|
|
52
|
+
*/
|
|
53
|
+
export declare function runGitHubSetupWizard(): Promise<GitHubSetupConfig | null>;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import prompts from 'prompts';
|
|
2
|
+
/**
|
|
3
|
+
* Validates kebab-case project name
|
|
4
|
+
*/
|
|
5
|
+
function isKebabCase(value) {
|
|
6
|
+
return /^[a-z][a-z0-9-]*[a-z0-9]$/.test(value) || /^[a-z]$/.test(value);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Project name prompt - used as prefix for IAM users
|
|
10
|
+
*/
|
|
11
|
+
export const projectNamePrompt = {
|
|
12
|
+
type: 'text',
|
|
13
|
+
name: 'projectName',
|
|
14
|
+
message: 'Project name (used as prefix for IAM users):',
|
|
15
|
+
validate: (value) => {
|
|
16
|
+
if (!value.trim())
|
|
17
|
+
return 'Project name is required';
|
|
18
|
+
if (value.length > 20)
|
|
19
|
+
return 'Project name must be 20 characters or less';
|
|
20
|
+
if (!isKebabCase(value))
|
|
21
|
+
return 'Project name must be kebab-case (e.g., my-app)';
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
format: (value) => value.trim().toLowerCase(),
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* AWS region selection prompt
|
|
28
|
+
*/
|
|
29
|
+
export const awsRegionPrompt = {
|
|
30
|
+
type: 'select',
|
|
31
|
+
name: 'awsRegion',
|
|
32
|
+
message: 'AWS Region:',
|
|
33
|
+
choices: [
|
|
34
|
+
{ title: 'US East (N. Virginia) - us-east-1', value: 'us-east-1' },
|
|
35
|
+
{ title: 'US West (Oregon) - us-west-2', value: 'us-west-2' },
|
|
36
|
+
{ title: 'EU (Ireland) - eu-west-1', value: 'eu-west-1' },
|
|
37
|
+
{ title: 'EU (Frankfurt) - eu-central-1', value: 'eu-central-1' },
|
|
38
|
+
{ title: 'Asia Pacific (Tokyo) - ap-northeast-1', value: 'ap-northeast-1' },
|
|
39
|
+
{ title: 'Asia Pacific (Sydney) - ap-southeast-2', value: 'ap-southeast-2' },
|
|
40
|
+
],
|
|
41
|
+
initial: 0,
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Environments multiselect prompt
|
|
45
|
+
*/
|
|
46
|
+
export const environmentsPrompt = {
|
|
47
|
+
type: 'multiselect',
|
|
48
|
+
name: 'environments',
|
|
49
|
+
message: 'Select environments to configure:',
|
|
50
|
+
choices: [
|
|
51
|
+
{ title: 'dev', value: 'dev', selected: true },
|
|
52
|
+
{ title: 'stage', value: 'stage', selected: true },
|
|
53
|
+
{ title: 'prod', value: 'prod', selected: true },
|
|
54
|
+
],
|
|
55
|
+
hint: '- Space to toggle, Enter to confirm',
|
|
56
|
+
min: 1,
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Validates 12-digit AWS account ID
|
|
60
|
+
*/
|
|
61
|
+
function isValidAccountId(value) {
|
|
62
|
+
return /^\d{12}$/.test(value);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates account ID prompt for a specific environment
|
|
66
|
+
*/
|
|
67
|
+
function createAccountIdPrompt(environment) {
|
|
68
|
+
return {
|
|
69
|
+
type: 'text',
|
|
70
|
+
name: `accountId_${environment}`,
|
|
71
|
+
message: `AWS Account ID for ${environment}:`,
|
|
72
|
+
validate: (value) => {
|
|
73
|
+
if (!value.trim())
|
|
74
|
+
return 'Account ID is required';
|
|
75
|
+
if (!isValidAccountId(value.trim()))
|
|
76
|
+
return 'Account ID must be a 12-digit number';
|
|
77
|
+
return true;
|
|
78
|
+
},
|
|
79
|
+
format: (value) => value.trim(),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates AWS profile prompt for a specific environment
|
|
84
|
+
*/
|
|
85
|
+
function createAwsProfilePrompt(environment) {
|
|
86
|
+
return {
|
|
87
|
+
type: 'text',
|
|
88
|
+
name: `awsProfile_${environment}`,
|
|
89
|
+
message: `AWS profile for ${environment} account:`,
|
|
90
|
+
initial: 'default',
|
|
91
|
+
format: (value) => value.trim() || 'default',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* GitHub repository prompt - accepts various formats
|
|
96
|
+
*/
|
|
97
|
+
export const githubRepoPrompt = {
|
|
98
|
+
type: 'text',
|
|
99
|
+
name: 'githubRepo',
|
|
100
|
+
message: 'GitHub repository (owner/repo or URL):',
|
|
101
|
+
validate: (value) => {
|
|
102
|
+
if (!value.trim())
|
|
103
|
+
return 'Repository is required';
|
|
104
|
+
// Try to parse the URL to validate format
|
|
105
|
+
const trimmed = value.trim();
|
|
106
|
+
const cleanUrl = trimmed.replace(/\/$/, '').replace(/\.git$/, '');
|
|
107
|
+
// Check supported formats
|
|
108
|
+
const httpsMatch = cleanUrl.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)$/);
|
|
109
|
+
const sshMatch = cleanUrl.match(/^git@github\.com:([^/]+)\/([^/]+)$/);
|
|
110
|
+
const shortMatch = cleanUrl.match(/^([^/]+)\/([^/]+)$/);
|
|
111
|
+
if (!httpsMatch && !sshMatch && !shortMatch) {
|
|
112
|
+
return 'Invalid format. Use: owner/repo, https://github.com/owner/repo, or git@github.com:owner/repo';
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
},
|
|
116
|
+
format: (value) => value.trim(),
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* GitHub Personal Access Token prompt
|
|
120
|
+
*/
|
|
121
|
+
export const githubTokenPrompt = {
|
|
122
|
+
type: 'password',
|
|
123
|
+
name: 'githubToken',
|
|
124
|
+
message: 'GitHub Personal Access Token (requires "repo" scope):',
|
|
125
|
+
validate: (value) => {
|
|
126
|
+
if (!value.trim())
|
|
127
|
+
return 'Token is required';
|
|
128
|
+
return true;
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Parses GitHub repository string to owner/repo
|
|
133
|
+
*/
|
|
134
|
+
function parseGitHubRepo(url) {
|
|
135
|
+
const cleanUrl = url.trim().replace(/\/$/, '').replace(/\.git$/, '');
|
|
136
|
+
// Format: https://github.com/owner/repo
|
|
137
|
+
const httpsMatch = cleanUrl.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+)$/);
|
|
138
|
+
if (httpsMatch) {
|
|
139
|
+
return { owner: httpsMatch[1], repo: httpsMatch[2] };
|
|
140
|
+
}
|
|
141
|
+
// Format: git@github.com:owner/repo
|
|
142
|
+
const sshMatch = cleanUrl.match(/^git@github\.com:([^/]+)\/([^/]+)$/);
|
|
143
|
+
if (sshMatch) {
|
|
144
|
+
return { owner: sshMatch[1], repo: sshMatch[2] };
|
|
145
|
+
}
|
|
146
|
+
// Format: owner/repo
|
|
147
|
+
const shortMatch = cleanUrl.match(/^([^/]+)\/([^/]+)$/);
|
|
148
|
+
if (shortMatch) {
|
|
149
|
+
return { owner: shortMatch[1], repo: shortMatch[2] };
|
|
150
|
+
}
|
|
151
|
+
throw new Error(`Unable to parse GitHub URL: ${url}`);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Runs the complete GitHub setup wizard
|
|
155
|
+
* @returns Configuration object or null if cancelled
|
|
156
|
+
*/
|
|
157
|
+
export async function runGitHubSetupWizard() {
|
|
158
|
+
let cancelled = false;
|
|
159
|
+
const onCancel = () => {
|
|
160
|
+
cancelled = true;
|
|
161
|
+
return false;
|
|
162
|
+
};
|
|
163
|
+
// Step 1: Basic configuration
|
|
164
|
+
const basicResponse = await prompts([projectNamePrompt, awsRegionPrompt, environmentsPrompt], { onCancel });
|
|
165
|
+
if (cancelled || !basicResponse.projectName || !basicResponse.environments?.length) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const selectedEnvironments = basicResponse.environments;
|
|
169
|
+
// Step 2: Account IDs and AWS profiles for each environment
|
|
170
|
+
const environmentPrompts = [];
|
|
171
|
+
for (const env of selectedEnvironments) {
|
|
172
|
+
environmentPrompts.push(createAccountIdPrompt(env));
|
|
173
|
+
environmentPrompts.push(createAwsProfilePrompt(env));
|
|
174
|
+
}
|
|
175
|
+
const environmentResponse = await prompts(environmentPrompts, { onCancel });
|
|
176
|
+
if (cancelled) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
// Validate all environment data was collected
|
|
180
|
+
for (const env of selectedEnvironments) {
|
|
181
|
+
if (!environmentResponse[`accountId_${env}`]) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Step 3: GitHub configuration
|
|
186
|
+
const githubResponse = await prompts([githubRepoPrompt, githubTokenPrompt], { onCancel });
|
|
187
|
+
if (cancelled || !githubResponse.githubRepo || !githubResponse.githubToken) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
// Parse GitHub repo
|
|
191
|
+
const { owner, repo } = parseGitHubRepo(githubResponse.githubRepo);
|
|
192
|
+
// Build environments array
|
|
193
|
+
const environments = selectedEnvironments.map((env) => ({
|
|
194
|
+
environment: env,
|
|
195
|
+
accountId: environmentResponse[`accountId_${env}`],
|
|
196
|
+
awsProfile: environmentResponse[`awsProfile_${env}`] || 'default',
|
|
197
|
+
}));
|
|
198
|
+
return {
|
|
199
|
+
projectName: basicResponse.projectName,
|
|
200
|
+
awsRegion: basicResponse.awsRegion,
|
|
201
|
+
environments,
|
|
202
|
+
github: {
|
|
203
|
+
owner,
|
|
204
|
+
repo,
|
|
205
|
+
token: githubResponse.githubToken,
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PromptObject } from 'prompts';
|
|
2
|
+
export declare const enableOrgPrompt: PromptObject;
|
|
3
|
+
export declare const orgNamePrompt: PromptObject;
|
|
4
|
+
export declare const orgEnvironmentsPrompt: PromptObject;
|
|
5
|
+
export declare const devEmailPrompt: PromptObject;
|
|
6
|
+
export declare const stageEmailPrompt: PromptObject;
|
|
7
|
+
export declare const prodEmailPrompt: PromptObject;
|
|
8
|
+
export declare const qaEmailPrompt: PromptObject;
|
|
9
|
+
export declare const sandboxEmailPrompt: PromptObject;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
export const enableOrgPrompt = {
|
|
3
|
+
type: 'select',
|
|
4
|
+
name: 'enableOrg',
|
|
5
|
+
message: 'Set up AWS Organizations with separate accounts per environment?',
|
|
6
|
+
choices: [
|
|
7
|
+
{ title: `${pc.yellow('○')} No (single account)`, value: false },
|
|
8
|
+
{ title: `${pc.cyan('◆')} Yes (multi-account)`, value: true },
|
|
9
|
+
],
|
|
10
|
+
initial: 0,
|
|
11
|
+
hint: '- Creates separate AWS accounts for each environment'
|
|
12
|
+
};
|
|
13
|
+
export const orgNamePrompt = {
|
|
14
|
+
type: (prev) => prev ? 'text' : null,
|
|
15
|
+
name: 'orgName',
|
|
16
|
+
message: 'Organization name:',
|
|
17
|
+
initial: (_prev, values) => `${values.projectName}-org`,
|
|
18
|
+
validate: (value) => value.trim().length > 0 || 'Organization name is required'
|
|
19
|
+
};
|
|
20
|
+
export const orgEnvironmentsPrompt = {
|
|
21
|
+
type: (_prev, values) => values.enableOrg ? 'multiselect' : null,
|
|
22
|
+
name: 'orgEnvironments',
|
|
23
|
+
message: 'Select environments to create accounts for:',
|
|
24
|
+
choices: [
|
|
25
|
+
{ title: 'dev', value: 'dev', selected: true },
|
|
26
|
+
{ title: 'stage', value: 'stage', selected: true },
|
|
27
|
+
{ title: 'prod', value: 'prod', selected: true },
|
|
28
|
+
{ title: 'qa', value: 'qa', selected: false },
|
|
29
|
+
{ title: 'sandbox', value: 'sandbox', selected: false },
|
|
30
|
+
],
|
|
31
|
+
hint: '- Space to toggle, Enter to confirm',
|
|
32
|
+
min: 1
|
|
33
|
+
};
|
|
34
|
+
export const devEmailPrompt = {
|
|
35
|
+
type: (_prev, values) => values.enableOrg && values.orgEnvironments?.includes('dev') ? 'text' : null,
|
|
36
|
+
name: 'devEmail',
|
|
37
|
+
message: 'Dev account root email:',
|
|
38
|
+
validate: (value) => {
|
|
39
|
+
if (!value.trim())
|
|
40
|
+
return 'Email is required';
|
|
41
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
42
|
+
return 'Invalid email format';
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export const stageEmailPrompt = {
|
|
47
|
+
type: (_prev, values) => values.enableOrg && values.orgEnvironments?.includes('stage') ? 'text' : null,
|
|
48
|
+
name: 'stageEmail',
|
|
49
|
+
message: 'Stage account root email:',
|
|
50
|
+
validate: (value) => {
|
|
51
|
+
if (!value.trim())
|
|
52
|
+
return 'Email is required';
|
|
53
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
54
|
+
return 'Invalid email format';
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
export const prodEmailPrompt = {
|
|
59
|
+
type: (_prev, values) => values.enableOrg && values.orgEnvironments?.includes('prod') ? 'text' : null,
|
|
60
|
+
name: 'prodEmail',
|
|
61
|
+
message: 'Prod account root email:',
|
|
62
|
+
validate: (value) => {
|
|
63
|
+
if (!value.trim())
|
|
64
|
+
return 'Email is required';
|
|
65
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
66
|
+
return 'Invalid email format';
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
export const qaEmailPrompt = {
|
|
71
|
+
type: (_prev, values) => values.enableOrg && values.orgEnvironments?.includes('qa') ? 'text' : null,
|
|
72
|
+
name: 'qaEmail',
|
|
73
|
+
message: 'QA account root email:',
|
|
74
|
+
validate: (value) => {
|
|
75
|
+
if (!value.trim())
|
|
76
|
+
return 'Email is required';
|
|
77
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
78
|
+
return 'Invalid email format';
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
export const sandboxEmailPrompt = {
|
|
83
|
+
type: (_prev, values) => values.enableOrg && values.orgEnvironments?.includes('sandbox') ? 'text' : null,
|
|
84
|
+
name: 'sandboxEmail',
|
|
85
|
+
message: 'Sandbox account root email:',
|
|
86
|
+
validate: (value) => {
|
|
87
|
+
if (!value.trim())
|
|
88
|
+
return 'Email is required';
|
|
89
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
|
|
90
|
+
return 'Invalid email format';
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const platformsPrompt = {
|
|
2
|
+
type: 'multiselect',
|
|
3
|
+
name: 'platforms',
|
|
4
|
+
message: 'Select platforms (space to toggle, enter to confirm):',
|
|
5
|
+
choices: [
|
|
6
|
+
{ title: 'Web (React + Vite + Chakra UI)', value: 'web', selected: true },
|
|
7
|
+
{ title: 'Mobile (React Native + Expo)', value: 'mobile' },
|
|
8
|
+
{ title: 'API (AWS Lambda + DynamoDB)', value: 'api', selected: true }
|
|
9
|
+
],
|
|
10
|
+
min: 1,
|
|
11
|
+
hint: '- At least one required'
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
export const themePrompt = {
|
|
3
|
+
type: 'select',
|
|
4
|
+
name: 'brandColor',
|
|
5
|
+
message: 'Choose your brand color:',
|
|
6
|
+
choices: [
|
|
7
|
+
{ title: `${pc.blue('●')} Blue`, value: 'blue' },
|
|
8
|
+
{ title: `${pc.magenta('●')} Purple`, value: 'purple' },
|
|
9
|
+
{ title: `${pc.cyan('●')} Teal`, value: 'teal' },
|
|
10
|
+
{ title: `${pc.green('●')} Green`, value: 'green' },
|
|
11
|
+
{ title: `${pc.yellow('●')} Orange`, value: 'orange' }
|
|
12
|
+
],
|
|
13
|
+
initial: 0
|
|
14
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { TOKENS, TOKEN_PATTERN } from './tokens.js';
|
|
2
|
+
export type { TokenName } from './tokens.js';
|
|
3
|
+
export type { TokenValues, Platform, TemplateFile, TemplateManifest, DeriveTokenValues, } from './types.js';
|
|
4
|
+
export { deriveTokenValues, templateManifest } from './manifest.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProjectConfig } from '../types.js';
|
|
2
|
+
import type { TokenValues, TemplateManifest } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Derive all token values from user's ProjectConfig
|
|
5
|
+
*/
|
|
6
|
+
export declare function deriveTokenValues(config: ProjectConfig): TokenValues;
|
|
7
|
+
/**
|
|
8
|
+
* Template manifest defining shared and platform-specific files
|
|
9
|
+
* This matches the structure in templates/manifest.json
|
|
10
|
+
*/
|
|
11
|
+
export declare const templateManifest: TemplateManifest;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert kebab-case to PascalCase
|
|
3
|
+
* my-awesome-app -> MyAwesomeApp
|
|
4
|
+
*/
|
|
5
|
+
function toPascalCase(str) {
|
|
6
|
+
return str
|
|
7
|
+
.split('-')
|
|
8
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
9
|
+
.join('');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Convert kebab-case to Title Case
|
|
13
|
+
* my-awesome-app -> My Awesome App
|
|
14
|
+
*/
|
|
15
|
+
function toTitleCase(str) {
|
|
16
|
+
return str
|
|
17
|
+
.split('-')
|
|
18
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
19
|
+
.join(' ');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Find account ID for a specific environment name
|
|
23
|
+
*/
|
|
24
|
+
function findAccountIdByEnvironment(accounts, environment) {
|
|
25
|
+
const account = accounts?.find((a) => a.environment.toLowerCase() === environment.toLowerCase());
|
|
26
|
+
return account?.accountId ?? '';
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Derive all token values from user's ProjectConfig
|
|
30
|
+
*/
|
|
31
|
+
export function deriveTokenValues(config) {
|
|
32
|
+
// Build organization accounts JSON for flexible environment handling
|
|
33
|
+
const orgAccounts = config.org?.accounts?.map((a) => ({
|
|
34
|
+
environment: a.environment,
|
|
35
|
+
accountId: a.accountId ?? '',
|
|
36
|
+
})) ?? [];
|
|
37
|
+
return {
|
|
38
|
+
PROJECT_NAME: config.projectName,
|
|
39
|
+
PROJECT_NAME_PASCAL: toPascalCase(config.projectName),
|
|
40
|
+
PROJECT_NAME_TITLE: toTitleCase(config.projectName),
|
|
41
|
+
AWS_REGION: config.awsRegion,
|
|
42
|
+
PACKAGE_SCOPE: `@${config.projectName}`,
|
|
43
|
+
BRAND_COLOR: config.brandColor,
|
|
44
|
+
AUTH_COGNITO: config.auth.provider === 'cognito' ? 'true' : 'false',
|
|
45
|
+
AUTH_AUTH0: config.auth.provider === 'auth0' ? 'true' : 'false',
|
|
46
|
+
AUTH_SOCIAL_LOGIN: config.auth.features.includes('social-login') ? 'true' : 'false',
|
|
47
|
+
AUTH_MFA: config.auth.features.includes('mfa') ? 'true' : 'false',
|
|
48
|
+
// Organization tokens
|
|
49
|
+
ORG_ENABLED: config.org?.enabled ? 'true' : 'false',
|
|
50
|
+
ORG_NAME: config.org?.organizationName ?? '',
|
|
51
|
+
ORG_ACCOUNTS_JSON: JSON.stringify(orgAccounts),
|
|
52
|
+
// Common environment account IDs for backward compatibility
|
|
53
|
+
DEV_ACCOUNT_ID: findAccountIdByEnvironment(config.org?.accounts, 'dev'),
|
|
54
|
+
STAGE_ACCOUNT_ID: findAccountIdByEnvironment(config.org?.accounts, 'stage'),
|
|
55
|
+
PROD_ACCOUNT_ID: findAccountIdByEnvironment(config.org?.accounts, 'prod'),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Template manifest defining shared and platform-specific files
|
|
60
|
+
* This matches the structure in templates/manifest.json
|
|
61
|
+
*/
|
|
62
|
+
export const templateManifest = {
|
|
63
|
+
shared: [
|
|
64
|
+
{ src: 'root/package.json', dest: 'package.json' },
|
|
65
|
+
{ src: 'root/tsconfig.base.json', dest: 'tsconfig.base.json' },
|
|
66
|
+
{ src: 'root/nx.json', dest: 'nx.json' },
|
|
67
|
+
{ src: 'root/jest.preset.js', dest: 'jest.preset.js' },
|
|
68
|
+
{ src: 'root/eslint.config.js', dest: 'eslint.config.js' },
|
|
69
|
+
{ src: 'root/.npmrc', dest: '.npmrc' },
|
|
70
|
+
{ src: 'root/.nvmrc', dest: '.nvmrc' },
|
|
71
|
+
{ src: 'root/.editorconfig', dest: '.editorconfig' },
|
|
72
|
+
{ src: 'root/.gitignore', dest: '.gitignore' },
|
|
73
|
+
{ src: 'packages/common-types', dest: 'packages/common-types' },
|
|
74
|
+
{ src: 'packages/api-client', dest: 'packages/api-client' },
|
|
75
|
+
],
|
|
76
|
+
byPlatform: {
|
|
77
|
+
web: [{ src: 'apps/web', dest: 'apps/web' }],
|
|
78
|
+
mobile: [{ src: 'apps/mobile', dest: 'apps/mobile' }],
|
|
79
|
+
api: [{ src: 'apps/api', dest: 'apps/api' }],
|
|
80
|
+
},
|
|
81
|
+
byFeature: {
|
|
82
|
+
'github-actions': [{ src: '.github', dest: '.github' }],
|
|
83
|
+
'vscode-config': [{ src: '.vscode', dest: '.vscode' }],
|
|
84
|
+
},
|
|
85
|
+
byAuthProvider: {
|
|
86
|
+
cognito: [
|
|
87
|
+
{ src: 'apps/api/cdk/auth', dest: 'apps/api/cdk/auth' },
|
|
88
|
+
{ src: 'apps/web/src/auth/cognito-provider.tsx', dest: 'apps/web/src/auth/cognito-provider.tsx' },
|
|
89
|
+
{ src: 'apps/web/src/config/amplify-config.ts', dest: 'apps/web/src/config/amplify-config.ts' },
|
|
90
|
+
{ src: 'apps/api/src/middleware/cognito-auth.ts', dest: 'apps/api/src/middleware/cognito-auth.ts' },
|
|
91
|
+
],
|
|
92
|
+
auth0: [
|
|
93
|
+
{ src: 'apps/web/src/auth/auth0-provider.tsx', dest: 'apps/web/src/auth/auth0-provider.tsx' },
|
|
94
|
+
{ src: 'apps/web/src/config/auth0-config.ts', dest: 'apps/web/src/config/auth0-config.ts' },
|
|
95
|
+
{ src: 'apps/api/src/middleware/auth0-auth.ts', dest: 'apps/api/src/middleware/auth0-auth.ts' },
|
|
96
|
+
],
|
|
97
|
+
none: [],
|
|
98
|
+
},
|
|
99
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Token Constants
|
|
3
|
+
*
|
|
4
|
+
* Placeholder tokens used throughout template files for project customization.
|
|
5
|
+
* Uses double-brace syntax {{TOKEN}} because:
|
|
6
|
+
* - Distinct from JS template literals (${}), EJS (<%%>), Mustache ({{}})
|
|
7
|
+
* - Easy to search/replace with simple regex
|
|
8
|
+
* - Visible in any file type (JSON, TS, MD)
|
|
9
|
+
*/
|
|
10
|
+
export declare const TOKENS: {
|
|
11
|
+
/** Project name in kebab-case (e.g., my-awesome-app) */
|
|
12
|
+
readonly PROJECT_NAME: "{{PROJECT_NAME}}";
|
|
13
|
+
/** Project name in PascalCase for class names, stack names (e.g., MyAwesomeApp) */
|
|
14
|
+
readonly PROJECT_NAME_PASCAL: "{{PROJECT_NAME_PASCAL}}";
|
|
15
|
+
/** Project name in Title Case for display (e.g., My Awesome App) */
|
|
16
|
+
readonly PROJECT_NAME_TITLE: "{{PROJECT_NAME_TITLE}}";
|
|
17
|
+
/** AWS region (e.g., us-east-1) */
|
|
18
|
+
readonly AWS_REGION: "{{AWS_REGION}}";
|
|
19
|
+
/** Package scope derived from project name (e.g., @my-awesome-app) */
|
|
20
|
+
readonly PACKAGE_SCOPE: "{{PACKAGE_SCOPE}}";
|
|
21
|
+
/** Brand color for theme (e.g., blue, purple, teal, green, orange) */
|
|
22
|
+
readonly BRAND_COLOR: "{{BRAND_COLOR}}";
|
|
23
|
+
/** Organization enabled flag ('true' or 'false') */
|
|
24
|
+
readonly ORG_ENABLED: "{{ORG_ENABLED}}";
|
|
25
|
+
/** Organization name */
|
|
26
|
+
readonly ORG_NAME: "{{ORG_NAME}}";
|
|
27
|
+
/** JSON array of {environment, accountId} objects for flexible environment handling */
|
|
28
|
+
readonly ORG_ACCOUNTS_JSON: "{{ORG_ACCOUNTS_JSON}}";
|
|
29
|
+
/** Development environment AWS Account ID (empty if not selected) */
|
|
30
|
+
readonly DEV_ACCOUNT_ID: "{{DEV_ACCOUNT_ID}}";
|
|
31
|
+
/** Staging environment AWS Account ID (empty if not selected) */
|
|
32
|
+
readonly STAGE_ACCOUNT_ID: "{{STAGE_ACCOUNT_ID}}";
|
|
33
|
+
/** Production environment AWS Account ID (empty if not selected) */
|
|
34
|
+
readonly PROD_ACCOUNT_ID: "{{PROD_ACCOUNT_ID}}";
|
|
35
|
+
};
|
|
36
|
+
/** Regex pattern to match any {{TOKEN_NAME}} placeholder */
|
|
37
|
+
export declare const TOKEN_PATTERN: RegExp;
|
|
38
|
+
/** Type representing valid token names */
|
|
39
|
+
export type TokenName = keyof typeof TOKENS;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Token Constants
|
|
3
|
+
*
|
|
4
|
+
* Placeholder tokens used throughout template files for project customization.
|
|
5
|
+
* Uses double-brace syntax {{TOKEN}} because:
|
|
6
|
+
* - Distinct from JS template literals (${}), EJS (<%%>), Mustache ({{}})
|
|
7
|
+
* - Easy to search/replace with simple regex
|
|
8
|
+
* - Visible in any file type (JSON, TS, MD)
|
|
9
|
+
*/
|
|
10
|
+
export const TOKENS = {
|
|
11
|
+
/** Project name in kebab-case (e.g., my-awesome-app) */
|
|
12
|
+
PROJECT_NAME: '{{PROJECT_NAME}}',
|
|
13
|
+
/** Project name in PascalCase for class names, stack names (e.g., MyAwesomeApp) */
|
|
14
|
+
PROJECT_NAME_PASCAL: '{{PROJECT_NAME_PASCAL}}',
|
|
15
|
+
/** Project name in Title Case for display (e.g., My Awesome App) */
|
|
16
|
+
PROJECT_NAME_TITLE: '{{PROJECT_NAME_TITLE}}',
|
|
17
|
+
/** AWS region (e.g., us-east-1) */
|
|
18
|
+
AWS_REGION: '{{AWS_REGION}}',
|
|
19
|
+
/** Package scope derived from project name (e.g., @my-awesome-app) */
|
|
20
|
+
PACKAGE_SCOPE: '{{PACKAGE_SCOPE}}',
|
|
21
|
+
/** Brand color for theme (e.g., blue, purple, teal, green, orange) */
|
|
22
|
+
BRAND_COLOR: '{{BRAND_COLOR}}',
|
|
23
|
+
/** Organization enabled flag ('true' or 'false') */
|
|
24
|
+
ORG_ENABLED: '{{ORG_ENABLED}}',
|
|
25
|
+
/** Organization name */
|
|
26
|
+
ORG_NAME: '{{ORG_NAME}}',
|
|
27
|
+
/** JSON array of {environment, accountId} objects for flexible environment handling */
|
|
28
|
+
ORG_ACCOUNTS_JSON: '{{ORG_ACCOUNTS_JSON}}',
|
|
29
|
+
/** Development environment AWS Account ID (empty if not selected) */
|
|
30
|
+
DEV_ACCOUNT_ID: '{{DEV_ACCOUNT_ID}}',
|
|
31
|
+
/** Staging environment AWS Account ID (empty if not selected) */
|
|
32
|
+
STAGE_ACCOUNT_ID: '{{STAGE_ACCOUNT_ID}}',
|
|
33
|
+
/** Production environment AWS Account ID (empty if not selected) */
|
|
34
|
+
PROD_ACCOUNT_ID: '{{PROD_ACCOUNT_ID}}',
|
|
35
|
+
};
|
|
36
|
+
/** Regex pattern to match any {{TOKEN_NAME}} placeholder */
|
|
37
|
+
export const TOKEN_PATTERN = /\{\{([A-Z_]+)\}\}/g;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ProjectConfig, Feature, AuthProvider } from '../types.js';
|
|
2
|
+
/** Mapping of token names to their replacement values */
|
|
3
|
+
export interface TokenValues {
|
|
4
|
+
PROJECT_NAME: string;
|
|
5
|
+
PROJECT_NAME_PASCAL: string;
|
|
6
|
+
PROJECT_NAME_TITLE: string;
|
|
7
|
+
AWS_REGION: string;
|
|
8
|
+
PACKAGE_SCOPE: string;
|
|
9
|
+
BRAND_COLOR: string;
|
|
10
|
+
AUTH_COGNITO: string;
|
|
11
|
+
AUTH_AUTH0: string;
|
|
12
|
+
AUTH_SOCIAL_LOGIN: string;
|
|
13
|
+
AUTH_MFA: string;
|
|
14
|
+
/** Organization enabled flag ('true' or 'false') */
|
|
15
|
+
ORG_ENABLED?: string;
|
|
16
|
+
/** Organization name */
|
|
17
|
+
ORG_NAME?: string;
|
|
18
|
+
/** JSON array of {environment, accountId} objects for templates needing full list */
|
|
19
|
+
ORG_ACCOUNTS_JSON?: string;
|
|
20
|
+
/** Development environment AWS Account ID (empty if not selected) */
|
|
21
|
+
DEV_ACCOUNT_ID?: string;
|
|
22
|
+
/** Staging environment AWS Account ID (empty if not selected) */
|
|
23
|
+
STAGE_ACCOUNT_ID?: string;
|
|
24
|
+
/** Production environment AWS Account ID (empty if not selected) */
|
|
25
|
+
PROD_ACCOUNT_ID?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Platform identifiers for conditional templates */
|
|
28
|
+
export type Platform = 'web' | 'mobile' | 'api';
|
|
29
|
+
/** A single template file entry */
|
|
30
|
+
export interface TemplateFile {
|
|
31
|
+
/** Source path relative to templates/ directory */
|
|
32
|
+
src: string;
|
|
33
|
+
/** Destination path relative to output directory (may contain tokens) */
|
|
34
|
+
dest: string;
|
|
35
|
+
/** Which platforms this file belongs to (undefined = all platforms) */
|
|
36
|
+
platforms?: Platform[];
|
|
37
|
+
}
|
|
38
|
+
/** Complete template manifest */
|
|
39
|
+
export interface TemplateManifest {
|
|
40
|
+
/** Files that are always included */
|
|
41
|
+
shared: TemplateFile[];
|
|
42
|
+
/** Files grouped by platform */
|
|
43
|
+
byPlatform: Record<Platform, TemplateFile[]>;
|
|
44
|
+
/** Files grouped by feature */
|
|
45
|
+
byFeature: Record<Feature, TemplateFile[]>;
|
|
46
|
+
/** Files grouped by auth provider */
|
|
47
|
+
byAuthProvider: Record<AuthProvider, TemplateFile[]>;
|
|
48
|
+
}
|
|
49
|
+
/** Function to derive token values from ProjectConfig */
|
|
50
|
+
export type DeriveTokenValues = (config: ProjectConfig) => TokenValues;
|
|
51
|
+
/** Re-export Feature and AuthProvider types for convenience */
|
|
52
|
+
export type { Feature, AuthProvider };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|