From cb70826a8bd50d596ac84eed2219b023e51165dc Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 5 Aug 2025 16:00:58 +0100 Subject: [PATCH 1/3] Add prettier Install prettier. --- .editorconfig | 7 +++---- .prettierignore | 3 +++ package-lock.json | 17 +++++++++++++++++ package.json | 21 ++++++++++++++++++--- 4 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 .prettierignore diff --git a/.editorconfig b/.editorconfig index 2c2737c..2875ac6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,12 +1,11 @@ -# http://editorconfig.org root = true [*] -indent_style = space -indent_size = 2 charset = utf-8 -trim_trailing_whitespace = true +indent_size = 2 +indent_style = space insert_final_newline = true +trim_trailing_whitespace = true [*.cs] indent_size = 4 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6de9a76 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +dist/ +lib/ +node_modules/ diff --git a/package-lock.json b/package-lock.json index 81bc8a8..605e344 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "devDependencies": { "glob": "^11.0.3", "mocha": "^11.7.1", + "prettier": "3.6.2", "yeoman-assert": "^3.1.1", "yeoman-environment": "^4.4.3", "yeoman-test": "^10.1.1" @@ -4684,6 +4685,22 @@ "node": ">=4" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-bytes": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", diff --git a/package.json b/package.json index 6024630..77a6f97 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,10 @@ "url": "https://github.com/jerriep" }, "scripts": { - "test": "mocha" + "format": "prettier --write **/*.js", + "format-check": "prettier --check **/*.js", + "test": "mocha", + "all": "npm run format && npm test" }, "files": [ "generators" @@ -32,14 +35,26 @@ "dependencies": { "cross-fetch": "^4.1.0", "query-string": "^9.2.2", - "yosay": "^3.0.0", - "yeoman-generator": "^7.5.1" + "yeoman-generator": "^7.5.1", + "yosay": "^3.0.0" }, "devDependencies": { "glob": "^11.0.3", "mocha": "^11.7.1", + "prettier": "3.6.2", "yeoman-assert": "^3.1.1", "yeoman-environment": "^4.4.3", "yeoman-test": "^10.1.1" + }, + "prettier": { + "arrowParens": "always", + "bracketSpacing": true, + "printWidth": 140, + "quoteProps": "consistent", + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": false } } From 299b2f9c259eda6c33127c6483ef317e4f95c254 Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 5 Aug 2025 16:04:20 +0100 Subject: [PATCH 2/3] Run prettier Run prettier on the JavaScript code. --- generators/app/index.js | 106 ++++++++++++++++++++++++---------------- package.json | 2 +- test/test-app.js | 57 +++++++++++++++------ 3 files changed, 108 insertions(+), 57 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index 3624b4b..b20f6e3 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -5,43 +5,44 @@ import queryString from 'query-string'; import yosay from 'yosay'; export default class extends Generator { - initializing() { this.templateData = {}; this.log(yosay('Welcome to the classy ASP.NET OAuth Provider generator!')); } async prompting() { - const prompts = [{ - type: 'input', - name: 'name', - message: 'What is the name of the provider you want to create?', - store: true - }, - { - type: 'input', - name: 'authorname', - message: 'What is your name?', - store: true - }, - { - type: 'input', - name: 'authorizationendpoint', - message: 'What is the Authorization Endpoint for this service?', - store: true - }, - { - type: 'input', - name: 'tokenendpoint', - message: 'What is the Token Endpoint for this service?', - store: true - }, - { - type: 'input', - name: 'userinformationendpoint', - message: 'What is the User Information Endpoint for this service?', - store: true - }]; + const prompts = [ + { + type: 'input', + name: 'name', + message: 'What is the name of the provider you want to create?', + store: true, + }, + { + type: 'input', + name: 'authorname', + message: 'What is your name?', + store: true, + }, + { + type: 'input', + name: 'authorizationendpoint', + message: 'What is the Authorization Endpoint for this service?', + store: true, + }, + { + type: 'input', + name: 'tokenendpoint', + message: 'What is the Token Endpoint for this service?', + store: true, + }, + { + type: 'input', + name: 'userinformationendpoint', + message: 'What is the User Information Endpoint for this service?', + store: true, + }, + ]; const answers = await this.prompt(prompts); @@ -58,15 +59,34 @@ export default class extends Generator { } writing() { - this.fs.copyTpl(this.templatePath('Project.csproj'), this.applicationName + '/' + this.applicationName + '.csproj', this.templateData) - this.fs.copyTpl(this.templatePath('AuthenticationDefaults.cs'), this.applicationName + '/' + this.name + 'AuthenticationDefaults.cs', this.templateData) - this.fs.copyTpl(this.templatePath('AuthenticationExtensions.cs'), this.applicationName + '/' + this.name + 'AuthenticationExtensions.cs', this.templateData) - this.fs.copyTpl(this.templatePath('AuthenticationHandler.cs'), this.applicationName + '/' + this.name + 'AuthenticationHandler.cs', this.templateData) - this.fs.copyTpl(this.templatePath('AuthenticationOptions.cs'), this.applicationName + '/' + this.name + 'AuthenticationOptions.cs', this.templateData) + this.fs.copyTpl( + this.templatePath('Project.csproj'), + this.applicationName + '/' + this.applicationName + '.csproj', + this.templateData + ); + this.fs.copyTpl( + this.templatePath('AuthenticationDefaults.cs'), + this.applicationName + '/' + this.name + 'AuthenticationDefaults.cs', + this.templateData + ); + this.fs.copyTpl( + this.templatePath('AuthenticationExtensions.cs'), + this.applicationName + '/' + this.name + 'AuthenticationExtensions.cs', + this.templateData + ); + this.fs.copyTpl( + this.templatePath('AuthenticationHandler.cs'), + this.applicationName + '/' + this.name + 'AuthenticationHandler.cs', + this.templateData + ); + this.fs.copyTpl( + this.templatePath('AuthenticationOptions.cs'), + this.applicationName + '/' + this.name + 'AuthenticationOptions.cs', + this.templateData + ); } async getCurrentVersion() { - let response = await fetch('https://api.nuget.org/v3/index.json'); if (!response.ok) { @@ -74,7 +94,9 @@ export default class extends Generator { } const serviceIndex = await response.json(); - const baseAddress = serviceIndex.resources.find(resource => resource['@type'] === 'SearchQueryService/3.5.0')['@id']; + const baseAddress = serviceIndex.resources.find( + (resource) => resource['@type'] === 'SearchQueryService/3.5.0' + )['@id']; if (!baseAddress) { throw new Error('Failed to determine the base address for the NuGet search query service.'); @@ -84,14 +106,16 @@ export default class extends Generator { prerelease: false, q: 'PackageId:AspNet.Security.OAuth.GitHub', semVerLevel: '2.0.0', - take: 1 + take: 1, }); const searchUrl = `${baseAddress}?${query}`; response = await fetch(searchUrl); if (!response.ok) { - throw new Error(`Failed to search for NuGet package from '${searchUrl}'. HTTP status code: ${response.status}.`); + throw new Error( + `Failed to search for NuGet package from '${searchUrl}'. HTTP status code: ${response.status}.` + ); } const searchResult = await response.json(); @@ -115,4 +139,4 @@ export default class extends Generator { return versionParts.join(dot); } -}; +} diff --git a/package.json b/package.json index 77a6f97..fea0114 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "prettier": { "arrowParens": "always", "bracketSpacing": true, - "printWidth": 140, + "printWidth": 100, "quoteProps": "consistent", "semi": true, "singleQuote": true, diff --git a/test/test-app.js b/test/test-app.js index 06fabe2..3569e6f 100644 --- a/test/test-app.js +++ b/test/test-app.js @@ -14,14 +14,15 @@ const __dirname = path.dirname(__filename); describe('aspnet-oauth:app', () => { before(async function () { this.timeout(10000); - await helpers.run(path.join(__dirname, '../generators/app')) + await helpers + .run(path.join(__dirname, '../generators/app')) .withOptions({ skipInstall: true }) .withAnswers({ name: 'Foo', authorname: 'John Smith', authorizationendpoint: 'https://foo.local/auth', tokenendpoint: 'https://foo.local/token', - userinformationendpoint: 'https://foo.local/user' + userinformationendpoint: 'https://foo.local/user', }); }); @@ -31,7 +32,7 @@ describe('aspnet-oauth:app', () => { 'AspNet.Security.OAuth.Foo/FooAuthenticationDefaults.cs', 'AspNet.Security.OAuth.Foo/FooAuthenticationExtensions.cs', 'AspNet.Security.OAuth.Foo/FooAuthenticationHandler.cs', - 'AspNet.Security.OAuth.Foo/FooAuthenticationOptions.cs' + 'AspNet.Security.OAuth.Foo/FooAuthenticationOptions.cs', ]); }); it('sets the authors name', () => { @@ -144,7 +145,6 @@ describe('aspnet-oauth:app', () => { }); describe('generating a new provider', () => { - const projectName = 'AspNet.Security.OAuth.Foo'; const tempDir = path.join(os.tmpdir(), `_generator-aspnet-oauth-${Math.random()}`); const artifactsDir = path.join(tempDir, 'artifacts'); @@ -156,9 +156,11 @@ describe('aspnet-oauth:app', () => { this.timeout(180000); // Clone the providers repository to add the project to - const clone = spawnSync( - 'git', - ['clone', 'https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers.git', tempDir]); + const clone = spawnSync('git', [ + 'clone', + 'https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers.git', + tempDir, + ]); if (clone.status !== 0 && clone.output) { console.error(clone.output.toString('utf8')); @@ -166,7 +168,8 @@ describe('aspnet-oauth:app', () => { assert.strictEqual(clone.status, 0); // Run the generator to create the project - context = await helpers.run(path.join(__dirname, '../generators/app'), { tmpdir: false }) + context = await helpers + .run(path.join(__dirname, '../generators/app'), { tmpdir: false }) .cd(sourceDir) .withOptions({ skipInstall: true }) .withPrompts({ @@ -174,14 +177,15 @@ describe('aspnet-oauth:app', () => { authorname: 'John Smith', authorizationendpoint: 'https://foo.local/auth', tokenendpoint: 'https://foo.local/token', - userinformationendpoint: 'https://foo.local/user' + userinformationendpoint: 'https://foo.local/user', }); // Add the new project to the solution const dotnetSlnAdd = spawnSync( `dotnet`, ['sln', 'add', path.join(projectDir, `${projectName}.csproj`)], - { cwd: tempDir }); + { cwd: tempDir } + ); if (dotnetSlnAdd.status !== 0) { console.error(dotnetSlnAdd.output.toString('utf8')); @@ -192,9 +196,14 @@ describe('aspnet-oauth:app', () => { let build; if (process.platform === 'win32') { - build = spawnSync('build.cmd', ['-test', '-pack', '-configuration', configuration], { cwd: tempDir, shell: true }); + build = spawnSync('build.cmd', ['-test', '-pack', '-configuration', configuration], { + cwd: tempDir, + shell: true, + }); } else { - build = spawnSync('./build.sh', ['--test', '--pack', '--configuration', configuration], { cwd: tempDir }); + build = spawnSync('./build.sh', ['--test', '--pack', '--configuration', configuration], { + cwd: tempDir, + }); } if (build.status !== 0 && build.output) { @@ -204,15 +213,33 @@ describe('aspnet-oauth:app', () => { }); it('compiles the provider', async () => { - const expected = path.join(artifactsDir, 'bin', projectName, configuration, 'net*', `${projectName}.dll`); + const expected = path.join( + artifactsDir, + 'bin', + projectName, + configuration, + 'net*', + `${projectName}.dll` + ); await glob(expected); }); it('generates the NuGet package', async () => { - const expected = path.join(artifactsDir, 'packages', configuration, 'Shipping', `${projectName}.*.nupkg`); + const expected = path.join( + artifactsDir, + 'packages', + configuration, + 'Shipping', + `${projectName}.*.nupkg` + ); await glob(expected); }); it('runs the tests', async () => { - const expected = path.join(artifactsDir, 'TestResults', configuration, 'AspNet.Security.OAuth.Providers.Tests_net*_x64.html'); + const expected = path.join( + artifactsDir, + 'TestResults', + configuration, + 'AspNet.Security.OAuth.Providers.Tests_net*_x64.html' + ); await glob(expected); }); }); From 8cb75cb52ac7040e62855b1ab2db47de3a6f01a4 Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 5 Aug 2025 16:06:59 +0100 Subject: [PATCH 3/3] Add lint to CI Validate code against lint rules in CI. --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dba334e..c83f159 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,6 +50,10 @@ jobs: with: dotnet-version: '9.0.x' + - name: Lint + run: | + npm run format-check + - name: Test run: | npm test