@tanstack/cta-engine 0.10.0-alpha.19 → 0.10.0-alpha.21

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.
Files changed (69) hide show
  1. package/dist/add-ons.js +5 -14
  2. package/dist/add-to-app.js +118 -74
  3. package/dist/config-file.js +9 -7
  4. package/dist/create-app.js +112 -34
  5. package/dist/custom-add-ons/add-on.js +175 -0
  6. package/dist/custom-add-ons/shared.js +117 -0
  7. package/dist/custom-add-ons/starter.js +84 -0
  8. package/dist/environment.js +59 -12
  9. package/dist/file-helpers.js +108 -2
  10. package/dist/frameworks.js +15 -1
  11. package/dist/index.js +12 -5
  12. package/dist/integrations/shadcn.js +10 -4
  13. package/dist/options.js +9 -0
  14. package/dist/package-json.js +7 -4
  15. package/dist/special-steps/index.js +24 -0
  16. package/dist/special-steps/rimraf-node-modules.js +16 -0
  17. package/dist/template-file.js +3 -13
  18. package/dist/types/add-ons.d.ts +3 -4
  19. package/dist/types/add-to-app.d.ts +16 -3
  20. package/dist/types/config-file.d.ts +4 -3
  21. package/dist/types/create-app.d.ts +1 -7
  22. package/dist/types/custom-add-ons/add-on.d.ts +69 -0
  23. package/dist/types/custom-add-ons/shared.d.ts +15 -0
  24. package/dist/types/custom-add-ons/starter.d.ts +7 -0
  25. package/dist/types/environment.d.ts +2 -1
  26. package/dist/types/file-helpers.d.ts +10 -0
  27. package/dist/types/frameworks.d.ts +2 -0
  28. package/dist/types/index.d.ts +13 -6
  29. package/dist/types/integrations/shadcn.d.ts +1 -1
  30. package/dist/types/options.d.ts +2 -0
  31. package/dist/types/package-json.d.ts +5 -0
  32. package/dist/types/package-manager.d.ts +6 -2
  33. package/dist/types/special-steps/index.d.ts +2 -0
  34. package/dist/types/special-steps/rimraf-node-modules.d.ts +2 -0
  35. package/dist/types/template-file.d.ts +1 -1
  36. package/dist/types/types.d.ts +752 -70
  37. package/dist/types.js +65 -1
  38. package/package.json +9 -3
  39. package/src/add-ons.ts +7 -19
  40. package/src/add-to-app.ts +196 -102
  41. package/src/config-file.ts +16 -13
  42. package/src/create-app.ts +129 -75
  43. package/src/custom-add-ons/add-on.ts +261 -0
  44. package/src/custom-add-ons/shared.ts +161 -0
  45. package/src/custom-add-ons/starter.ts +126 -0
  46. package/src/environment.ts +70 -11
  47. package/src/file-helpers.ts +164 -2
  48. package/src/frameworks.ts +21 -1
  49. package/src/index.ts +46 -11
  50. package/src/integrations/shadcn.ts +14 -4
  51. package/src/options.ts +11 -0
  52. package/src/package-json.ts +13 -6
  53. package/src/special-steps/index.ts +36 -0
  54. package/src/special-steps/rimraf-node-modules.ts +25 -0
  55. package/src/template-file.ts +3 -18
  56. package/src/types.ts +143 -85
  57. package/tests/add-ons.test.ts +5 -5
  58. package/tests/add-to-app.test.ts +358 -0
  59. package/tests/config-file.test.ts +15 -11
  60. package/tests/create-app.test.ts +43 -67
  61. package/tests/custom-add-ons/add-on.test.ts +12 -0
  62. package/tests/custom-add-ons/shared.test.ts +257 -0
  63. package/tests/custom-add-ons/starter.test.ts +58 -0
  64. package/tests/environment.test.ts +19 -0
  65. package/tests/integrations/shadcn.test.ts +48 -63
  66. package/tests/options.test.ts +42 -0
  67. package/tests/setupVitest.ts +6 -0
  68. package/tests/template-file.test.ts +54 -91
  69. package/vitest.config.ts +2 -0
package/src/index.ts CHANGED
@@ -1,42 +1,77 @@
1
1
  export { createApp } from './create-app.js'
2
2
  export { addToApp } from './add-to-app.js'
3
3
 
