diff --git a/.vscode/settings.json b/.vscode/settings.json index 82a5396..5d35e77 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "eslint.validate": ["json"], "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": "explicit" } } diff --git a/e2e/func-e2e/tests/func.spec.ts b/e2e/func-e2e/tests/func.spec.ts index 1083e55..2ec1831 100644 --- a/e2e/func-e2e/tests/func.spec.ts +++ b/e2e/func-e2e/tests/func.spec.ts @@ -71,100 +71,6 @@ describe('Project initialization and build', () => { const funcFilePath = `apps/${project}/${func}/index.ts`; - updateFile( - funcFilePath, - ` import { AzureFunction, Context, HttpRequest } from "@azure/functions" - import { ${lib} } from "@proj/${lib}"; - - const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise { - context.res = { - // status: 200, /* Defaults to 200 */ - body: ${lib}() - }; - - }; - - export default httpTrigger; - `, - ); - - const buildResult = await runNxCommandAsync(`build ${project}`); - - expect(buildResult.stdout).toContain(`Done compiling TypeScript files for project "${project}"`); - }, - TEST_TIMEOUT, - ); - - it( - 'Use strict mode', - async () => { - const project = uniq('func'); - await runNxCommandAsync(`generate @nxazure/func:init ${project}`); - - const tsConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.json`); - const tsBuildConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.build.json`); - - expect(tsConfig.compilerOptions.strict).toBe(true); - expect(tsBuildConfig.compilerOptions.strict).toBe(true); - }, - TEST_TIMEOUT, - ); - - it( - 'Use no strict mode', - async () => { - const project = uniq('func'); - await runNxCommandAsync(`generate @nxazure/func:init ${project} --no-strict`); - - const tsConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.json`); - const tsBuildConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.build.json`); - - expect(tsConfig.compilerOptions.strict).toBe(false); - expect(tsBuildConfig.compilerOptions.strict).toBe(false); - }, - TEST_TIMEOUT, - ); - - it( - 'should init & build and empty workspace with a functions app (V4)', - async () => { - const project = uniq('func'); - await runNxCommandAsync(`generate @nxazure/func:init ${project} --v4`); - const buildResult = await runNxCommandAsync(`build ${project}`); - - expect(buildResult.stdout).toContain(`Done compiling TypeScript files for project "${project}"`); - }, - TEST_TIMEOUT, - ); - - it( - 'should init & build a workspace with a functions app and a function (V4)', - async () => { - const project = uniq('func'); - const func = 'hello'; - - await runNxCommandAsync(`generate @nxazure/func:init ${project} --v4`); - await runNxCommandAsync(`generate @nxazure/func:new ${func} --project=${project} --template="HTTP trigger"`); - const buildResult = await runNxCommandAsync(`build ${project}`); - - expect(buildResult.stdout).toContain(`Done compiling TypeScript files for project "${project}"`); - }, - TEST_TIMEOUT, - ); - - it( - 'should init & build a workspace with a js lib functions app and a function (V4)', - async () => { - const project = uniq('func'); - const lib = uniq('lib'); - const func = 'hello'; - - await runNxCommandAsync(`generate @nxazure/func:init ${project} --v4`); - await runNxCommandAsync(`generate @nxazure/func:new ${func} --project=${project} --template="HTTP trigger"`); - await runNxCommandAsync(`generate @nx/js:library ${lib}`); - - const funcFilePath = `apps/${project}/${func}/index.ts`; - updateFile( funcFilePath, ` import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions"; @@ -192,10 +98,10 @@ describe('Project initialization and build', () => { ); it( - 'Use strict mode (V4)', + 'Use strict mode', async () => { const project = uniq('func'); - await runNxCommandAsync(`generate @nxazure/func:init ${project} --v4`); + await runNxCommandAsync(`generate @nxazure/func:init ${project}`); const tsConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.json`); const tsBuildConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.build.json`); @@ -207,10 +113,10 @@ describe('Project initialization and build', () => { ); it( - 'Use no strict mode (V4)', + 'Use no strict mode', async () => { const project = uniq('func'); - await runNxCommandAsync(`generate @nxazure/func:init ${project} --no-strict --v4`); + await runNxCommandAsync(`generate @nxazure/func:init ${project} --no-strict`); const tsConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.json`); const tsBuildConfig = await readJson<{ compilerOptions: CompilerOptions }>(`apps/${project}/tsconfig.build.json`); diff --git a/migrations.json b/migrations.json new file mode 100644 index 0000000..6667931 --- /dev/null +++ b/migrations.json @@ -0,0 +1,72 @@ +{ + "migrations": [ + { + "cli": "nx", + "version": "17.0.0-beta.1", + "description": "Updates the default cache directory to .nx/cache", + "implementation": "./src/migrations/update-17-0-0/move-cache-directory", + "package": "nx", + "name": "17.0.0-move-cache-directory" + }, + { + "cli": "nx", + "version": "17.0.0-beta.3", + "description": "Use minimal config for tasksRunnerOptions", + "implementation": "./src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options", + "package": "nx", + "name": "17.0.0-use-minimal-config-for-tasks-runner-options" + }, + { + "version": "17.0.0-rc.1", + "description": "Migration for v17.0.0-rc.1", + "implementation": "./src/migrations/update-17-0-0/rm-default-collection-npm-scope", + "package": "nx", + "name": "rm-default-collection-npm-scope" + }, + { + "cli": "nx", + "version": "16.9.0-beta.1", + "description": "Replace imports of Module Federation utils frm @nx/devkit to @nx/webpack", + "implementation": "./src/migrations/update-16-9-0/migrate-mf-util-usage", + "package": "@nx/devkit", + "name": "update-16-9-0-migrate-mf-usage-to-webpack" + }, + { + "version": "17.0.0-beta.7", + "description": "update-17-0-0-rename-to-eslint", + "implementation": "./src/migrations/update-17-0-0-rename-to-eslint/update-17-0-0-rename-to-eslint", + "package": "@nx/linter", + "name": "update-17-0-0-rename-to-eslint" + }, + { + "version": "17.1.0-beta.1", + "description": "Updates for @typescript-utils/utils v6.9.1+", + "implementation": "./src/migrations/update-17-1-0/update-typescript-eslint", + "package": "@nx/linter", + "name": "update-typescript-eslint" + }, + { + "cli": "nx", + "version": "16.8.2-beta.0", + "description": "Remove invalid options (strict, noInterop) for ES6 type modules.", + "factory": "./src/migrations/update-16-8-2/update-swcrc", + "package": "@nx/js", + "name": "16-8-2-update-swcrc" + }, + { + "cli": "nx", + "version": "17.0.2", + "description": "Remove deprecated build options", + "implementation": "./src/migrations/update-17-0-0/remove-deprecated-build-options", + "package": "@nx/js", + "name": "update-17-0-0-remove-deprecated-build-options" + }, + { + "version": "17.1.0-beta.2", + "description": "Move jest executor options to nx.json targetDefaults", + "implementation": "./src/migrations/update-17-1-0/move-options-to-target-defaults", + "package": "@nx/jest", + "name": "move-options-to-target-defaults" + } + ] +} diff --git a/package.json b/package.json index 7c5ab13..3ac8337 100644 --- a/package.json +++ b/package.json @@ -13,39 +13,40 @@ "lint-staged": "lint-staged" }, "devDependencies": { - "@nx/devkit": "16.8.1", - "@nx/eslint-plugin": "16.8.1", - "@nx/jest": "16.8.1", - "@nx/js": "16.8.1", - "@nx/linter": "16.8.1", - "@nx/plugin": "16.8.1", - "@nx/workspace": "16.8.1", - "@swc-node/register": "^1.4.2", + "@nx/devkit": "17.1.2", + "@nx/eslint-plugin": "17.1.2", + "@nx/jest": "17.1.2", + "@nx/js": "17.1.2", + "@nx/linter": "17.1.2", + "@nx/plugin": "17.1.2", + "@nx/workspace": "17.1.2", + "@swc-node/register": "1.6.8", "@swc/cli": "0.1.62", - "@swc/core": "^1.2.173", + "@swc/core": "1.3.96", "@types/jest": "29.4.0", "@types/node": "^18.11.19", - "@typescript-eslint/eslint-plugin": "5.60.1", - "@typescript-eslint/parser": "5.60.1", + "@typescript-eslint/eslint-plugin": "6.9.1", + "@typescript-eslint/parser": "6.9.1", "eslint": "8.46.0", - "eslint-config-prettier": "8.1.0", + "eslint-config-prettier": "9.0.0", "husky": "^8.0.3", "is-ci": "^3.0.1", "jest": "29.4.3", "jest-environment-jsdom": "29.4.3", "jsonc-eslint-parser": "^2.1.0", "lint-staged": "^13.1.0", - "nx": "16.8.1", + "nx": "17.1.2", "prettier": "^2.6.2", "ts-jest": "29.1.0", "ts-node": "10.9.1", "tsc-files": "^1.1.3", - "typescript": "5.1.6" + "typescript": "5.2.2" }, "dependencies": { - "@swc/helpers": "0.5.1", + "@swc/helpers": "0.5.3", "glob": "^10.2.2", "tree-kill": "^1.2.2", "tslib": "^2.3.0" } } + diff --git a/packages/func/src/common/utils.ts b/packages/func/src/common/utils.ts index b0bc527..6a66eec 100644 --- a/packages/func/src/common/utils.ts +++ b/packages/func/src/common/utils.ts @@ -1,5 +1,3 @@ -import { Tree, readJson, readJsonFile } from '@nx/devkit'; - export const color = { error: (message: string) => `\x1B[31m${message}\x1B[0m`, // Red warn: (message: string) => `\x1B[33m${message}\x1B[0m`, // Yellow @@ -9,15 +7,3 @@ export const color = { endpoint: (message: string) => `\x1B[38;2;19;161;14m${message}\x1B[0m`, // Green fade: (message: string) => `\x1B[90m${message}\x1B[0m`, // Gray }; - -type PackageJsonDependencies = { dependencies?: Record }; -const isV4PackageRegex = /^[^0-9]*4/; -export const isV4 = (tree?: Tree) => { - const { dependencies } = tree - ? readJson(tree, 'package.json') - : readJsonFile('package.json'); - - const funcPackageVersion = dependencies?.['@azure/functions']; - - return funcPackageVersion && isV4PackageRegex.test(funcPackageVersion); -}; diff --git a/packages/func/src/executors/common/inject-path-registration.ts b/packages/func/src/executors/common/inject-path-registration.ts index 711383c..885248c 100644 --- a/packages/func/src/executors/common/inject-path-registration.ts +++ b/packages/func/src/executors/common/inject-path-registration.ts @@ -2,28 +2,15 @@ import { readJsonFile } from '@nx/devkit'; import fs from 'fs'; import { glob } from 'glob'; import path from 'path'; -import { isV4, registrationFileName } from '../../common'; +import { registrationFileName } from '../../common'; const getFilesForPathInjection = async (appRoot: string) => { - if (isV4()) { - const { main: functionsPathPattern } = readJsonFile<{ main: string }>(path.join(appRoot, 'package.json')); + const { main: functionsPathPattern } = readJsonFile<{ main: string }>(path.join(appRoot, 'package.json')); - const functionsPath = path.posix.join(appRoot, functionsPathPattern); - const functions = await glob(functionsPath); + const functionsPath = path.posix.join(appRoot, functionsPathPattern); + const functions = await glob(functionsPath); - return functions; - } else { - const functionJsonFiles = await glob('**/function.json', { cwd: appRoot, ignore: ['**/node_modules/**'] }); - - return await Promise.all( - functionJsonFiles - .map(file => path.join(appRoot, file)) - .map(async file => { - const { scriptFile } = await readJsonFile<{ scriptFile: string }>(file); - return path.join(path.dirname(file), scriptFile); - }), - ); - } + return functions; }; export const injectPathRegistration = async (outputPath: string, appRoot: string) => { diff --git a/packages/func/src/executors/publish/executor.ts b/packages/func/src/executors/publish/executor.ts index c95f703..67d5760 100644 --- a/packages/func/src/executors/publish/executor.ts +++ b/packages/func/src/executors/publish/executor.ts @@ -2,7 +2,6 @@ import { Executor } from '@nx/devkit'; import { execSync } from 'child_process'; import fs from 'fs'; import path from 'path'; -import { color, isV4 } from '../../common'; import { build } from '../common'; import { PublishExecutorSchema } from './schema'; @@ -12,11 +11,6 @@ const executor: Executor = async (options, context) => { if (success) { const { projectName, workspace, isVerbose, target } = context; - if (isV4()) { - console.log(color.warn('[V4 FUNCTION][ATTENTION]')); - console.log(color.warn('Add the configuration "AzureWebJobsFeatureFlags": "EnableWorkerIndexing" to your deployment.')); - } - const { name, additionalFlags } = options; const installCommand = 'npm i'; if (isVerbose) { diff --git a/packages/func/src/generators/common/utils.ts b/packages/func/src/generators/common/utils.ts index 045cd2e..8c31a58 100644 --- a/packages/func/src/generators/common/utils.ts +++ b/packages/func/src/generators/common/utils.ts @@ -6,12 +6,12 @@ import path from 'path'; const getEnvTempDir = () => process.env.RUNNER_TEMP || os.tmpdir(); // This supports not only local dev but also GitHub Actions -export const createTempFolderWithInit = (tempAppName: string, v4: boolean) => { - const tempName = names(tempAppName).fileName.split('/') - const tempFolder = fs.mkdtempSync(path.posix.join(getEnvTempDir(),`func-${tempName.pop()}-`)); +export const createTempFolderWithInit = (tempAppName: string) => { + const tempName = names(tempAppName).fileName.split('/'); + const tempFolder = fs.mkdtempSync(path.posix.join(getEnvTempDir(), `func-${tempName.pop()}-`)); try { - execSync(`func init ${tempAppName} --worker-runtime node --language typescript ${v4 ? '--model V4' : ''}`, { + execSync(`func init ${tempAppName} --worker-runtime node --language typescript`, { cwd: tempFolder, stdio: 'ignore', }); @@ -23,7 +23,7 @@ export const createTempFolderWithInit = (tempAppName: string, v4: boolean) => { return { tempFolder, tempProjectRoot: path.posix.join(tempFolder, tempAppName) }; }; -export const copyToTempFolder = (tree: Tree, projectRootPath: string, v4: boolean) => { +export const copyToTempFolder = (tree: Tree, projectRootPath: string) => { const tempFolder = fs.mkdtempSync(path.posix.join(getEnvTempDir(), `func-copy-`)); tree @@ -33,7 +33,7 @@ export const copyToTempFolder = (tree: Tree, projectRootPath: string, v4: boolea .map(({ filename, fullPath }) => ({ filename, content: tree.read(fullPath).toString() })) .forEach(({ filename, content }) => fs.writeFileSync(path.posix.join(tempFolder, filename), content)); - if (v4) fs.mkdirSync(path.posix.join(tempFolder, 'src/functions'), { recursive: true }); + fs.mkdirSync(path.posix.join(tempFolder, 'src/functions'), { recursive: true }); return tempFolder; }; diff --git a/packages/func/src/generators/init/generator.ts b/packages/func/src/generators/init/generator.ts index 8c23989..2b79d6d 100644 --- a/packages/func/src/generators/init/generator.ts +++ b/packages/func/src/generators/init/generator.ts @@ -31,13 +31,12 @@ type NormalizedOptions = { appRoot: string; appNames: ReturnType; strict: boolean; - v4: boolean; tags: string[]; }; const staticFilesToCopy = ['host.json', 'local.settings.json', '.funcignore']; -const normalizeOptions = (tree: Tree, { name, strict, v4, tags }: InitGeneratorSchema): NormalizedOptions => { +const normalizeOptions = (tree: Tree, { name, strict, tags }: InitGeneratorSchema): NormalizedOptions => { const appNames = names(name); const { appsDir } = getWorkspaceLayout(tree); @@ -46,13 +45,10 @@ const normalizeOptions = (tree: Tree, { name, strict, v4, tags }: InitGeneratorS if (tree.exists(appRoot) && tree.children(appRoot).length > 0) throw new Error(`Project [${name} (${appNames.fileName})] already exists in the workspace.`); - if (v4) console.log(color.warn('The V4 model is currently in preview. Use with caution.')); - return { appRoot, appNames, strict, - v4, tags: tags.split(',').map(s => s.trim()) || [], }; }; @@ -118,26 +114,16 @@ const updateWorkspacePackageJson = (tree: Tree, copyFromFolder: string) => { json.devDependencies = json.devDependencies || {}; - // In most new instances, Node 18 is used. V3 model is using 16.x, which fails on build in that case. - // After V3 is deprecated, this can be removed. - sourcePackageJson.devDependencies['@types/node'] = '18.x'; - Object.keys(sourcePackageJson.devDependencies).forEach(key => { json.devDependencies[key] = json.devDependencies[key] || sourcePackageJson.devDependencies[key]; }); - // For V4, the @azure/functions package is moved from devDependencies to dependencies - if (sourceDependencies['@azure/functions'] && json.devDependencies['@azure/functions']) { - console.log(color.warn('ATTENTION'), 'Upgrading to V4 model requires you to upgrade ALL your existing functions'); - delete json.devDependencies['@azure/functions']; - } - return json; }); console.log( color.warn('ATTENTION'), - 'Some dependencies might not work well together. If something is not working, try to update @types/node, typescript or @azure/functions to the latest (preview for V4) versions.', + 'Some dependencies might not work well together. If something is not working, try to update @types/node, typescript or @azure/functions to the latest versions.', ); }; @@ -169,17 +155,16 @@ const updateBaseTsConfig = (tree: Tree) => { }); }; -const createProjectPackageJson = (tree: Tree, { appRoot, v4 }: NormalizedOptions, copyFromFolder: string) => { +const createProjectPackageJson = (tree: Tree, { appRoot }: NormalizedOptions, copyFromFolder: string) => { // This needs to be copied and dependencies + devDependencies removed const sourcePackageJson = readJsonFile<{ dependencies: Record; devDependencies: Record; main: string }>( path.posix.join(copyFromFolder, 'package.json'), ); const azureFunctionsVersion = sourcePackageJson.dependencies['@azure/functions']; - sourcePackageJson.dependencies = v4 ? { ['@azure/functions']: azureFunctionsVersion } : {}; + sourcePackageJson.dependencies = { ['@azure/functions']: azureFunctionsVersion }; sourcePackageJson.devDependencies = {}; - - if (v4) sourcePackageJson.main = `dist/${appRoot}/src/functions/*.js`; + sourcePackageJson.main = `dist/${appRoot}/src/functions/*.js`; tree.write(path.posix.join(appRoot, 'package.json'), JSON.stringify(sourcePackageJson, null, 2)); }; @@ -265,7 +250,7 @@ export default async function (tree: Tree, options: InitGeneratorSchema) { if (options.silent) console.log = () => {}; // eslint-disable-line @typescript-eslint/no-empty-function const normalizedOptions = normalizeOptions(tree, options); - const { tempFolder, tempProjectRoot } = createTempFolderWithInit(normalizedOptions.appNames.fileName, normalizedOptions.v4); + const { tempFolder, tempProjectRoot } = createTempFolderWithInit(normalizedOptions.appNames.fileName); try { createProjectConfigurationFile(tree, normalizedOptions); diff --git a/packages/func/src/generators/init/schema.d.ts b/packages/func/src/generators/init/schema.d.ts index 7329c6a..a64f18c 100644 --- a/packages/func/src/generators/init/schema.d.ts +++ b/packages/func/src/generators/init/schema.d.ts @@ -2,6 +2,5 @@ export interface InitGeneratorSchema { name: string; strict: boolean; silent: boolean; - v4: boolean; tags: string; } diff --git a/packages/func/src/generators/init/schema.json b/packages/func/src/generators/init/schema.json index 7871ff8..eabcb20 100644 --- a/packages/func/src/generators/init/schema.json +++ b/packages/func/src/generators/init/schema.json @@ -23,11 +23,6 @@ "description": "Do not print any output", "default": false }, - "v4": { - "type": "boolean", - "description": "Use the preview V4 model of Azure Functions. (WIP, 'new' generator is not supported. Init functions manually)", - "default": false - }, "tags": { "type": "string", "description": "Add tags to the library (used for linting).", diff --git a/packages/func/src/generators/init/tests/eslint.spec.ts b/packages/func/src/generators/init/tests/eslint.spec.ts index ff517e7..ce155b9 100644 --- a/packages/func/src/generators/init/tests/eslint.spec.ts +++ b/packages/func/src/generators/init/tests/eslint.spec.ts @@ -12,31 +12,41 @@ jest.mock('@nx/devkit', () => { }; }); +const TEST_TIMEOUT = 120000; + describe('Init with no eslint', () => { const projectName = 'HelloWorld'; let appTree: Tree; - const baseOptions: InitGeneratorSchema = { name: projectName, strict: true, silent: true, v4: false, tags: '' }; + const baseOptions: InitGeneratorSchema = { name: projectName, strict: true, silent: true, tags: '' }; beforeAll(async () => { appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - }); - - it('No global config -> no app config', async () => { - await generator(appTree, { ...baseOptions, name: baseOptions.name + '1' }); - - const eslintConfigExists = appTree.exists('apps/hello-world1/.eslintrc.json'); - expect(eslintConfigExists).toBeFalsy(); - }); - - it('Global config exists -> app config generated', async () => { - appTree.write('.eslintrc.json', JSON.stringify({})); - const name = baseOptions.name + '2'; - await generator(appTree, { ...baseOptions, name }); - - const eslintConfigExists = appTree.exists('apps/hello-world2/.eslintrc.json'); - expect(eslintConfigExists).toBeTruthy(); - - const projectConfiguration = readProjectConfiguration(appTree, name); - expect(projectConfiguration).toHaveProperty('targets.lint'); - }); + }, TEST_TIMEOUT); + + it( + 'No global config -> no app config', + async () => { + await generator(appTree, { ...baseOptions, name: baseOptions.name + '1' }); + + const eslintConfigExists = appTree.exists('apps/hello-world1/.eslintrc.json'); + expect(eslintConfigExists).toBeFalsy(); + }, + TEST_TIMEOUT, + ); + + it( + 'Global config exists -> app config generated', + async () => { + appTree.write('.eslintrc.json', JSON.stringify({})); + const name = baseOptions.name + '2'; + await generator(appTree, { ...baseOptions, name }); + + const eslintConfigExists = appTree.exists('apps/hello-world2/.eslintrc.json'); + expect(eslintConfigExists).toBeTruthy(); + + const projectConfiguration = readProjectConfiguration(appTree, name); + expect(projectConfiguration).toHaveProperty('targets.lint'); + }, + TEST_TIMEOUT, + ); }); diff --git a/packages/func/src/generators/init/tests/main-v3.spec.ts b/packages/func/src/generators/init/tests/main-v3.spec.ts deleted file mode 100644 index 76b864b..0000000 --- a/packages/func/src/generators/init/tests/main-v3.spec.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Tree, readProjectConfiguration } from '@nx/devkit'; -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import generator from '../generator'; -import { InitGeneratorSchema } from '../schema'; - -jest.mock('@nx/devkit', () => { - const originalModule = jest.requireActual('@nx/devkit'); - - return { - ...originalModule, - installPackagesTask: jest.fn(() => console.log('Imagine installing packages here...')), - }; -}); - -describe.each([ - { - name: 'HelloWorld', - path: 'apps/hello-world', - sublevelFromRoot: 2, - }, - { - name: 'core/HelloWorld', - path: 'apps/core/hello-world', - sublevelFromRoot: 3, - }, -])('Check files (v3)', (testArgs: { name: string; path: string; sublevelFromRoot: number }) => { - const projectName = testArgs.name; - let appTree: Tree; - const options: InitGeneratorSchema = { name: projectName, strict: true, silent: true, v4: false, tags: '' }; - - beforeAll(async () => { - appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - appTree.write('.eslintrc.json', JSON.stringify({})); - await generator(appTree, options); - }); - - it('Folder name', () => { - expect(appTree.exists(testArgs.path)).toBeTruthy(); - }); - - it('Project config', () => { - const config = readProjectConfiguration(appTree, projectName); - expect(config).toBeDefined(); - expect(config).toHaveProperty('name', projectName); - expect(config).toHaveProperty('projectType', 'application'); - expect(config).toHaveProperty('targets.build.executor', '@nxazure/func:build'); - expect(config).toHaveProperty('targets.start.executor', '@nxazure/func:start'); - expect(config).toHaveProperty('targets.start.options.port', 7071); - expect(config).toHaveProperty('targets.publish.executor', '@nxazure/func:publish'); - }); - - it('VScode extension', () => { - const vscodeSettings = appTree.read('.vscode/extensions.json'); - expect(vscodeSettings).toBeDefined(); - - const vscodeSettingsObj = JSON.parse(vscodeSettings?.toString() || '{}'); - expect(vscodeSettingsObj.recommendations).toContain('ms-azuretools.vscode-azurefunctions'); - }); - - it('Workspace package.json', () => { - const packageJson = appTree.read('package.json'); - expect(packageJson).toBeDefined(); - - const packageJsonObj = JSON.parse(packageJson?.toString() || '{}'); - expect(packageJsonObj).toHaveProperty('dependencies.tsconfig-paths'); - expect(packageJsonObj).toHaveProperty('devDependencies.typescript'); - expect(packageJsonObj).toHaveProperty('devDependencies.@azure/functions'); - expect(packageJsonObj).toHaveProperty('devDependencies.azure-functions-core-tools'); - expect(packageJsonObj).toHaveProperty('devDependencies.@types/node'); - }); - - it('Workspace TS config file', () => { - const tsconfig = appTree.read(`${testArgs.path}/tsconfig.json`); - expect(tsconfig).toBeDefined(); - - const tsconfigObj = JSON.parse(tsconfig?.toString() || '{}'); - expect(tsconfigObj).toHaveProperty('extends', `${'../'.repeat(testArgs.sublevelFromRoot)}tsconfig.base.json`); - expect(tsconfigObj).toHaveProperty('compilerOptions.module', 'commonjs'); - expect(tsconfigObj).toHaveProperty('compilerOptions.target', 'es6'); - expect(tsconfigObj).toHaveProperty('compilerOptions.sourceMap', true); - expect(tsconfigObj).toHaveProperty('compilerOptions.strict', true); - }); - - it('Build TS config file', () => { - const tsconfig = appTree.read(`${testArgs.path}/tsconfig.build.json`); - expect(tsconfig).toBeDefined(); - - const tsconfigObj = JSON.parse(tsconfig?.toString() || '{}'); - expect(tsconfigObj).not.toHaveProperty('extends'); - expect(tsconfigObj).toHaveProperty('compilerOptions.outDir', 'dist'); - expect(tsconfigObj).toHaveProperty('compilerOptions.resolveJsonModule', true); - expect(tsconfigObj).toHaveProperty('compilerOptions.module', 'commonjs'); - expect(tsconfigObj).toHaveProperty('compilerOptions.target', 'es6'); - expect(tsconfigObj).toHaveProperty('compilerOptions.sourceMap', true); - expect(tsconfigObj).toHaveProperty('compilerOptions.strict', true); - }); - - it('Base TS config file', () => { - const tsconfig = appTree.read('tsconfig.base.json'); - expect(tsconfig).toBeDefined(); - - const tsconfigObj = JSON.parse(tsconfig?.toString() || '{}'); - expect(tsconfigObj).toHaveProperty('compilerOptions.resolveJsonModule', true); - }); - - it('Project eslint config file', () => { - const eslintConfig = appTree.read(`${testArgs.path}/.eslintrc.json`); - expect(eslintConfig).toBeDefined(); - - const eslintConfigObj = JSON.parse(eslintConfig?.toString() || '{}'); - expect(eslintConfigObj).toHaveProperty('extends', `${'../'.repeat(testArgs.sublevelFromRoot)}.eslintrc.json`); - expect(eslintConfigObj.overrides[0]).toHaveProperty('parserOptions.project', [`${testArgs.path}/tsconfig.*?.json`]); - }); - - it('Auto generated files', () => { - expect(appTree.exists(`${testArgs.path}/package.json`)).toBeTruthy(); - expect(appTree.exists(`${testArgs.path}/host.json`)).toBeTruthy(); - expect(appTree.exists(`${testArgs.path}/local.settings.json`)).toBeTruthy(); - expect(appTree.exists(`${testArgs.path}/.funcignore`)).toBeTruthy(); - expect(appTree.exists(`${testArgs.path}/_registerPaths.ts`)).toBeTruthy(); - }); -}); diff --git a/packages/func/src/generators/init/tests/main-v4.spec.ts b/packages/func/src/generators/init/tests/main.spec.ts similarity index 96% rename from packages/func/src/generators/init/tests/main-v4.spec.ts rename to packages/func/src/generators/init/tests/main.spec.ts index a896861..c593085 100644 --- a/packages/func/src/generators/init/tests/main-v4.spec.ts +++ b/packages/func/src/generators/init/tests/main.spec.ts @@ -12,6 +12,8 @@ jest.mock('@nx/devkit', () => { }; }); +const TEST_TIMEOUT = 120000; + describe.each([ { name: 'HelloWorld', @@ -23,16 +25,16 @@ describe.each([ path: 'apps/core/hello-world', sublevelFromRoot: 3, }, -])('Check files (v4)', (testArgs: { name: string; path: string; sublevelFromRoot: number }) => { +])('Check files', (testArgs: { name: string; path: string; sublevelFromRoot: number }) => { const projectName = testArgs.name; let appTree: Tree; - const options: InitGeneratorSchema = { name: projectName, strict: true, silent: true, v4: true, tags: '' }; + const options: InitGeneratorSchema = { name: projectName, strict: true, silent: true, tags: '' }; beforeAll(async () => { appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); appTree.write('.eslintrc.json', JSON.stringify({})); await generator(appTree, options); - }, 120000); + }, TEST_TIMEOUT); it('Folder name', () => { expect(appTree.exists(testArgs.path)).toBeTruthy(); diff --git a/packages/func/src/generators/init/tests/port-increase.spec.ts b/packages/func/src/generators/init/tests/port-increase.spec.ts index 8242584..7908c5e 100644 --- a/packages/func/src/generators/init/tests/port-increase.spec.ts +++ b/packages/func/src/generators/init/tests/port-increase.spec.ts @@ -12,38 +12,52 @@ jest.mock('@nx/devkit', () => { }; }); +const TEST_TIMEOUT = 120000; + describe('Check port increased value', () => { let appTree: Tree; - const baseOptions: InitGeneratorSchema = { name: 'HelloWorld', strict: true, silent: true, v4: false, tags: '' }; + const baseOptions: InitGeneratorSchema = { name: 'HelloWorld', strict: true, silent: true, tags: '' }; beforeAll(() => { appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); }); - it('Port is 7071', async () => { - const projectName = `${baseOptions.name}1`; + it( + 'Port is 7071', + async () => { + const projectName = `${baseOptions.name}1`; - await generator(appTree, { ...baseOptions, name: projectName }); - const config = readProjectConfiguration(appTree, projectName); + await generator(appTree, { ...baseOptions, name: projectName }); + const config = readProjectConfiguration(appTree, projectName); - expect(config).toHaveProperty('targets.start.options.port', 7071); - }); + expect(config).toHaveProperty('targets.start.options.port', 7071); + }, + TEST_TIMEOUT, + ); - it('Port is 7072', async () => { - const projectName = `${baseOptions.name}2`; + it( + 'Port is 7072', + async () => { + const projectName = `${baseOptions.name}2`; - await generator(appTree, { ...baseOptions, name: projectName }); - const config = readProjectConfiguration(appTree, projectName); + await generator(appTree, { ...baseOptions, name: projectName }); + const config = readProjectConfiguration(appTree, projectName); - expect(config).toHaveProperty('targets.start.options.port', 7072); - }); + expect(config).toHaveProperty('targets.start.options.port', 7072); + }, + TEST_TIMEOUT, + ); - it('Port is 7073', async () => { - const projectName = `${baseOptions.name}3`; + it( + 'Port is 7073', + async () => { + const projectName = `${baseOptions.name}3`; - await generator(appTree, { ...baseOptions, name: projectName }); - const config = readProjectConfiguration(appTree, projectName); + await generator(appTree, { ...baseOptions, name: projectName }); + const config = readProjectConfiguration(appTree, projectName); - expect(config).toHaveProperty('targets.start.options.port', 7073); - }); + expect(config).toHaveProperty('targets.start.options.port', 7073); + }, + TEST_TIMEOUT, + ); }); diff --git a/packages/func/src/generators/init/tests/strict.spec.ts b/packages/func/src/generators/init/tests/strict.spec.ts index ff3025f..785155e 100644 --- a/packages/func/src/generators/init/tests/strict.spec.ts +++ b/packages/func/src/generators/init/tests/strict.spec.ts @@ -12,35 +12,45 @@ jest.mock('@nx/devkit', () => { }; }); +const TEST_TIMEOUT = 120000; + describe('Check strict option', () => { let appTree: Tree; - const partialOptions: Omit = { name: 'HelloWorld', silent: true, v4: false, tags: '' }; + const partialOptions: Omit = { name: 'HelloWorld', silent: true, tags: '' }; beforeEach(() => { appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - }); - - it('Strict option is true', async () => { - await generator(appTree, { ...partialOptions, strict: true }); - const workspaceTsConfig = appTree.read('apps/hello-world/tsconfig.json'); - const buildTsConfig = appTree.read('apps/hello-world/tsconfig.build.json'); - - const workspaceTsConfigObj = JSON.parse(workspaceTsConfig?.toString() || '{}'); - const buildTsConfigObj = JSON.parse(buildTsConfig?.toString() || '{}'); - - expect(workspaceTsConfigObj).toHaveProperty('compilerOptions.strict', true); - expect(buildTsConfigObj).toHaveProperty('compilerOptions.strict', true); - }); - - it('Strict option is false', async () => { - await generator(appTree, { ...partialOptions, strict: false }); - const workspaceTsConfig = appTree.read('apps/hello-world/tsconfig.json'); - const buildTsConfig = appTree.read('apps/hello-world/tsconfig.build.json'); - - const workspaceTsConfigObj = JSON.parse(workspaceTsConfig?.toString() || '{}'); - const buildTsConfigObj = JSON.parse(buildTsConfig?.toString() || '{}'); - - expect(workspaceTsConfigObj).toHaveProperty('compilerOptions.strict', false); - expect(buildTsConfigObj).toHaveProperty('compilerOptions.strict', false); - }); + }, TEST_TIMEOUT); + + it( + 'Strict option is true', + async () => { + await generator(appTree, { ...partialOptions, strict: true }); + const workspaceTsConfig = appTree.read('apps/hello-world/tsconfig.json'); + const buildTsConfig = appTree.read('apps/hello-world/tsconfig.build.json'); + + const workspaceTsConfigObj = JSON.parse(workspaceTsConfig?.toString() || '{}'); + const buildTsConfigObj = JSON.parse(buildTsConfig?.toString() || '{}'); + + expect(workspaceTsConfigObj).toHaveProperty('compilerOptions.strict', true); + expect(buildTsConfigObj).toHaveProperty('compilerOptions.strict', true); + }, + TEST_TIMEOUT, + ); + + it( + 'Strict option is false', + async () => { + await generator(appTree, { ...partialOptions, strict: false }); + const workspaceTsConfig = appTree.read('apps/hello-world/tsconfig.json'); + const buildTsConfig = appTree.read('apps/hello-world/tsconfig.build.json'); + + const workspaceTsConfigObj = JSON.parse(workspaceTsConfig?.toString() || '{}'); + const buildTsConfigObj = JSON.parse(buildTsConfig?.toString() || '{}'); + + expect(workspaceTsConfigObj).toHaveProperty('compilerOptions.strict', false); + expect(buildTsConfigObj).toHaveProperty('compilerOptions.strict', false); + }, + TEST_TIMEOUT, + ); }); diff --git a/packages/func/src/generators/new/consts.ts b/packages/func/src/generators/new/consts.ts index 9c01261..9be046f 100644 --- a/packages/func/src/generators/new/consts.ts +++ b/packages/func/src/generators/new/consts.ts @@ -1,21 +1,13 @@ export const TemplateValues = [ 'Azure Blob Storage trigger', - 'Durable Functions activity', + 'Azure Cosmos DB trigger', 'Durable Functions entity', - 'Durable Functions Entity HTTP starter', - 'Durable Functions HTTP starter', 'Durable Functions orchestrator', 'Azure Event Grid trigger', 'Azure Event Hub trigger', 'HTTP trigger', - 'IoT Hub (Event Hub)', - 'Kafka output', - 'Kafka trigger', 'Azure Queue Storage trigger', - 'RabbitMQ trigger', - 'SendGrid', 'Azure Service Bus Queue trigger', 'Azure Service Bus Topic trigger', - 'SignalR negotiate HTTP trigger', 'Timer trigger', ] as const; diff --git a/packages/func/src/generators/new/generator.ts b/packages/func/src/generators/new/generator.ts index a777c30..191b5c6 100644 --- a/packages/func/src/generators/new/generator.ts +++ b/packages/func/src/generators/new/generator.ts @@ -1,21 +1,18 @@ -import { getWorkspaceLayout, names, readJson, Tree, updateJson } from '@nx/devkit'; +import { getWorkspaceLayout, names, Tree } from '@nx/devkit'; import { execSync } from 'child_process'; import fs from 'fs'; import path from 'path'; -import { CompilerOptions } from 'typescript'; -import { isV4, TS_CONFIG_BUILD_FILE } from '../../common'; import { copyToTempFolder } from '../common'; import { TemplateValues } from './consts'; import { NewGeneratorSchema } from './schema'; -const V4_FUNCTIONS_FOLDER = 'src/functions'; +const FUNCTIONS_FOLDER = 'src/functions'; type Template = (typeof TemplateValues)[number]; type NormalizedOptions = Pick & { projectRoot: string; funcNames: ReturnType; - v4: boolean; template: Template; }; @@ -29,19 +26,14 @@ const normalizeOptions = (tree: Tree, { name, project, template, language, authL const projectRoot = path.join(appsDir, names(project).fileName); if (!tree.exists(projectRoot)) throw new Error(`Project [${project} (${projectNames.fileName})] does not exist in the workspace.`); - const v4 = isV4(tree); - if (v4 && template.endsWith('(V3 only)')) throw new Error(`Template [${template}] is not supported in V4.`); - - const cleanTemplateName = template.replace(' (V3 only)', ''); - if (!isTemplateValid(cleanTemplateName)) throw new Error(`Template [${template}] is not supported.`); + if (!isTemplateValid(template)) throw new Error(`Template [${template}] is not supported.`); return { projectRoot, funcNames, - template: cleanTemplateName as NormalizedOptions['template'], + template: template as NormalizedOptions['template'], language, - v4, - authLevel: template === 'HttpTrigger' ? authLevel : undefined, + authLevel: template === 'HTTP trigger' ? authLevel : undefined, silent, }; }; @@ -58,28 +50,13 @@ const copyFiles = (tree: Tree, copyFromRootPath: string, copyToRootPath: string, .forEach(({ destination, content }) => tree.write(destination, content)); }; -const fixFunctionsJson = (tree: Tree, { projectRoot, funcNames }: NormalizedOptions) => { - const funcRoot = path.posix.join(projectRoot, funcNames.fileName); - - const { - compilerOptions: { outDir }, - } = readJson<{ compilerOptions: CompilerOptions }>(tree, path.join(projectRoot, TS_CONFIG_BUILD_FILE)); - const indexJsRelativePath = path.posix.join('..', outDir, funcRoot, 'index.js'); - const posixIndexJsRelativePath = path.posix.join(...indexJsRelativePath.split(path.sep)); - - updateJson(tree, path.posix.join(funcRoot, 'function.json'), functionJsonObject => { - functionJsonObject['scriptFile'] = posixIndexJsRelativePath; - return functionJsonObject; - }); -}; - export default async function (tree: Tree, options: NewGeneratorSchema) { const normalizedOptions = normalizeOptions(tree, options); const originalConsoleLog = console.log; if (options.silent) console.log = () => {}; // eslint-disable-line @typescript-eslint/no-empty-function - const tempFolder = copyToTempFolder(tree, normalizedOptions.projectRoot, normalizedOptions.v4); + const tempFolder = copyToTempFolder(tree, normalizedOptions.projectRoot); try { let funcNewCommand = `func new -n ${normalizedOptions.funcNames.fileName} -t "${normalizedOptions.template}"`; @@ -87,10 +64,7 @@ export default async function (tree: Tree, options: NewGeneratorSchema) { execSync(funcNewCommand, { cwd: tempFolder, stdio: 'ignore' }); - const subFolder = normalizedOptions.v4 ? V4_FUNCTIONS_FOLDER : normalizedOptions.funcNames.fileName; - copyFiles(tree, tempFolder, normalizedOptions.projectRoot, subFolder); - - if (!normalizedOptions.v4) fixFunctionsJson(tree, normalizedOptions); + copyFiles(tree, tempFolder, normalizedOptions.projectRoot, FUNCTIONS_FOLDER); } catch (e) { console.error(`Could not create ${normalizedOptions.funcNames.fileName} function with template ${normalizedOptions.template}.`, e); throw e; diff --git a/packages/func/src/generators/new/schema.json b/packages/func/src/generators/new/schema.json index 4593c9f..b12ed15 100644 --- a/packages/func/src/generators/new/schema.json +++ b/packages/func/src/generators/new/schema.json @@ -35,26 +35,18 @@ "type": "string", "enum": [ "Azure Blob Storage trigger", - "Durable Functions activity (V3 only)", + "Azure Cosmos DB trigger", "Durable Functions entity", - "Durable Functions Entity HTTP starter (V3 only)", - "Durable Functions HTTP starter (V3 only)", "Durable Functions orchestrator", "Azure Event Grid trigger", "Azure Event Hub trigger", "HTTP trigger", - "IoT Hub (Event Hub) (V3 only)", - "Kafka output (V3 only)", - "Kafka trigger (V3 only)", "Azure Queue Storage trigger", - "RabbitMQ trigger (V3 only)", - "SendGrid (V3 only)", "Azure Service Bus Queue trigger", "Azure Service Bus Topic trigger", - "SignalR negotiate HTTP trigger (V3 only)", "Timer trigger" ], - "description": "The template to use for the new function. Note, not all templates are supported for V4 model", + "description": "The template to use for the new function", "x-prompt": "Which template would you like to use to create a new function?", "default": "HTTP trigger" }, diff --git a/packages/func/src/generators/new/v4-tests.spec.ts b/packages/func/src/generators/new/tests.spec.ts similarity index 73% rename from packages/func/src/generators/new/v4-tests.spec.ts rename to packages/func/src/generators/new/tests.spec.ts index da81695..c655915 100644 --- a/packages/func/src/generators/new/v4-tests.spec.ts +++ b/packages/func/src/generators/new/tests.spec.ts @@ -15,6 +15,7 @@ jest.mock('@nx/devkit', () => { const supportedTemplates = [ ['Azure Blob Storage trigger', 'Blob', 'blob'], + ['Azure Cosmos DB trigger', 'CosmosDB', 'cosmos-db'], ['Durable Functions entity', 'DurableFunctionsEntity', 'durable-functions-entity'], ['Durable Functions orchestrator', 'DurableFunctionsOrchestrator', 'durable-functions-orchestrator'], ['Azure Event Grid trigger', 'EventGrid', 'event-grid'], @@ -26,19 +27,9 @@ const supportedTemplates = [ ['Timer trigger', 'Timer', 'timer'], ] as const; -const unsupportedTemplates = [ - 'Durable Functions activity (V3 only)', - 'Durable Functions Entity HTTP starter (V3 only)', - 'Durable Functions HTTP starter (V3 only)', - 'IoT Hub (Event Hub) (V3 only)', - 'Kafka output (V3 only)', - 'Kafka trigger (V3 only)', - 'RabbitMQ trigger (V3 only)', - 'SendGrid (V3 only)', - 'SignalR negotiate HTTP trigger (V3 only)', -]; +const TEST_TIMEOUT = 120000; -describe('new generator (V4)', () => { +describe('new generator', () => { const projectName = 'HelloWorld'; let appTree: Tree; const options: NewGeneratorSchema = { @@ -52,20 +43,14 @@ describe('new generator (V4)', () => { beforeAll(async () => { appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - await initProjecteGenerator(appTree, { name: projectName, strict: true, silent: true, v4: true, tags: '' }); - }, 120000); + await initProjecteGenerator(appTree, { name: projectName, strict: true, silent: true, tags: '' }); + }, TEST_TIMEOUT); it.each(supportedTemplates)('%s supported template function', async (template, name, fileName) => { await generator(appTree, { ...options, template, name }); appTree.exists(`apps/${projectName}/src/functions/${fileName}.ts`); }); - it.each(unsupportedTemplates)('%s unsupported V3 template function', async template => { - expect(generator(appTree, { ...options, template, name: 'unsupported-test' })).rejects.toThrowError( - `Template [${template}] is not supported in V4.`, - ); - }); - it('Non existing template', async () => { const template = 'Non existing template'; expect(generator(appTree, { ...options, template, name: 'non-existing-test' })).rejects.toThrowError( diff --git a/packages/func/src/generators/new/v3-tests.spec.ts b/packages/func/src/generators/new/v3-tests.spec.ts deleted file mode 100644 index 54ac3aa..0000000 --- a/packages/func/src/generators/new/v3-tests.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Tree } from '@nx/devkit'; -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import initProjecteGenerator from '../init/generator'; -import generator from './generator'; -import { NewGeneratorSchema } from './schema'; - -jest.mock('@nx/devkit', () => { - const originalModule = jest.requireActual('@nx/devkit'); - - return { - ...originalModule, - installPackagesTask: jest.fn(() => console.log('Imagine installing packages here...')), - }; -}); - -const templates = [ - ['Azure Blob Storage trigger', 'Blob', 'blob'], - ['Durable Functions activity (V3 only)', 'DurableFunctionsActivity', 'durable-functions-activity'], - ['Durable Functions entity', 'DurableFunctionsEntity', 'durable-functions-entity'], - ['Durable Functions Entity HTTP starter (V3 only)', 'DurableFunctionsEntityHttpStart', 'durable-functions-entity-http-start'], - ['Durable Functions HTTP starter (V3 only)', 'DurableFunctionsHttpStart', 'durable-functions-http-start'], - ['Durable Functions orchestrator', 'DurableFunctionsOrchestrator', 'durable-functions-orchestrator'], - ['Azure Event Grid trigger', 'EventGrid', 'event-grid'], - ['Azure Event Hub trigger', 'EventHub', 'event-hub'], - ['HTTP trigger', 'Http', 'http'], - ['IoT Hub (Event Hub) (V3 only)', 'IotHub', 'iot-hub'], - ['Kafka output (V3 only)', 'KafkaOutput', 'kafka-output'], - ['Kafka trigger (V3 only)', 'KafkaTrigger', 'kafka-trigger'], - ['Azure Queue Storage trigger', 'Queue', 'queue'], - ['RabbitMQ trigger (V3 only)', 'RabbitMq', 'rabbit-mq'], - ['SendGrid (V3 only)', 'SendGrid', 'send-grid'], - ['Azure Service Bus Queue trigger', 'ServiceBusQueue', 'service-bus-queue'], - ['Azure Service Bus Topic trigger', 'ServiceBusTopic', 'service-bus-topic'], - ['SignalR negotiate HTTP trigger (V3 only)', 'SignalRNegotiate', 'signal-rnegotiate'], - ['Timer trigger', 'Timer', 'timer'], -] as const; - -describe('new generator (V3)', () => { - const projectName = 'HelloWorld'; - let appTree: Tree; - const options: NewGeneratorSchema = { - project: projectName, - name: 'test-func', - language: 'TypeScript', - template: 'HTTP trigger', - authLevel: 'anonymous', - silent: true, - }; - - beforeAll(async () => { - appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - await initProjecteGenerator(appTree, { name: projectName, strict: true, silent: true, v4: false, tags: '' }); - }); - - it.each(templates)('%s template function', async (template, name, directory) => { - await generator(appTree, { ...options, template, name }); - appTree.exists(`apps/${projectName}/${directory}/index.ts`); - appTree.exists(`apps/${projectName}/${directory}/function.json`); - }); - - it('Unexisting template', async () => { - const template = 'Unexisting template'; - expect(generator(appTree, { ...options, template })).rejects.toThrowError(`Template [${template}] is not supported.`); - }); -}); diff --git a/packages/func/tsconfig.spec.json b/packages/func/tsconfig.spec.json index b7c5120..546f128 100644 --- a/packages/func/tsconfig.spec.json +++ b/packages/func/tsconfig.spec.json @@ -5,5 +5,5 @@ "module": "commonjs", "types": ["jest", "node"] }, - "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "src/generators/init/tests/main-v3.ts"] + "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] }