@zairakai/js-dev-tools 1.0.0

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/.editorconfig +86 -0
  2. package/.gitlab/ci/pipeline-js-app.yml +75 -0
  3. package/.gitlab/ci/pipeline-js-package.yml +360 -0
  4. package/LICENSE +21 -0
  5. package/README.md +206 -0
  6. package/config/.markdownlint.json +7 -0
  7. package/config/.markdownlintignore +5 -0
  8. package/config/.prettierignore +11 -0
  9. package/config/.stylelintignore +7 -0
  10. package/config/eslint.config.js +198 -0
  11. package/config/knip.config.js +40 -0
  12. package/config/prettier.config.js +121 -0
  13. package/config/stylelint.config.js +56 -0
  14. package/config/tsconfig.base.json +20 -0
  15. package/config/vitest.config.js +25 -0
  16. package/index.js +24 -0
  17. package/package.json +148 -0
  18. package/scripts/build.sh +58 -0
  19. package/scripts/ci-quality.sh +51 -0
  20. package/scripts/config.sh +254 -0
  21. package/scripts/doctor.sh +74 -0
  22. package/scripts/eslint-fix.sh +38 -0
  23. package/scripts/eslint.sh +49 -0
  24. package/scripts/install-bats.sh +227 -0
  25. package/scripts/install-hooks.sh +167 -0
  26. package/scripts/install-markdownlint.sh +31 -0
  27. package/scripts/install-shellcheck.sh +232 -0
  28. package/scripts/knip.sh +40 -0
  29. package/scripts/markdownlint-fix.sh +8 -0
  30. package/scripts/markdownlint.sh +84 -0
  31. package/scripts/outdated.sh +70 -0
  32. package/scripts/prettier-fix.sh +52 -0
  33. package/scripts/prettier.sh +53 -0
  34. package/scripts/setup-project.sh +816 -0
  35. package/scripts/stylelint-fix.sh +64 -0
  36. package/scripts/stylelint.sh +66 -0
  37. package/scripts/test.sh +40 -0
  38. package/scripts/typecheck.sh +41 -0
  39. package/scripts/validate-shellcheck.sh +70 -0
  40. package/stubs/githooks/commit-msg +34 -0
  41. package/stubs/githooks/pre-commit +58 -0
  42. package/stubs/githooks/pre-push +57 -0
  43. package/stubs/githooks/prepare-commit-msg +39 -0
  44. package/stubs/gitlab-ci/gitlab-ci.yml.stub +18 -0
  45. package/stubs/gitlab-ci/gitlab-pipeline-js-app.yml.stub +16 -0
  46. package/stubs/governance/CODE_OF_CONDUCT.md.stub +8 -0
  47. package/stubs/governance/CONTRIBUTING.md.stub +39 -0
  48. package/stubs/governance/SECURITY.md.stub +41 -0
  49. package/stubs/quality/eslint.config.js.stub +18 -0
  50. package/stubs/quality/knip.config.js.stub +14 -0
  51. package/stubs/style/prettier.config.js.stub +16 -0
  52. package/stubs/style/stylelint.config.js.stub +17 -0
  53. package/stubs/testing/vitest.config.js.stub +18 -0
  54. package/stubs/typescript/tsconfig.json.stub +10 -0
  55. package/tools/make/bats.mk +49 -0
  56. package/tools/make/code-style.mk +20 -0
  57. package/tools/make/core.mk +56 -0
  58. package/tools/make/help.mk +32 -0
  59. package/tools/make/knip.mk +7 -0
  60. package/tools/make/markdownlint.mk +17 -0
  61. package/tools/make/quality.mk +19 -0
  62. package/tools/make/shellcheck.mk +14 -0
  63. package/tools/make/stylelint.mk +11 -0
  64. package/tools/make/test.mk +19 -0
  65. package/tools/make/typescript.mk +10 -0
  66. package/tools/make/utils.mk +44 -0
  67. package/tools/make/variables.mk +42 -0
  68. package/tools/scripts/git-cleanup.sh +53 -0
  69. package/tools/scripts/git-update.sh +37 -0