4
- export { finalizeAddOns, getAllAddOns, loadRemoteAddOn } from './add-ons.js'
4
+ export { finalizeAddOns, getAllAddOns } from './add-ons.js'
5
+
6
+ export { loadRemoteAddOn } from './custom-add-ons/add-on.js'
7
+ export { loadStarter } from './custom-add-ons/starter.js'
8
+
5
9
  export {
6
10
  createMemoryEnvironment,
7
11
  createDefaultEnvironment,
8
12
  } from './environment.js'
13
+
9
14
  export { CODE_ROUTER, CONFIG_FILE, FILE_ROUTER } from './constants.js'
15
+
10
16
  export {
11
17
  DEFAULT_PACKAGE_MANAGER,
12
18
  SUPPORTED_PACKAGE_MANAGERS,
13
19
  getPackageManager,
14
- getPackageManagerInstallCommand,
15
- getPackageManagerExecuteCommand,
16
- getPackageManagerScriptCommand,
17
- packageManagerInstall,
18
- packageManagerExecute,
19
20
  } from './package-manager.js'
21
+
20
22
  export {
21
23
  registerFramework,
22
24
  getFrameworkById,
23
25
  getFrameworkByName,
24
26
  getFrameworks,
25
27
  } from './frameworks.js'
26
- export { formatCommand, jsSafeName, sortObject } from './utils.js'
27
- export { writeConfigFile, readConfigFile } from './config-file.js'
28
- export { readFileHelper, getBinaryFile, relativePath } from './file-helpers.js'
28
+
29
+ export {
30
+ writeConfigFileToEnvironment,
31
+ readConfigFileFromEnvironment,
32
+ } from './config-file.js'
33
+
34
+ export {
35
+ cleanUpFiles,
36
+ cleanUpFileArray,
37
+ readFileHelper,
38
+ getBinaryFile,
39
+ recursivelyGatherFiles,
40
+ relativePath,
41
+ } from './file-helpers.js'
42
+
43
+ export { formatCommand } from './utils.js'
44
+
45
+ export { initStarter, compileStarter } from './custom-add-ons/starter.js'
46
+ export { initAddOn, compileAddOn } from './custom-add-ons/add-on.js'
47
+ export {
48
+ createAppOptionsFromPersisted,
49
+ createSerializedOptionsFromPersisted,
50
+ } from './custom-add-ons/shared.js'
51
+
52
+ export { createSerializedOptions } from './options.js'
53
+
54
+ export {
55
+ StarterCompiledSchema,
56
+ StatusEvent,
57
+ StatusStepType,
58
+ StopEvent,
59
+ AddOnCompiledSchema,
60
+ AddOnInfoSchema,
61
+ IntegrationSchema,
62
+ } from './types.js'
29
63
 
30
64
  export type {
31
65
  AddOn,
32
66
  Environment,
33
67
  FileBundleHandler,
68
+ Framework,
34
69
  FrameworkDefinition,
35
70
  Mode,
36
71
  Options,
72
+ SerializedOptions,
37
73
  Starter,
38
- TemplateOptions,
39
- Variable,
74
+ StarterCompiled,
40
75
  } from './types.js'
41
76
  export type { PersistedOptions } from './config-file.js'
42
77
  export type { PackageManager } from './package-manager.js'
