diff --git a/.github/workflows/azure-static-web-apps-proud-glacier-090545300.yml b/.github/workflows/azure-static-web-apps-proud-glacier-090545300.yml index ee3915f..46fe7c9 100644 --- a/.github/workflows/azure-static-web-apps-proud-glacier-090545300.yml +++ b/.github/workflows/azure-static-web-apps-proud-glacier-090545300.yml @@ -29,7 +29,7 @@ jobs: ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig app_location: "/" # App source code path - api_location: "" # Api source code path - optional + api_location: "/api" # Api source code path - optional output_location: "dist" # Built app content directory - optional ###### End of Repository/Build Configurations ###### diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..036c408 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "ms-azuretools.vscode-azurefunctions" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index edc1364..503d100 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,6 +10,13 @@ "name": "Launch Chrome against localhost", "url": "http://localhost:5200", "webRoot": "${workspaceFolder}" + }, + { + "name": "Attach to Node Functions", + "type": "node", + "request": "attach", + "port": 9229, + "preLaunchTask": "func: host start" } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 7b98f6e..1fbd1b4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,10 @@ { - "angular.enable-strict-mode-prompt": false + "angular.enable-strict-mode-prompt": false, + "azureFunctions.deploySubpath": "api", + "azureFunctions.postDeployTask": "npm install (functions)", + "azureFunctions.projectLanguage": "JavaScript", + "azureFunctions.projectRuntime": "~4", + "debug.internalConsoleOptions": "neverOpen", + "azureFunctions.projectLanguageModel": 4, + "azureFunctions.preDeployTask": "npm prune (functions)" } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..3201931 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,33 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "func", + "label": "func: host start", + "command": "host start", + "problemMatcher": "$func-node-watch", + "isBackground": true, + "dependsOn": "npm install (functions)", + "options": { + "cwd": "${workspaceFolder}/api" + } + }, + { + "type": "shell", + "label": "npm install (functions)", + "command": "npm install", + "options": { + "cwd": "${workspaceFolder}/api" + } + }, + { + "type": "shell", + "label": "npm prune (functions)", + "command": "npm prune --production", + "problemMatcher": [], + "options": { + "cwd": "${workspaceFolder}/api" + } + } + ] +} \ No newline at end of file diff --git a/api/.funcignore b/api/.funcignore new file mode 100644 index 0000000..3fbdeb4 --- /dev/null +++ b/api/.funcignore @@ -0,0 +1,10 @@ +*.js.map +*.ts +.git* +.vscode +__azurite_db*__.json +__blobstorage__ +__queuestorage__ +local.settings.json +test +tsconfig.json \ No newline at end of file diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..01774db --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,99 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TypeScript output +dist +out + +# Azure Functions artifacts +bin +obj +appsettings.json +local.settings.json + +# Azurite artifacts +__blobstorage__ +__queuestorage__ +__azurite_db*__.json \ No newline at end of file diff --git a/api/host.json b/api/host.json new file mode 100644 index 0000000..05291ed --- /dev/null +++ b/api/host.json @@ -0,0 +1,15 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + }, + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle", + "version": "[1.*, 2.0.0)" + } +} \ No newline at end of file diff --git a/api/local.settings.sample.json b/api/local.settings.sample.json new file mode 100644 index 0000000..e4f5c2e --- /dev/null +++ b/api/local.settings.sample.json @@ -0,0 +1,13 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "", + "FUNCTIONS_WORKER_RUNTIME": "node", + "AzureWebJobsFeatureFlags": "EnableWorkerIndexing", + "EnvName": "CDEV - JSON", + "IsFirebase": false, + "FireBaseAPIKey": "AIzaSyCubx8YGktd3hNv6_8wKGdRYaCqsmN3JU4", + "IsRestAPI": true, + "RESTLoggingUrl": "https://ngangularpracticesapi.azurewebsites.net/logger" + } +} \ No newline at end of file diff --git a/api/package-lock.json b/api/package-lock.json new file mode 100644 index 0000000..428ca3c --- /dev/null +++ b/api/package-lock.json @@ -0,0 +1,61 @@ +{ + "name": "api", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "api", + "version": "1.0.0", + "dependencies": { + "@azure/functions": "^4.0.0" + }, + "devDependencies": {} + }, + "node_modules/@azure/functions": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@azure/functions/-/functions-4.4.0.tgz", + "integrity": "sha512-debidWolFTsfapsK53ftzLtXJc3dbYYPc9UqJoEm1GAj1lS7jFMARQnbfTQPDqBIhuJxLZ9D8WVvhIEV7Hifzw==", + "dependencies": { + "cookie": "^0.6.0", + "long": "^4.0.0", + "undici": "^5.13.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + } + } +} diff --git a/api/package.json b/api/package.json new file mode 100644 index 0000000..3350148 --- /dev/null +++ b/api/package.json @@ -0,0 +1,14 @@ +{ + "name": "api", + "version": "1.0.0", + "description": "", + "scripts": { + "start": "func start", + "test": "echo \"No tests yet...\"" + }, + "dependencies": { + "@azure/functions": "^4.0.0" + }, + "devDependencies": {}, + "main": "src/functions/*.js" +} \ No newline at end of file diff --git a/api/src/functions/GetConfig.js b/api/src/functions/GetConfig.js new file mode 100644 index 0000000..4581f40 --- /dev/null +++ b/api/src/functions/GetConfig.js @@ -0,0 +1,21 @@ +const { app } = require('@azure/functions'); + +app.http('GetConfig', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + handler: async (request, context) => { + context.log(`Http function processed request for url "${request.url}"`); + + const name = request.query.get('name') || await request.text() || 'world'; + + const config = { + "EnvName": process.env['EnvName'], + "IsFirebase": process.env['IsFirebase'], + "FireBaseAPIKey": process.env['FireBaseAPIKey'], + "IsRestAPI": process.env['IsRestAPI'], + "RESTLoggingUrl": process.env['RESTLoggingUrl'] + } + + return { body: config }; + } +}); diff --git a/package.json b/package.json index 38fbd6d..9af11c9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build": "ng build --prod", "test": "ng test --code-coverage", "lint": "ng lint", - "e2e": "ng e2e" + "e2e": "ng e2e", + "spa": "swa start dist/angular-basic --api-location api" }, "private": true, "dependencies": { @@ -31,6 +32,7 @@ "@angular-devkit/build-angular": "~0.1000.6", "@angular/cli": "~10.0.6", "@angular/compiler-cli": "~10.0.9", + "@azure/static-web-apps-cli": "^1.1.7", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", @@ -48,4 +50,4 @@ "tslint": "~6.1.0", "typescript": "~3.9.5" } -} \ No newline at end of file +} diff --git a/src/app/core/app-config/app-config.service.ts b/src/app/core/app-config/app-config.service.ts index 28219fb..242f19f 100644 --- a/src/app/core/app-config/app-config.service.ts +++ b/src/app/core/app-config/app-config.service.ts @@ -12,7 +12,7 @@ export class AppConfigService { constructor(private http: HttpClient) { } public loadConfig() { - return this.http.get('./assets/config/config.json') + return this.http.get('/api/GetConfig') .toPromise() .then((config: any) => {