package/.editorconfig ADDED
@@ -0,0 +1,86 @@
1
+ # ===============================================
2
+ # EDITORCONFIG
3
+ # Coding standards for consistent formatting
4
+ # ===============================================
5
+
6
+ root = true
7
+
8
+ # ======================
9
+ # ALL FILES
10
+ # ======================
11
+ [*]
12
+ charset = utf-8
13
+ end_of_line = lf
14
+ indent_size = 4
15
+ indent_style = space
16
+ insert_final_newline = true
17
+ trim_trailing_whitespace = true
18
+
19
+ # ======================
20
+ # MARKDOWN FILES
21
+ # ======================
22
+ [markdown]
23
+ indent_style = space
24
+ indent_size = 4
25
+ trim_trailing_whitespace = false
26
+ insert_final_newline = true
27
+ max_line_length = 120
28
+
29
+ [*.md]
30
+ trim_trailing_whitespace = false
31
+
32
+ # ======================
33
+ # SHELL SCRIPTS
34
+ # ======================
35
+ [*.sh]
36
+ end_of_line = lf
37
+
38
+ # ======================
39
+ # YAML FILES
40
+ # ======================
41
+ [*.{yml,yaml}]
42
+ indent_size = 2
43
+
44
+ [docker-compose.yml]
45
+ indent_size = 4
46
+
47
+ # ======================
48
+ # BUILD FILES
49
+ # ======================
50
+ [Makefile]
51
+ indent_style = tab
52
+
53
+ [Dockerfile*]
54
+ indent_size = 4
55
+
56
+ # ======================
57
+ # CONFIGURATION FILES
58
+ # ======================
59
+ [*.{ini,conf}]
60
+ indent_size = 4
61
+
62
+ # ======================
63
+ # FRONTEND FILES
64
+ # ======================
65
+ [*.json]
66
+ indent_size = 2
67
+
68
+ # ======================
69
+ # PHP FILES
70
+ # ======================
71
+ [*.php]
72
+ indent_size = 4
73
+ max_line_length = 120
74
+
75
+ # ======================
76
+ # Test FILES
77
+ # ======================
78
+ [*.feature]
79
+ charset = utf-8
80
+ gherkin_indent_feature_children = true
81
+ gherkin_indent_steps = true
82
+ gherkin_indent_datatable = true
83
+ gherkin_indent_docstring = true
84
+ gherkin_indent_examples_table = true
85
+ gherkin_table_cell_padding_size = 2
86
+ gherkin_table_cell_right_align_numeric_content = true
@@ -0,0 +1,75 @@
1
+ # ================================
2
+ # PIPELINE TEMPLATE — Laravel App JS/Frontend
3
+ # ================================
4
+ # Provides JS/Frontend CI jobs for a Laravel application.
5
+ # Includes pipeline-js-package.yml (all js: jobs) and disables the
6
+ # package-specific stages (build, publish, release) not relevant for apps.
7
+ #
8
+ # PHP jobs come from laravel-dev-tools (pipeline-laravel-app.yml).
9
+ # All js: job names never conflict with php: job names.
10
+ #
11
+ # Fullstack usage (recommended — single include):
12
+ # ─────────────────────────────────────────────────────
13
+ # include:
14
+ # - project: 'zairakai/php-packages/laravel-dev-tools'
15
+ # ref: main
16
+ # file: '.gitlab/ci/pipeline-laravel-fullstack.yml'
17
+ #
18
+ # Standalone usage (JS side only, alongside a custom PHP pipeline):
19
+ # ─────────────────────────────────────────────────────
20
+ # include:
21
+ # - project: 'zairakai/npm-packages/dev-tools'
22
+ # ref: main
23
+ # file: '.gitlab/ci/pipeline-js-app.yml'
24
+ #
25
+ # variables:
26
+ # CACHE_KEY: "my-app-v1"
27
+ # ================================
28
+
29
+ include:
30
+ # All js: jobs come from pipeline-js-package.yml — no duplication.
31
+ - project: "zairakai/npm-packages/dev-tools"
32
+ ref: main
33
+ file: ".gitlab/ci/pipeline-js-package.yml"
34
+
35
+ # ================================
36
+ # STAGES
37
+ # ================================
38
+ # Merges with PHP pipeline stages — GitLab deduplicates identical names.
39
+ # The build/publish/release stages from pipeline-js-package.yml are kept
40
+ # in the merged list but stay empty (jobs below are disabled).
41
+ stages:
42
+ - security
43
+ - install
44
+ - validate
45
+ - quality
46
+ - test
47
+ - deploy
48
+ - metrics
49
+
50
+ # ================================
51
+ # VARIABLES
52
+ # ================================
53
+ variables:
54
+ # Default cache key for app context (overridden per project via CACHE_KEY).
55
+ CACHE_KEY: "zairakai-laravel-app"
56
+
57
+ # Note: GIT_CLEAN_FLAGS intentionally NOT set here.
58
+ # pipeline-laravel-fullstack.yml sets the combined value to preserve
59
+ # both vendor/ and node_modules/.
60
+
61
+ # ================================
62
+ # DISABLE package-specific jobs
63
+ # Not relevant for a Laravel app (no npm publish or GitLab release).
64
+ # ================================
65
+ js:build:
66
+ rules:
67
+ - when: never
68
+
69
+ js:publish:
70
+ rules:
71
+ - when: never
72
+
73
+ js:release:
74
+ rules:
75
+ - when: never
@@ -0,0 +1,360 @@
1
+ # ================================
2
+ # PIPELINE TEMPLATE — NPM Package
3
+ # ================================
4
+ # Shared pipeline template for NPM packages in the Zairakai namespace.
5
+ # Self-contained: anchors and jobs are all in this single file.
6
+ # YAML anchors do not survive cross-file include: — this is a YAML parser
7
+ # limitation, not a GitLab one. Everything is therefore kept here.
8
+ #
9
+ # All job names are prefixed js: to avoid any collision with PHP or custom
10
+ # jobs when this template is combined with other templates.
11
+ # pipeline-js-app.yml (fullstack context) includes this file directly — no duplication.
12
+ #
13
+ # USAGE in a consumer project:
14
+ # ─────────────────────────────────────────
15
+ # include:
16
+ # - project: 'zairakai/npm-packages/dev-tools'
17
+ # ref: main
18
+ # file: '.gitlab/ci/pipeline-js-package.yml'
19
+ #
20
+ # variables:
21
+ # CACHE_KEY: "my-package-v1"
22
+ # NPM_PACKAGE_NAME: "@myorg/my-package"
23
+ #
24
+ # FOR dev-tools ITSELF (self-hosted mode):
25
+ # ─────────────────────────────────────────────────────
26
+ # include:
27
+ # - local: '.gitlab/ci/pipeline-js-package.yml'
28
+ #
29
+ # variables:
30
+ # CACHE_KEY: "dev-tools-v1"
31
+ # NPM_PACKAGE_NAME: "@zairakai/js-dev-tools"
32
+ # DEV_TOOLS_SCRIPTS: "scripts"
33
+ # ================================
34
+
35
+ include:
36
+ - template: Jobs/Secret-Detection.gitlab-ci.yml
37
+
38
+ # ================================
39
+ # WORKFLOW
40
+ # ================================
41
+ workflow:
42
+ rules:
43
+ - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
44
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_MERGE_REQUEST_ID
45
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
46
+ - if: $CI_COMMIT_REF_NAME =~ /^feature\// || $CI_COMMIT_REF_NAME =~ /^fix\// || $CI_COMMIT_REF_NAME =~ /^hotfix\//
47
+ - when: never
48
+
49
+ # ================================
50
+ # STAGES
51
+ # ================================
52
+ stages:
53
+ - security
54
+ - install
55
+ - validate
56
+ - quality
57
+ - test
58
+ - build
59
+ - publish
60
+ - release
61
+
62
+ # ================================
63
+ # DEFAULT VARIABLES
64
+ # ================================
65
+ variables:
66
+ # ── OVERRIDE PER PROJECT ──────────────────────────────────────────────────
67
+ CACHE_KEY: "zairakai-npm-package"
68
+ NPM_PACKAGE_NAME: "@zairakai/package"
69
+
70
+ # Paths to dev-tools scripts.
71
+ # Consumer projects do NOT need to override these.
72
+ # dev-tools itself overrides them in its own .gitlab-ci.yml.
73
+ DEV_TOOLS_SCRIPTS: "node_modules/@zairakai/js-dev-tools/scripts"
74
+
75
+ # ── NODE ──────────────────────────────────────────────────────────────────
76
+ NODE_VERSION: "22"
77
+ NODE_IMAGE: "zairakai/node:latest-dev"
78
+ NODE_TEST_IMAGE: "zairakai/node:latest-test"
79
+ SHELLCHECK_IMAGE: "koalaman/shellcheck-alpine:v0.10.0"
80
+ RELEASE_CLI_IMAGE: "registry.gitlab.com/gitlab-org/release-cli:v0.18.0"
81
+ ALPINE_IMAGE: "alpine:3.18"
82
+
83
+ # ── GIT ───────────────────────────────────────────────────────────────────
84
+ GIT_DEPTH: 1
85
+ GIT_STRATEGY: fetch
86
+ GIT_CLEAN_FLAGS: "-ffdx -e node_modules/ -e .npm/"
87
+
88
+ # ── SECURITY ──────────────────────────────────────────────────────────────
89
+ SECRET_DETECTION_EXCLUDED_PATHS: "node_modules/,dist/,build/,coverage/"
90
+
91
+ # ================================
92
+ # ANCHORS
93
+ # ================================
94
+ .base_job: &base_job
95
+ retry:
96
+ max: 2
97
+ when:
98
+ - runner_system_failure
99
+ - stuck_or_timeout_failure
100
+
101
+ .cache_node: &cache_node
102
+ cache:
103
+ key:
104
+ files:
105
+ - package-lock.json
106
+ prefix: $CACHE_KEY
107
+ paths:
108
+ - node_modules/
109
+ - .npm/
110
+ policy: pull
111
+
112
+ .cache_node_push: &cache_node_push
113
+ cache:
114
+ key:
115
+ files:
116
+ - package-lock.json
117
+ prefix: $CACHE_KEY
118
+ paths:
119
+ - node_modules/
120
+ - .npm/
121
+ policy: pull-push
122
+
123
+ .job_node: &job_node
124
+ <<: [*base_job, *cache_node]
125
+ image: ${NODE_IMAGE}
126
+ before_script:
127
+ - node --version
128
+ - npm --version
129
+
130
+ # ================================
131
+ # SECURITY
132
+ # ================================
133
+ secret_detection:
134
+ stage: security
135
+ rules:
136
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_MERGE_REQUEST_ID
137
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
138
+
139
+ # ================================
140
+ # INSTALL
141
+ # ================================
142
+ js:install:
143
+ <<: [*base_job, *cache_node_push]
144
+ stage: install
145
+ image: ${NODE_IMAGE}
146
+ script:
147
+ - npm ci --cache .npm --prefer-offline
148
+ - |
149
+ if [ -f /lib/ld-musl-x86_64.so.1 ]; then
150
+ npm install --no-save @oxc-resolver/binding-linux-x64-musl @rollup/rollup-linux-x64-musl
151
+ fi
152
+ artifacts:
153
+ paths:
154
+ - node_modules/
155
+ expire_in: 1 hour
156
+
157
+ # ================================
158
+ # VALIDATE
159
+ # ================================
160
+ js:validate:markdownlint:
161
+ <<: [*base_job, *cache_node]
162
+ stage: validate
163
+ image: ${NODE_IMAGE}
164
+ script:
165
+ - bash "$DEV_TOOLS_SCRIPTS/markdownlint.sh"
166
+
167
+ js:validate:shellcheck:
168
+ <<: *base_job
169
+ stage: validate
170
+ image: ${SHELLCHECK_IMAGE}
171
+ before_script:
172
+ - apk add --no-cache bash
173
+ script:
174
+ - |
175
+ if [[ -d scripts/ ]]; then
176
+ bash "$DEV_TOOLS_SCRIPTS/validate-shellcheck.sh"
177
+ else
178
+ echo "No scripts/ directory found — skipping ShellCheck"
179
+ fi
180
+
181
+ # ================================
182
+ # QUALITY
183
+ # ================================
184
+ js:quality:lint:
185
+ <<: *job_node
186
+ stage: quality
187
+ script:
188
+ - bash "$DEV_TOOLS_SCRIPTS/eslint.sh"
189
+ artifacts:
190
+ reports:
191
+ junit: build/reports/eslint.xml
192
+ paths:
193
+ - build/reports/
194
+ expire_in: 1 week
195
+ when: always
196
+
197
+ js:quality:format:
198
+ <<: *job_node
199
+ stage: quality
200
+ script:
201
+ - bash "$DEV_TOOLS_SCRIPTS/prettier.sh"
202
+
203
+ js:quality:stylelint:
204
+ <<: *job_node
205
+ stage: quality
206
+ script:
207
+ - bash "$DEV_TOOLS_SCRIPTS/stylelint.sh"
208
+
209
+ js:quality:typecheck:
210
+ <<: *job_node
211
+ stage: quality
212
+ script:
213
+ - |
214
+ if [ -f tsconfig.json ] && [ -f node_modules/.bin/tsc ]; then
215
+ bash "$DEV_TOOLS_SCRIPTS/typecheck.sh"
216
+ else
217
+ echo "TypeScript not configured — skipping (add tsconfig.json + typescript to devDependencies)"
218
+ fi
219
+
220
+ js:quality:knip:
221
+ <<: *job_node
222
+ stage: quality
223
+ script:
224
+ - bash "$DEV_TOOLS_SCRIPTS/knip.sh"
225
+
226
+ js:quality:bats:
227
+ <<: [*base_job, *cache_node]
228
+ stage: quality
229
+ image: ${ALPINE_IMAGE}
230
+ before_script:
231
+ - apk add --no-cache bash bats
232
+ script:
233
+ - |
234
+ if [[ -d tests/bats ]]; then
235
+ bats tests/bats --recursive
236
+ else
237
+ echo "No BATS tests found — skipping"
238
+ fi
239
+
240
+ js:quality:outdated:
241
+ <<: *job_node
242
+ stage: quality
243
+ script:
244
+ - bash "$DEV_TOOLS_SCRIPTS/outdated.sh"
245
+ artifacts:
246
+ paths:
247
+ - build/reports/npm-outdated.json
248
+ expire_in: 1 week
249
+ when: always
250
+
251
+ # ================================
252
+ # TEST
253
+ # ================================
254
+ js:test:
255
+ <<: [*base_job, *cache_node]
256
+ stage: test
257
+ image: ${NODE_TEST_IMAGE}
258
+ script:
259
+ - CI=true bash "$DEV_TOOLS_SCRIPTS/test.sh"
260
+ coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
261
+ artifacts:
262
+ reports:
263
+ junit: build/coverage/junit.xml
264
+ coverage_report:
265
+ coverage_format: cobertura
266
+ path: build/coverage/cobertura-coverage.xml
267
+ paths:
268
+ - build/coverage/
269
+ expire_in: 1 week
270
+ when: always
271
+
272
+ # ================================
273
+ # BUILD
274
+ # ================================
275
+ js:build:
276
+ <<: *job_node
277
+ stage: build
278
+ script:
279
+ - |
280
+ if { [ -f node_modules/.bin/tsup ] || [ -f node_modules/.bin/tsc ]; } && [ -f tsconfig.json ]; then
281
+ bash "$DEV_TOOLS_SCRIPTS/build.sh"
282
+ else
283
+ echo "No TypeScript builder configured — skipping (install tsup or typescript)"
284
+ fi
285
+ artifacts:
286
+ paths:
287
+ - dist/
288
+ expire_in: 1 week
289
+ when: on_success
290
+ rules:
291
+ - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
292
+ - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"
293
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_MERGE_REQUEST_ID
294
+
295
+ # ================================
296
+ # PUBLISH
297
+ # ================================
298
+ js:publish:
299
+ <<: [*base_job, *cache_node]
300
+ stage: publish
301
+ image: ${NODE_IMAGE}
302
+ rules:
303
+ - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
304
+ script:
305
+ - |
306
+ if [[ -z "${NPM_TOKEN:-}" ]]; then
307
+ echo "ERROR: NPM_TOKEN is not set or empty"
308
+ echo "Go to: GitLab → Settings → CI/CD → Variables → add NPM_TOKEN (type: Variable, protected, masked)"
309
+ exit 1
310
+ fi
311
+ - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > "${CI_PROJECT_DIR}/.npmrc"
312
+ - |
313
+ if [[ $CI_COMMIT_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then
314
+ echo "Publishing ${NPM_PACKAGE_NAME}@${CI_COMMIT_TAG#v} to npm..."
315
+ npm version "${CI_COMMIT_TAG#v}" --no-git-tag-version --allow-same-version
316
+ npm publish --access public
317
+ else
318
+ echo "Invalid tag format: ${CI_COMMIT_TAG}. Expected: v1.0.0"
319
+ exit 1
320
+ fi
321
+ environment:
322
+ name: production
323
+ url: https://www.npmjs.com/package/${NPM_PACKAGE_NAME}
324
+
325
+ # ================================
326
+ # RELEASE
327
+ # ================================
328
+ js:release:
329
+ <<: *base_job
330
+ stage: release
331
+ image: ${RELEASE_CLI_IMAGE}
332
+ rules:
333
+ - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
334
+ before_script:
335
+ - apk add --no-cache bash git jq
336
+ - git config --global --add safe.directory '*'
337
+ - git config --global user.name "GitLab CI"
338
+ - git config --global user.email "ci@gitlab.com"
339
+ script:
340
+ - |
341
+ PREVIOUS_TAG=$(git tag --sort=-version:refname | head -n 2 | tail -n 1 || echo "")
342
+ if [[ -n "$PREVIOUS_TAG" && "$PREVIOUS_TAG" != "$CI_COMMIT_TAG" ]]; then
343
+ COMMITS=$(git log --pretty=format:"- %s" "${PREVIOUS_TAG}..${CI_COMMIT_TAG}" | head -20)
344
+ else
345
+ COMMITS="- Initial release"
346
+ fi
347
+ cat > release_notes.md << NOTES
348
+ ## ${CI_COMMIT_TAG}
349
+
350
+ ${COMMITS}
351
+ NOTES
352
+ release-cli create \
353
+ --tag-name "${CI_COMMIT_TAG}" \
354
+ --name "Release ${CI_COMMIT_TAG}" \
355
+ --description "$(cat release_notes.md)" \
356
+ --assets-link "{\"name\":\"npm\",\"url\":\"https://www.npmjs.com/package/${NPM_PACKAGE_NAME}/v/${CI_COMMIT_TAG#v}\"}"
357
+ artifacts:
358
+ paths:
359
+ - release_notes.md
360
+ expire_in: 1 year
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Stanislas Poisson (Zairakai)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.