@@ -6,9 +6,8 @@ export async function installShadcnComponents(
6
6
  environment: Environment,
7
7
  targetDir: string,
8
8
  options: Options,
9
- silent: boolean,
10
9
  ) {
11
- const s = silent ? null : environment.spinner()
10
+ const s = environment.spinner()
12
11
 
13
12
  if (options.chosenAddOns.find((a) => a.id === 'shadcn')) {
14
13
  const shadcnComponents = new Set<string>()
@@ -28,9 +27,15 @@ export async function installShadcnComponents(
28
27
  }
29
28
 
30
29
  if (shadcnComponents.size > 0) {
31
- s?.start(
30
+ s.start(
32
31
  `Installing shadcn components (${Array.from(shadcnComponents).join(', ')})...`,
33
32
  )
33
+ environment.startStep({
34
+ id: 'install-shadcn-components',
35
+ type: 'command',
36
+ message: `Installing shadcn components (${Array.from(shadcnComponents).join(', ')})...`,
37
+ })
38
+
34
39
  await packageManagerExecute(
35
40
  environment,
36
41
  resolve(targetDir),
@@ -38,7 +43,12 @@ export async function installShadcnComponents(
38
43
  'shadcn@latest',
39
44
  ['add', '--silent', '--yes', ...Array.from(shadcnComponents)],
40
45
  )
41
- s?.stop(`Installed additional shadcn components`)
46
+
47
+ environment.finishStep(
48
+ 'install-shadcn-components',
49
+ 'Shadcn components installed',
50
+ )
51
+ s.stop(`Installed additional shadcn components`)
42
52
  }
43
53
  }
44
54
  }
package/src/options.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { Options, SerializedOptions } from './types'
2
+
3
+ export const createSerializedOptions = (options: Options) => {
4
+ const serializedOptions: SerializedOptions = {
5
+ ...options,
6
+ chosenAddOns: options.chosenAddOns.map((addOn) => addOn.id),
7
+ framework: options.framework.id,
8
+ starter: options.starter?.id,
9
+ }
10
+ return serializedOptions
11
+ }
@@ -3,23 +3,23 @@ import { sortObject } from './utils.js'
3
3
 
4
4
  import type { Options } from './types.js'
5
5
 
6
- function mergePackageJSON(
6
+ export function mergePackageJSON(
7
7
  packageJSON: Record<string, any>,
8
- overlayPackageJSON: Record<string, any>,
8
+ overlayPackageJSON?: Record<string, any>,
9
9
  ) {
10
10
  return {
11
11
  ...packageJSON,
12
12
  dependencies: {
13
13
  ...packageJSON.dependencies,
14
- ...overlayPackageJSON.dependencies,
14
+ ...(overlayPackageJSON?.dependencies || {}),
15
15
  },
16
16
  devDependencies: {
17
17
  ...packageJSON.devDependencies,
18
- ...overlayPackageJSON.devDependencies,
18
+ ...(overlayPackageJSON?.devDependencies || {}),
19
19
  },
20
20
  scripts: {
21
21
  ...packageJSON.scripts,
22
- ...overlayPackageJSON.scripts,
22
+ ...(overlayPackageJSON?.scripts || {}),
23
23
  },
24
24
  }
25
25
  }
@@ -42,7 +42,7 @@ export function createPackageJSON(options: Options) {
42
42
  : undefined,
43
43
  ]
44
44
  for (const addition of additions.filter(Boolean)) {
45
- packageJSON = mergePackageJSON(packageJSON, addition!)
45
+ packageJSON = mergePackageJSON(packageJSON, addition)
46
46
  }
47
47
 
48
48
  for (const addOn of options.chosenAddOns.map(
@@ -51,6 +51,13 @@ export function createPackageJSON(options: Options) {
51
51
  packageJSON = mergePackageJSON(packageJSON, addOn)
52
52
  }
53
53
 
54
+ if (options.starter) {
55
+ packageJSON = mergePackageJSON(
56
+ packageJSON,
57
+ options.starter.packageAdditions,
58
+ )
59
+ }
60
+
54
61
  packageJSON.dependencies = sortObject(
55
62
  (packageJSON.dependencies ?? {}) as Record<string, string>,
56
63
  )
@@ -0,0 +1,36 @@
1
+ import { rimrafNodeModules } from './rimraf-node-modules.js'
2
+
3
+ import type { Environment, Options } from '../types.js'
4
+
5
+ const specialStepsLookup: Record<
6
+ string,
7
+ (environment: Environment, options: Options) => Promise<void>
8
+ > = {
9
+ 'rimraf-node-modules': rimrafNodeModules,
10
+ }
11
+
12
+ export async function runSpecialSteps(
13
+ environment: Environment,
14
+ options: Options,
15
+ specialSteps: Array<string>,
16
+ ) {
17
+ if (specialSteps.length) {
18
+ environment.startStep({
19
+ id: 'special-steps',
20
+ type: 'command',
21
+ message: 'Removing node_modules...',
22
+ })
23
+
24
+ for (const step of specialSteps) {
25
+ const stepFunction = specialStepsLookup[step]
26
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
27
+ if (stepFunction) {
28
+ await stepFunction(environment, options)
29
+ } else {
30
+ environment.error(`Special step ${step} not found`)
31
+ }
32
+ }
33
+
34
+ environment.finishStep('special-steps', 'Special steps complete')
35
+ }
36
+ }
@@ -0,0 +1,25 @@
1
+ import { resolve } from 'node:path'
2
+
3
+ import type { Environment, Options } from '../types.js'
4
+
5
+ const lockFiles = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']
6
+
7
+ export async function rimrafNodeModules(
8
+ environment: Environment,
9
+ options: Options,
10
+ ) {
11
+ environment.startStep({
12
+ id: 'special-steps',
13
+ type: 'command',
14
+ message: 'Removing node_modules...',
15
+ })
16
+
17
+ await environment.rimraf(resolve(options.targetDir, 'node_modules'))
18
+
19
+ for (const lockFile of lockFiles) {
20
+ const lockFilePath = resolve(options.targetDir, lockFile)
21
+ if (environment.exists(lockFilePath)) {
22
+ await environment.deleteFile(lockFilePath)
23
+ }
24
+ }
25
+ }
@@ -19,11 +19,7 @@ function convertDotFilesAndPaths(path: string) {
19
19
  .join('/')
20
20
  }
21
21
 
22
- export function createTemplateFile(
23
- environment: Environment,
24
- options: Options,
25
- targetDir: string,
26
- ) {
22
+ export function createTemplateFile(environment: Environment, options: Options) {
27
23
  function getPackageManagerAddScript(
28
24
  packageName: string,
29
25
  isDev: boolean = false,
@@ -71,16 +67,6 @@ export function createTemplateFile(
71
67
  }
72
68
  }
73
69
 
74
- const variables = {
75
- ...options.variableValues,
76
- ...options.chosenAddOns.reduce<Record<string, any>>((acc, addOn) => {
77
- return {
78
- ...acc,
79
- ...addOn.variables,
80
- }
81
- }, {}),
82
- }
83
-
84
70
  const addOnEnabled = options.chosenAddOns.reduce<Record<string, boolean>>(
85
71
  (acc, addOn) => {
86
72
  acc[addOn.id] = true
@@ -103,7 +89,6 @@ export function createTemplateFile(
103
89
  addOns: options.chosenAddOns,
104
90
  integrations,
105
91
  routes,
106
- variables,
107
92
 
108
93
  getPackageManagerAddScript,
109
94
  getPackageManagerRunScript,
@@ -157,9 +142,9 @@ export function createTemplateFile(
157
142
  }
158
143
 
159
144
  if (append) {
160
- await environment.appendFile(resolve(targetDir, target), content)
145
+ await environment.appendFile(resolve(options.targetDir, target), content)
161
146
  } else {
162
- await environment.writeFile(resolve(targetDir, target), content)
147
+ await environment.writeFile(resolve(options.targetDir, target), content)
163
148
  }
164
149
  }
165
150
  }
package/src/types.ts CHANGED
@@ -1,69 +1,110 @@
1
+ import z from 'zod'
2
+
1
3
  import type { CODE_ROUTER, FILE_ROUTER } from './constants.js'
2
4
  import type { PackageManager } from './package-manager.js'
3
5
 
4
- export type TemplateOptions = 'typescript' | 'javascript' | 'file-router'
5
-
6
6
  export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER
7
7
 
8
+ export type StatusStepType =
9
+ | 'file'
10
+ | 'command'
11
+ | 'info'
12
+ | 'package-manager'
13
+ | 'other'
14
+
15
+ export const AddOnBaseSchema = z.object({
16
+ id: z.string(),
17
+ name: z.string(),
18
+ description: z.string(),
19
+ author: z.string().optional(),
20
+ version: z.string().optional(),
21
+ link: z.string().optional(),
22
+ license: z.string().optional(),
23
+ warning: z.string().optional(),
24
+ type: z.enum(['add-on', 'example', 'starter', 'toolchain']),
25
+ command: z
26
+ .object({
27
+ command: z.string(),
28
+ args: z.array(z.string()).optional(),
29
+ })
30
+ .optional(),
31
+ routes: z
32
+ .array(
33
+ z.object({
34
+ url: z.string().optional(),
35
+ name: z.string().optional(),
36
+ path: z.string(),
37
+ jsName: z.string(),
38
+ }),
39
+ )
40
+ .optional(),
41
+ packageAdditions: z
42
+ .object({
43
+ dependencies: z.record(z.string(), z.string()).optional(),
44
+ devDependencies: z.record(z.string(), z.string()).optional(),
45
+ scripts: z.record(z.string(), z.string()).optional(),
46
+ })
47
+ .optional(),
48
+ shadcnComponents: z.array(z.string()).optional(),
49
+ dependsOn: z.array(z.string()).optional(),
50
+ smallLogo: z.string().optional(),
51
+ logo: z.string().optional(),
52
+ addOnSpecialSteps: z.array(z.string()).optional(),
53
+ createSpecialSteps: z.array(z.string()).optional(),
54
+ })
55
+
56
+ export const StarterSchema = AddOnBaseSchema.extend({
57
+ framework: z.string(),
58
+ mode: z.string(),
59
+ typescript: z.boolean(),
60
+ tailwind: z.boolean(),
61
+ banner: z.string().optional(),
62
+ })
63
+
64
+ export const StarterCompiledSchema = StarterSchema.extend({
65
+ files: z.record(z.string(), z.string()),
66
+ deletedFiles: z.array(z.string()),
67
+ })
68
+
69
+ export const IntegrationSchema = z.object({
70
+ type: z.string(),
71
+ path: z.string(),
72
+ jsName: z.string(),
73
+ })
74
+
75
+ export const AddOnInfoSchema = AddOnBaseSchema.extend({
76
+ modes: z.array(z.string()),
77
+ integrations: z.array(IntegrationSchema).optional(),
78
+ phase: z.enum(['setup', 'add-on']),
79
+ readme: z.string().optional(),
80
+ })
81
+
82
+ export const AddOnCompiledSchema = AddOnInfoSchema.extend({
83
+ files: z.record(z.string(), z.string()),
84
+ deletedFiles: z.array(z.string()),
85
+ })
86
+
87
+ export type Integration = z.infer<typeof IntegrationSchema>
88
+
89
+ export type AddOnBase = z.infer<typeof AddOnBaseSchema>
90
+
91
+ export type StarterInfo = z.infer<typeof StarterSchema>
92
+
93
+ export type StarterCompiled = z.infer<typeof StarterCompiledSchema>
94
+
95
+ export type AddOnInfo = z.infer<typeof AddOnInfoSchema>
96
+
97
+ export type AddOnCompiled = z.infer<typeof AddOnCompiledSchema>
98
+
8
99
  export type FileBundleHandler = {
9
100
  getFiles: () => Promise<Array<string>>
10
101
  getFileContents: (path: string) => Promise<string>
102
+ getDeletedFiles: () => Promise<Array<string>>
11
103
  }
12
104
 
13
- export type Integration = {
14
- type: 'provider' | 'root-provider' | 'layout' | 'header-user'
15
- path: string
16
- jsName: string
17
- }
18
-
19
- export type AddOnDefinition = {
20
- id: string
21
- name: string
22
- description: string
23
- type: 'add-on' | 'example' | 'starter' | 'toolchain'
24
- link: string
25
- templates: Array<string>
26
- routes?: Array<{
27
- url: string
28
- name: string
29
- path: string
30
- jsName: string
31
- }>
32
- packageAdditions: {
33
- dependencies?: Record<string, string>
34
- devDependencies?: Record<string, string>
35
- scripts?: Record<string, string>
36
- }
37
- command?: {
38
- command: string
39
- args?: Array<string>
40
- }
41
- readme?: string
42
- phase: 'setup' | 'add-on'
43
- shadcnComponents?: Array<string>
44
- warning?: string
45
- dependsOn?: Array<string>
46
- integrations?: Array<Integration>
47
- variables?: Array<Variable>
48
-
49
- files?: Record<string, string>
50
- deletedFiles?: Array<string>
51
- }
52
-
53
- export type StarterDefinition = AddOnDefinition & {
54
- type: 'starter'
55
- version: string
56
- author: string
57
- link: string
58
- license: string
59
- mode: Mode
60
- framework: string
61
- typescript: boolean
62
- tailwind: boolean
63
- }
105
+ export type AddOn = AddOnInfo & FileBundleHandler
64
106
 
65
- export type AddOn = AddOnDefinition & FileBundleHandler
66
- export type Starter = StarterDefinition & FileBundleHandler
107
+ export type Starter = StarterCompiled & FileBundleHandler
67
108
 
68
109
  export type FrameworkDefinition = {
69
110
  id: string
@@ -85,17 +126,29 @@ export type Framework = FrameworkDefinition &
85
126
  }
86
127
 
87
128
  export interface Options {
88
- framework: Framework
89
129
  projectName: string
130
+ targetDir: string
131
+
132
+ framework: Framework
133
+ mode: Mode
134
+
90
135
  typescript: boolean
91
136
  tailwind: boolean
137
+
92
138
  packageManager: PackageManager
93
- mode: Mode
94
- addOns: boolean
95
- chosenAddOns: Array<AddOn>
96
139
  git: boolean
97
- variableValues: Record<string, string | number | boolean>
98
- starter?: AddOn | undefined
140
+
141
+ chosenAddOns: Array<AddOn>
142
+ starter?: Starter | undefined
143
+ }
144
+
145
+ export type SerializedOptions = Omit<
146
+ Options,
147
+ 'chosenAddOns' | 'starter' | 'framework'
148
+ > & {
149
+ chosenAddOns: Array<string>
150
+ starter?: string | undefined
151
+ framework: string
99
152
  }
100
153
 
101
154
  type ProjectEnvironment = {
@@ -108,12 +161,40 @@ type FileEnvironment = {
108
161
  appendFile: (path: string, contents: string) => Promise<void>
109
162
  copyFile: (from: string, to: string) => Promise<void>
110
163
  writeFile: (path: string, contents: string) => Promise<void>
111
- execute: (command: string, args: Array<string>, cwd: string) => Promise<void>
164
+ writeFileBase64: (path: string, base64Contents: string) => Promise<void>
165
+ execute: (
166
+ command: string,
167
+ args: Array<string>,
168
+ cwd: string,
169
+ ) => Promise<{ stdout: string }>
112
170
  deleteFile: (path: string) => Promise<void>
171
+
113
172
  exists: (path: string) => boolean
173
+ isDirectory: (path: string) => boolean
174
+ readFile: (path: string) => Promise<string>
175
+ readdir: (path: string) => Promise<Array<string>>
176
+ rimraf: (path: string) => Promise<void>
177
+ }
178
+
179
+ export type StatusEvent = {
180
+ id: string
181
+ type: StatusStepType
182
+ message: string
183
+ }
184
+ export type StopEvent = {
185
+ id: string
114
186
  }
115
187
 
116
188
  type UIEnvironment = {
189
+ appName: string
190
+
191
+ startStep: (info: {
192
+ id: string
193
+ type: StatusStepType
194
+ message: string
195
+ }) => void
196
+ finishStep: (id: string, finalMessage: string) => void
197
+
117
198
  intro: (message: string) => void
118
199
  outro: (message: string) => void
119
200
 
@@ -129,26 +210,3 @@ type UIEnvironment = {
129
210
  }
130
211
 
131
212
  export type Environment = ProjectEnvironment & FileEnvironment & UIEnvironment
132
-
133
- type BooleanVariable = {
134
- name: string
135
- default: boolean
136
- description: string
137
- type: 'boolean'
138
- }
139
-
140
- type NumberVariable = {
141
- name: string
142
- default: number
143
- description: string
144
- type: 'number'
145
- }
146
-
147
- type StringVariable = {
148
- name: string
149
- default: string
150
- description: string
151
- type: 'string'
152
- }
153
-
154
- export type Variable = BooleanVariable | NumberVariable | StringVariable
@@ -13,12 +13,12 @@ describe('getAllAddOns', () => {
13
13
  {
14
14
  id: 'add-on-1',
15
15
  description: 'Add-on 1',
16
- templates: ['file-router'],
16
+ modes: ['file-router'],
17
17
  } as AddOn,
18
18
  {
19
19
  id: 'add-on-2',
20
20
  description: 'Add-on 2',
21
- templates: ['code-router'],
21
+ modes: ['code-router'],
22
22
  } as AddOn,
23
23
  ],
24
24
  } as Framework,
@@ -39,18 +39,18 @@ describe('finalizeAddOns', () => {
39
39
  {
40
40
  id: 'add-on-1',
41
41
  description: 'Add-on 1',
42
- templates: ['file-router'],
42
+ modes: ['file-router'],
43
43
  dependsOn: ['add-on-2'],
44
44
  } as AddOn,
45
45
  {
46
46
  id: 'add-on-2',
47
47
  description: 'Add-on 2',
48
- templates: ['file-router'],
48
+ modes: ['file-router'],
49
49
  } as AddOn,
50
50
  {
51
51
  id: 'add-on-3',
52
52
  description: 'Add-on 3',
53
- templates: ['file-router'],
53
+ modes: ['file-router'],
54
54
  } as AddOn,
55
55
  ],
56
56
  } as Framework,