@nzz/q-cli 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. package/bin/commands/bootstrap.js +0 -1
  2. package/bin/q.js +30 -5
  3. package/package.json +2 -2
  4. package/skeletons/et-utils-package-skeleton/README.md +5 -0
  5. package/skeletons/et-utils-package-skeleton/jest.config.ts +17 -0
  6. package/skeletons/et-utils-package-skeleton/package.json +19 -13
  7. package/skeletons/et-utils-package-skeleton/scripts/package-fixup.sh +13 -0
  8. package/skeletons/et-utils-package-skeleton/test/Service.spec.ts +1 -10
  9. package/skeletons/et-utils-package-skeleton/test/tsconfig.json +8 -0
  10. package/skeletons/et-utils-package-skeleton/tsconfig-base.json +10 -0
  11. package/skeletons/et-utils-package-skeleton/tsconfig-cjs.json +8 -0
  12. package/skeletons/et-utils-package-skeleton/tsconfig.json +4 -5
  13. package/skeletons/toolv2-skeleton/.husky/pre-commit +6 -0
  14. package/skeletons/toolv2-skeleton/.nvmrc +1 -0
  15. package/skeletons/toolv2-skeleton/.prettierrc.cjs +15 -0
  16. package/skeletons/toolv2-skeleton/.travis.yml +30 -0
  17. package/skeletons/toolv2-skeleton/.vscode/settings.json +6 -0
  18. package/skeletons/toolv2-skeleton/Dockerfile +19 -0
  19. package/skeletons/toolv2-skeleton/LICENSE +21 -0
  20. package/skeletons/toolv2-skeleton/README.md +99 -0
  21. package/skeletons/toolv2-skeleton/dev.js +7 -0
  22. package/skeletons/toolv2-skeleton/index.js +39 -0
  23. package/skeletons/toolv2-skeleton/jest.config.ts +39 -0
  24. package/skeletons/toolv2-skeleton/nodemon.json +4 -0
  25. package/skeletons/toolv2-skeleton/package-lock.json +21382 -0
  26. package/skeletons/toolv2-skeleton/package.json +80 -0
  27. package/skeletons/toolv2-skeleton/resources/display-options-schema.json +11 -0
  28. package/skeletons/toolv2-skeleton/resources/locales/de/translation.json +8 -0
  29. package/skeletons/toolv2-skeleton/resources/locales/en/translation.json +10 -0
  30. package/skeletons/toolv2-skeleton/resources/locales/fr/translation.json +10 -0
  31. package/skeletons/toolv2-skeleton/resources/schema.json +66 -0
  32. package/skeletons/toolv2-skeleton/rollup.config.js +48 -0
  33. package/skeletons/toolv2-skeleton/scripts/postinstall.sh +5 -0
  34. package/skeletons/toolv2-skeleton/src/.eslintrc.cjs +52 -0
  35. package/skeletons/toolv2-skeleton/src/components/Main.spec.ts +15 -0
  36. package/skeletons/toolv2-skeleton/src/components/Main.svelte +32 -0
  37. package/skeletons/toolv2-skeleton/src/enums.ts +11 -0
  38. package/skeletons/toolv2-skeleton/src/helpers/fixture-generators.ts +38 -0
  39. package/skeletons/toolv2-skeleton/src/helpers/toolRuntimeConfig.ts +15 -0
  40. package/skeletons/toolv2-skeleton/src/interfaces.ts +82 -0
  41. package/skeletons/toolv2-skeleton/src/modules.d.ts +8 -0
  42. package/skeletons/toolv2-skeleton/src/routes/dynamic-schemas/exampleDynamicSchema.ts +49 -0
  43. package/skeletons/toolv2-skeleton/src/routes/dynamic-schemas/index.ts +5 -0
  44. package/skeletons/toolv2-skeleton/src/routes/health.ts +14 -0
  45. package/skeletons/toolv2-skeleton/src/routes/locales.ts +31 -0
  46. package/skeletons/toolv2-skeleton/src/routes/notifications/exampleNotification.ts +46 -0
  47. package/skeletons/toolv2-skeleton/src/routes/option-availability.ts +27 -0
  48. package/skeletons/toolv2-skeleton/src/routes/rendering-info/web.ts +150 -0
  49. package/skeletons/toolv2-skeleton/src/routes/routes.ts +21 -0
  50. package/skeletons/toolv2-skeleton/src/routes/schema.ts +21 -0
  51. package/skeletons/toolv2-skeleton/src/routes/stylesheet.ts +31 -0
  52. package/skeletons/toolv2-skeleton/src/styles/main.scss +6 -0
  53. package/skeletons/toolv2-skeleton/svelte.config.cjs +6 -0
  54. package/skeletons/toolv2-skeleton/tasks/compileStyleFiles.cjs +101 -0
  55. package/skeletons/toolv2-skeleton/tests/e2e-tests.spec.ts +158 -0
  56. package/skeletons/toolv2-skeleton/tests/helpers.ts +21 -0
  57. package/skeletons/toolv2-skeleton/tsconfig.json +48 -0
  58. package/skeletons/et-utils-package-skeleton/rollup.config.js +0 -17
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "[tool-name]",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "rollup -c rollup.config.js && npm run compile-style-files",
9
+ "compile-style-files": "node tasks/compileStyleFiles.cjs",
10
+ "dev": "npm run build && node dev.js",
11
+ "jest": "NODE_OPTIONS='--experimental-vm-modules --experimental-specifier-resolution=node' jest --config jest.config.ts",
12
+ "lint": "eslint --fix --ext .svelte,.ts --config src/.eslintrc.cjs src",
13
+ "lint:all": "run-s -c lint ts-check svelte-check",
14
+ "postinstall": "scripts/postinstall.sh",
15
+ "prettier-format": "prettier --write src/",
16
+ "start": "nodemon --exec \"npm run dev\"",
17
+ "svelte-check": "svelte-check",
18
+ "test": "npm run build && npm run jest",
19
+ "ts-check": "tsc --noEmit"
20
+ },
21
+ "author": "",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@hapi/boom": "^9.1.3",
25
+ "@hapi/hapi": "^20.2.1",
26
+ "@hapi/inert": "^6.0.3",
27
+ "ajv": "^6.12.6",
28
+ "clone": "^2.1.2",
29
+ "d3-format": "^1.4.5",
30
+ "joi": "^17.4.2",
31
+ "simple-statistics": "^7.7.0",
32
+ "svelte": "^3.48.0",
33
+ "uglify-js": "^3.14.3"
34
+ },
35
+ "devDependencies": {
36
+ "@hapi/code": "^8.0.5",
37
+ "@ota-meshi/eslint-plugin-svelte": "^0.34.1",
38
+ "@rollup/plugin-alias": "^3.1.9",
39
+ "@rollup/plugin-json": "^4.1.0",
40
+ "@rollup/plugin-node-resolve": "^13.3.0",
41
+ "@rollup/plugin-typescript": "^8.3.3",
42
+ "@testing-library/jest-dom": "^5.16.4",
43
+ "@testing-library/svelte": "^3.1.3",
44
+ "@tsconfig/svelte": "^3.0.0",
45
+ "@types/d3": "^7.4.0",
46
+ "@types/hapi__inert": "^5.2.3",
47
+ "@types/jest": "^28.1.1",
48
+ "@types/jsdom": "^16.2.14",
49
+ "@types/node": "^17.0.35",
50
+ "@types/uglify-js": "^3.13.2",
51
+ "@typescript-eslint/eslint-plugin": "^5.27.0",
52
+ "@typescript-eslint/parser": "^5.27.0",
53
+ "autoprefixer": "^9.8.8",
54
+ "cssnano": "^4.1.11",
55
+ "eslint": "^8.16.0",
56
+ "eslint-svelte3-preprocess": "^0.0.5",
57
+ "html-minifier": "^4.0.0",
58
+ "husky": "^8.0.1",
59
+ "jest": "^28.1.1",
60
+ "jest-environment-jsdom": "^28.1.2",
61
+ "jsdom": "^16.7.0",
62
+ "nodemon": "^2.0.16",
63
+ "npm-run-all": "^4.1.5",
64
+ "postcss": "^7.0.39",
65
+ "postcss-import": "^12.0.1",
66
+ "prettier": "^2.7.1",
67
+ "prettier-plugin-svelte": "^2.7.0",
68
+ "rollup": "^2.75.6",
69
+ "rollup-plugin-svelte": "^7.1.0",
70
+ "rollup-plugin-terser": "^7.0.2",
71
+ "sass": "^1.43.5",
72
+ "svelte-check": "^2.8.0",
73
+ "svelte-jester": "^2.3.2",
74
+ "svelte-preprocess": "^4.10.7",
75
+ "svelte-strip": "^1.0.1",
76
+ "ts-jest": "^28.0.5",
77
+ "ts-node": "^10.8.0",
78
+ "typescript": "^4.7.4"
79
+ }
80
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "title": "Anzeigeoptionen",
5
+ "properties": {
6
+ "hideTitle": {
7
+ "type": "boolean",
8
+ "title": "Titel ausblenden"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "notifications": {
3
+ "exampleNotification": {
4
+ "title": "Title",
5
+ "body": "body."
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "Title": "Title",
3
+ "Untertitel": "Subtitle",
4
+ "notifications": {
5
+ "exampleNotification": {
6
+ "title": "Title",
7
+ "body": "body."
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "Title": "Titre",
3
+ "Untertitel": "Sous-titre",
4
+ "notifications": {
5
+ "exampleNotification": {
6
+ "title": "Title",
7
+ "body": "body."
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "title": "[tool-name]",
5
+ "properties": {
6
+ "title": {
7
+ "title": "Titel",
8
+ "type": "string"
9
+ },
10
+ "subtitle": {
11
+ "title": "Untertitel",
12
+ "type": "string"
13
+ }
14
+ },
15
+ "options": {
16
+ "title": "Optionen",
17
+ "type": "object",
18
+ "properties": {
19
+ "showSearch": {
20
+ "title": "Suche anzeigen",
21
+ "type": "boolean",
22
+ "default": false,
23
+ "Q:options": {
24
+ "availabilityChecks": [
25
+ {
26
+ "type": "ToolEndpoint",
27
+ "config": {
28
+ "endpoint": "option-availability/showSearch",
29
+ "fields": [
30
+ "options"
31
+ ]
32
+ }
33
+ }
34
+ ],
35
+ "notificationChecks": [
36
+ {
37
+ "type": "ToolEndpoint",
38
+ "config": {
39
+ "endpoint": "notification/exampleNotification",
40
+ "fields": [
41
+ "options"
42
+ ]
43
+ },
44
+ "priority": {
45
+ "type": "medium",
46
+ "value": 2
47
+ }
48
+ }
49
+ ],
50
+ "dynamicSchema": {
51
+ "type": "ToolEndpoint",
52
+ "config": {
53
+ "endpoint": "dynamic-schema/exampleDynamicSchema",
54
+ "fields": [
55
+ "options"
56
+ ]
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "required": [
64
+ "title"
65
+ ]
66
+ }
@@ -0,0 +1,48 @@
1
+ import alias from '@rollup/plugin-alias';
2
+ import json from '@rollup/plugin-json';
3
+ import nodeResolve from '@rollup/plugin-node-resolve';
4
+ import svelte from 'rollup-plugin-svelte';
5
+ import sveltePreprocess from 'svelte-preprocess';
6
+ import typescript from '@rollup/plugin-typescript';
7
+ import { terser } from 'rollup-plugin-terser';
8
+
9
+ const backendConfig = {
10
+ input: 'src/routes/routes.ts',
11
+ output: {
12
+ file: 'dist/routes.js',
13
+ format: 'es',
14
+ },
15
+ plugins: [typescript(), json()],
16
+ external: ['@hapi/boom', 'ajv', 'd3-format', 'joi', 'module', 'path', 'simple-statistics', 'svelte/internal', 'uglify-js', 'url'],
17
+ };
18
+
19
+ const frontendConfig = {
20
+ input: 'src/components/main.svelte',
21
+ output: {
22
+ name: 'window.[tool_name]',
23
+ file: 'dist/[Tool-name].js',
24
+ format: 'iife',
25
+ },
26
+ plugins: [
27
+ typescript(),
28
+ json(),
29
+ svelte({
30
+ preprocess: sveltePreprocess(),
31
+ emitCss: false,
32
+ compilerOptions: {},
33
+ }),
34
+ nodeResolve({ browser: true }),
35
+ terser(),
36
+
37
+ alias({
38
+ entries: [
39
+ // If you add a new top-level-folder besides src which you want to use, add it here.
40
+ { find: /^@src(\/|$)/, replacement: `${__dirname}/src/` },
41
+ { find: /^@cps(\/|$)/, replacement: `${__dirname}/src/components/` },
42
+ { find: /^@helpers(\/|$)/, replacement: `${__dirname}/src/helpers/` },
43
+ ],
44
+ }),
45
+ ],
46
+ };
47
+
48
+ export default [frontendConfig, backendConfig];
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
3
+ git init;
4
+ husky install;
5
+ fi
@@ -0,0 +1,52 @@
1
+ module.exports = {
2
+ root: true,
3
+ parser: '@typescript-eslint/parser',
4
+ extends: [
5
+ 'eslint:recommended',
6
+
7
+ // Disables rules from eslint:recommended which are already handled by TypeScript.
8
+ 'plugin:@typescript-eslint/eslint-recommended',
9
+
10
+ // Typescript defined rules for linter.
11
+ 'plugin:@typescript-eslint/recommended',
12
+ 'plugin:@typescript-eslint/recommended-requiring-type-checking',
13
+
14
+ // eslint-plugin-svelte rules.
15
+ 'plugin:@ota-meshi/svelte/recommended',
16
+ ],
17
+ parserOptions: {
18
+ ecmaVersion: 2020,
19
+ sourceType: 'module',
20
+ tsconfigRootDir: __dirname + '/..',
21
+ project: ['tsconfig.json'],
22
+ extraFileExtensions: ['.svelte'],
23
+ },
24
+ env: {
25
+ es6: true,
26
+ browser: true,
27
+ },
28
+ overrides: [
29
+ {
30
+ files: ['*.svelte'],
31
+ parser: 'svelte-eslint-parser',
32
+ parserOptions: {
33
+ parser: '@typescript-eslint/parser',
34
+ },
35
+ },
36
+ ],
37
+ settings: {},
38
+ plugins: ['@ota-meshi/svelte', '@typescript-eslint'],
39
+ ignorePatterns: ['*.cjs', 'node_modules'],
40
+ rules: {
41
+ quotes: [2, 'single'],
42
+ '@typescript-eslint/no-explicit-any': 'error',
43
+ '@typescript-eslint/triple-slash-reference': 'off',
44
+ '@typescript-eslint/restrict-template-expressions': 'off',
45
+ '@typescript-eslint/explicit-function-return-type': [
46
+ 'error',
47
+ {
48
+ allowExpressions: true,
49
+ },
50
+ ],
51
+ },
52
+ };
@@ -0,0 +1,15 @@
1
+ import Main from './Main.svelte';
2
+ import { render } from '@testing-library/svelte';
3
+ import { create[ToolName]SveltePropertiesFixture } from '@src/helpers/fixture-generators';
4
+
5
+ describe('[Tool-name]', () => {
6
+ it('shows the component correctly', () => {
7
+ const componentProps = create[ToolName]SveltePropertiesFixture();
8
+
9
+ const { container } = render(Main, { props: { componentProps } });
10
+
11
+ const el = container.getElementsByClassName('s-q-item')[0];
12
+
13
+ expect(el).toBeInstanceOf(HTMLDivElement);
14
+ });
15
+ });
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import type { [ToolName]SvelteProperties } from '@src/interfaces';
3
+
4
+ // You must type it expclitly to have no lint errors.
5
+ export let componentProps: [ToolName]SvelteProperties;
6
+
7
+ // Extract const heres.
8
+ const { config, displayOptions, id } = componentProps;
9
+
10
+ // Extract dynamic using let instead of cost.
11
+ // let { dynProp } = componentProps;
12
+
13
+ function shouldShowTitle(): boolean {
14
+ if (typeof displayOptions.hideTitle === 'boolean') {
15
+ return !displayOptions.hideTitle;
16
+ }
17
+
18
+ return true;
19
+ }
20
+ </script>
21
+
22
+ <div {id} class="s-q-item">
23
+ {#if shouldShowTitle()}
24
+ <h3 class="s-q-item__title">{config.title}</h3>
25
+ {/if}
26
+
27
+ {#if config.subtitle && config.subtitle !== ''}
28
+ <div class="s-q-item__subtitle">{config.subtitle}</div>
29
+ {/if}
30
+
31
+ Your first [Tool-name]!
32
+ </div>
@@ -0,0 +1,11 @@
1
+ // Put enums here.
2
+
3
+ /**
4
+ * Example
5
+ */
6
+ export const enum LEGEND_ID {
7
+ SMALL = 'small',
8
+ MEDIAN = 'median',
9
+ LARGE = 'large',
10
+ AVERAGE = 'average',
11
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Put all fixture generators here.
3
+ * Or if the file gets too big split them up to your liking.
4
+ */
5
+ import type { DisplayOptions, [ToolName]Config, [ToolName]ConfigOptions, [ToolName]SvelteProperties } from '@src/interfaces';
6
+
7
+ export function create[ToolName]SveltePropertiesFixture(): [ToolName]SvelteProperties {
8
+ const displayOptions = createDisplayOptionsFixture();
9
+
10
+ return {
11
+ config: create[ToolName]ConfigFixture(),
12
+ displayOptions,
13
+ id: 'id',
14
+ noInteraction: false,
15
+ width: 400,
16
+ };
17
+ }
18
+
19
+ export function create[ToolName]ConfigFixture(): [ToolName]Config {
20
+ return {
21
+ options: create[ToolName]ConfigOptionsFixture(),
22
+ title: 'title',
23
+ subtitle: 'id',
24
+ };
25
+ }
26
+
27
+ export function create[ToolName]ConfigOptionsFixture(): [ToolName]ConfigOptions {
28
+ return {
29
+ showSearch: true,
30
+ };
31
+ }
32
+
33
+ export function createDisplayOptionsFixture(override: Partial<DisplayOptions> = {}): DisplayOptions {
34
+ return {
35
+ hideTitle: false,
36
+ ...override,
37
+ };
38
+ }
@@ -0,0 +1,15 @@
1
+ import type { ToolRuntimeConfig } from '../interfaces.js';
2
+
3
+ export default function getExactPixelWidth(toolRuntimeConfig: ToolRuntimeConfig): number | undefined {
4
+ if (!toolRuntimeConfig.size || !Array.isArray(toolRuntimeConfig.size.width)) {
5
+ return undefined;
6
+ }
7
+
8
+ for (const width of toolRuntimeConfig.size.width) {
9
+ if (width && width.value && width.comparison === '=' && (!width.unit || width.unit === 'px')) {
10
+ return width.value;
11
+ }
12
+ }
13
+
14
+ return undefined;
15
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * These interface are the basic setup for your [Tool-name] to run.
3
+ */
4
+
5
+ /**
6
+ * What is received by your [Tool-name]'s backend.
7
+ */
8
+ export interface WebPayload {
9
+ item: [ToolName]Config;
10
+ itemStateInDb: boolean;
11
+ toolRuntimeConfig: ToolRuntimeConfig;
12
+ }
13
+
14
+ /**
15
+ * The total config file.
16
+ */
17
+ export interface [ToolName]Config {
18
+ options: [ToolName]ConfigOptions;
19
+ title: string;
20
+ subtitle: string;
21
+ }
22
+
23
+ /**
24
+ * Specific options for this Q-item.
25
+ */
26
+ export interface [ToolName]ConfigOptions {
27
+ showSearch: boolean;
28
+ }
29
+
30
+ export interface DisplayOptions {
31
+ hideTitle?: boolean;
32
+ }
33
+
34
+ /**
35
+ * Specific options set for this runtime.
36
+ */
37
+ export interface ToolRuntimeConfig {
38
+ displayOptions?: DisplayOptions;
39
+ fileRequestBaseUrl: string;
40
+ toolBaseUrl: string;
41
+ id: string;
42
+ size: {
43
+ width: Array<{ value: number; unit: string; comparison: '=' | '>' | '<' | '>=' | '<=' }>;
44
+ };
45
+ isPure: boolean;
46
+ requestId: string;
47
+ markup?: string;
48
+ noInteraction?: boolean;
49
+ }
50
+
51
+ /**
52
+ * What is sent to the front-end.
53
+ */
54
+ export interface RenderingInfo {
55
+ polyfills: string[];
56
+ stylesheets: Array<{ name: string }>;
57
+ scripts: Array<{ content: string }>;
58
+ markup: string;
59
+ }
60
+
61
+ /**
62
+ * Standard interface for availability checks.
63
+ */
64
+ export interface AvailabilityResponseObject {
65
+ available: boolean;
66
+ }
67
+
68
+ /**
69
+ * The config that you pass into your main svelte component.
70
+ * This is the entry point of your interacte Q-item.
71
+ */
72
+ export interface [ToolName]SvelteProperties {
73
+ config: [ToolName]Config;
74
+ displayOptions: DisplayOptions;
75
+ noInteraction: boolean;
76
+ id: string;
77
+ width: number | undefined;
78
+ }
79
+
80
+ export interface StyleHashMap {
81
+ main: string;
82
+ }
@@ -0,0 +1,8 @@
1
+ // The references is required to register the inert extension onto hapi__hapi so that
2
+ // the h.file line is registered correctly by typescript.
3
+ /// <reference path="../node_modules/@types/hapi__inert/index.d.ts"/>
4
+
5
+
6
+ // https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html
7
+ // https://www.typescriptlang.org/docs/handbook/modules.html
8
+ // https://www.typescriptlang.org/docs/handbook/declaration-files/templates.html
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Dynamic schemas return options to a field that change depending
3
+ * other settings. Hence, dynamic options.
4
+ *
5
+ * You can write your logic in the handler and return whatever options
6
+ * are decided.
7
+ */
8
+ import Joi from 'joi';
9
+ import type { [ToolName]ConfigOptions } from '@src/interfaces';
10
+ import type { Request, ServerRoute } from '@hapi/hapi';
11
+
12
+ const route: ServerRoute = {
13
+ method: 'POST',
14
+ path: '/dynamic-schema/exampleDynamicSchema',
15
+ options: {
16
+ validate: {
17
+ payload: Joi.object(),
18
+ },
19
+ },
20
+ handler: function (request: Request): ExampleDynamicSchemeReturnPayload {
21
+ const payload = request.payload as Payload;
22
+ const options = payload.item.options;
23
+
24
+ return {
25
+ enum: ['one', 'two', 'three', 'four'],
26
+ 'Q:options': {
27
+ enum_titles: ['1', '2', '3', '4'],
28
+ },
29
+ };
30
+ },
31
+ };
32
+
33
+ export default route;
34
+
35
+ /**
36
+ * Interfaces.
37
+ */
38
+ interface Payload {
39
+ item: {
40
+ options: [ToolName]ConfigOptions;
41
+ };
42
+ }
43
+
44
+ export interface ExampleDynamicSchemeReturnPayload {
45
+ enum: string[];
46
+ 'Q:options': {
47
+ enum_titles: string[];
48
+ };
49
+ }
@@ -0,0 +1,5 @@
1
+ import exampleDynamicSchema from './exampleDynamicSchema.js';
2
+
3
+ export default [
4
+ exampleDynamicSchema,
5
+ ];
@@ -0,0 +1,14 @@
1
+ import type { ServerRoute } from '@hapi/hapi';
2
+
3
+ const route: ServerRoute = {
4
+ path: '/health',
5
+ method: 'GET',
6
+ options: {
7
+ tags: ['api'],
8
+ },
9
+ handler: () => {
10
+ return 'ok';
11
+ },
12
+ };
13
+
14
+ export default route;
@@ -0,0 +1,31 @@
1
+ import Joi from 'joi';
2
+ import { dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import type { Request, ServerRoute, ResponseToolkit } from '@hapi/hapi';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const localesDir = __dirname + '/../../resources/locales/';
8
+
9
+ const route: ServerRoute = {
10
+ path: '/locales/{lng}/translation.json',
11
+ method: 'GET',
12
+ options: {
13
+ description: 'Returns translations for given language',
14
+ tags: ['api'],
15
+ validate: {
16
+ params: {
17
+ lng: Joi.string().required(),
18
+ },
19
+ },
20
+ },
21
+ handler: (request: Request, h: ResponseToolkit) => {
22
+ const params = request.params as Params;
23
+ return h.file(localesDir + params.lng + '/translation.json').type('application/json');
24
+ },
25
+ };
26
+
27
+ export default route;
28
+
29
+ interface Params {
30
+ lng: string;
31
+ }
@@ -0,0 +1,46 @@
1
+ import Joi from 'joi';
2
+ import type { Request } from '@hapi/hapi';
3
+ import type { [ToolName]ConfigOptions } from '@src/interfaces';
4
+
5
+ export default {
6
+ method: 'POST',
7
+ path: '/notification/exampleNotification',
8
+ options: {
9
+ validate: {
10
+ options: {
11
+ allowUnknown: true,
12
+ },
13
+ payload: Joi.object().required(),
14
+ },
15
+ tags: ['api'],
16
+ },
17
+ handler: function (request: Request) {
18
+ try {
19
+ const payload = request.payload as Payload;
20
+ const item = payload.item;
21
+
22
+ /** Response is fetched from the locales folder. */
23
+ return {
24
+ message: {
25
+ title: 'notifications.exampleNotification.title',
26
+ body: 'notifications.exampleNotification.body',
27
+ },
28
+ };
29
+ } catch (err) {
30
+ console.log('Error processing /notification/exampleNotification', err);
31
+ }
32
+
33
+ return null;
34
+ },
35
+ };
36
+
37
+ /**
38
+ * Payload is defined in the schema.json:
39
+ * showSearch -> notificationChecks -> fields
40
+ */
41
+ interface Payload {
42
+ item: {
43
+ options: [ToolName]ConfigOptions;
44
+ };
45
+ roles: string[];
46
+ }