@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.
- package/.editorconfig +86 -0
- package/.gitlab/ci/pipeline-js-app.yml +75 -0
- package/.gitlab/ci/pipeline-js-package.yml +360 -0
- package/LICENSE +21 -0
- package/README.md +206 -0
- package/config/.markdownlint.json +7 -0
- package/config/.markdownlintignore +5 -0
- package/config/.prettierignore +11 -0
- package/config/.stylelintignore +7 -0
- package/config/eslint.config.js +198 -0
- package/config/knip.config.js +40 -0
- package/config/prettier.config.js +121 -0
- package/config/stylelint.config.js +56 -0
- package/config/tsconfig.base.json +20 -0
- package/config/vitest.config.js +25 -0
- package/index.js +24 -0
- package/package.json +148 -0
- package/scripts/build.sh +58 -0
- package/scripts/ci-quality.sh +51 -0
- package/scripts/config.sh +254 -0
- package/scripts/doctor.sh +74 -0
- package/scripts/eslint-fix.sh +38 -0
- package/scripts/eslint.sh +49 -0
- package/scripts/install-bats.sh +227 -0
- package/scripts/install-hooks.sh +167 -0
- package/scripts/install-markdownlint.sh +31 -0
- package/scripts/install-shellcheck.sh +232 -0
- package/scripts/knip.sh +40 -0
- package/scripts/markdownlint-fix.sh +8 -0
- package/scripts/markdownlint.sh +84 -0
- package/scripts/outdated.sh +70 -0
- package/scripts/prettier-fix.sh +52 -0
- package/scripts/prettier.sh +53 -0
- package/scripts/setup-project.sh +816 -0
- package/scripts/stylelint-fix.sh +64 -0
- package/scripts/stylelint.sh +66 -0
- package/scripts/test.sh +40 -0
- package/scripts/typecheck.sh +41 -0
- package/scripts/validate-shellcheck.sh +70 -0
- package/stubs/githooks/commit-msg +34 -0
- package/stubs/githooks/pre-commit +58 -0
- package/stubs/githooks/pre-push +57 -0
- package/stubs/githooks/prepare-commit-msg +39 -0
- package/stubs/gitlab-ci/gitlab-ci.yml.stub +18 -0
- package/stubs/gitlab-ci/gitlab-pipeline-js-app.yml.stub +16 -0
- package/stubs/governance/CODE_OF_CONDUCT.md.stub +8 -0
- package/stubs/governance/CONTRIBUTING.md.stub +39 -0
- package/stubs/governance/SECURITY.md.stub +41 -0
- package/stubs/quality/eslint.config.js.stub +18 -0
- package/stubs/quality/knip.config.js.stub +14 -0
- package/stubs/style/prettier.config.js.stub +16 -0
- package/stubs/style/stylelint.config.js.stub +17 -0
- package/stubs/testing/vitest.config.js.stub +18 -0
- package/stubs/typescript/tsconfig.json.stub +10 -0
- package/tools/make/bats.mk +49 -0
- package/tools/make/code-style.mk +20 -0
- package/tools/make/core.mk +56 -0
- package/tools/make/help.mk +32 -0
- package/tools/make/knip.mk +7 -0
- package/tools/make/markdownlint.mk +17 -0
- package/tools/make/quality.mk +19 -0
- package/tools/make/shellcheck.mk +14 -0
- package/tools/make/stylelint.mk +11 -0
- package/tools/make/test.mk +19 -0
- package/tools/make/typescript.mk +10 -0
- package/tools/make/utils.mk +44 -0
- package/tools/make/variables.mk +42 -0
- package/tools/scripts/git-cleanup.sh +53 -0
- package/tools/scripts/git-update.sh +37 -0
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Zairakai NPM Dev Tools - Project Setup Script
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash setup-project.sh # Normal setup (Makefile + .editorconfig + eslint baseline)
|
|
7
|
+
# bash setup-project.sh --publish # Publish all configs to config/dev-tools/
|
|
8
|
+
# bash setup-project.sh --publish=quality # Publish quality group (eslint)
|
|
9
|
+
# bash setup-project.sh --publish=style # Publish style group (prettier, stylelint, ignore files)
|
|
10
|
+
# bash setup-project.sh --publish=testing # Publish vitest config
|
|
11
|
+
# bash setup-project.sh --publish=gitlab-ci # Publish GitLab CI (auto-detects project type)
|
|
12
|
+
# bash setup-project.sh --publish=eslint # Publish specific config
|
|
13
|
+
# bash setup-project.sh --with-makefile # Also generate/inject Makefile
|
|
14
|
+
# bash setup-project.sh --force # Force overwrite existing files
|
|
15
|
+
# bash setup-project.sh --silent # Suppress output (errors only)
|
|
16
|
+
# bash setup-project.sh --help # Show this help
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
# shellcheck disable=SC1091
|
|
23
|
+
source "${SCRIPT_DIR}/config.sh"
|
|
24
|
+
|
|
25
|
+
# ============================================================================
|
|
26
|
+
# CI Mode Detection — delegates to IS_CI exported by config.sh
|
|
27
|
+
# ============================================================================
|
|
28
|
+
CI_MODE="$IS_CI"
|
|
29
|
+
|
|
30
|
+
# ============================================================================
|
|
31
|
+
# Publishable configs registry
|
|
32
|
+
# Format: [key]="source_relative_to_dev_tools|target_relative_to_project|group"
|
|
33
|
+
# Note: gitlab-ci has a special handler (auto-detects project type) — not in this registry.
|
|
34
|
+
# ============================================================================
|
|
35
|
+
|
|
36
|
+
declare -A PUBLISHABLE=(
|
|
37
|
+
["eslint"]="stubs/quality/eslint.config.js.stub|config/dev-tools/eslint.config.js|quality"
|
|
38
|
+
["knip"]="stubs/quality/knip.config.js.stub|config/dev-tools/knip.config.js|quality"
|
|
39
|
+
["prettier"]="stubs/style/prettier.config.js.stub|config/dev-tools/prettier.config.js|style"
|
|
40
|
+
["stylelint"]="stubs/style/stylelint.config.js.stub|config/dev-tools/stylelint.config.js|style"
|
|
41
|
+
["prettierignore"]="config/.prettierignore|config/dev-tools/.prettierignore|style"
|
|
42
|
+
["stylelintignore"]="config/.stylelintignore|config/dev-tools/.stylelintignore|style"
|
|
43
|
+
["markdownlint"]="config/.markdownlint.json|config/dev-tools/.markdownlint.json|style"
|
|
44
|
+
["markdownlintignore"]="config/.markdownlintignore|config/dev-tools/.markdownlintignore|style"
|
|
45
|
+
["vitest"]="stubs/testing/vitest.config.js.stub|config/dev-tools/vitest.config.js|testing"
|
|
46
|
+
["tsconfig"]="stubs/typescript/tsconfig.json.stub|tsconfig.json|typescript"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
declare -A PUBLISH_GROUPS=(
|
|
50
|
+
["quality"]="eslint knip"
|
|
51
|
+
["style"]="prettier stylelint prettierignore stylelintignore markdownlint markdownlintignore"
|
|
52
|
+
["testing"]="vitest"
|
|
53
|
+
["typescript"]="tsconfig"
|
|
54
|
+
["hooks"]="hooks"
|
|
55
|
+
["governance"]="governance"
|
|
56
|
+
["all"]="eslint knip prettier stylelint prettierignore stylelintignore markdownlint markdownlintignore vitest tsconfig hooks"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# ============================================================================
|
|
60
|
+
# Argument Parsing
|
|
61
|
+
# ============================================================================
|
|
62
|
+
|
|
63
|
+
FORCE_OVERWRITE=false
|
|
64
|
+
SILENT_MODE=false
|
|
65
|
+
PUBLISH_TARGET=""
|
|
66
|
+
WITH_MAKEFILE=false
|
|
67
|
+
|
|
68
|
+
for arg in "$@"; do
|
|
69
|
+
case "$arg" in
|
|
70
|
+
--force|-f) FORCE_OVERWRITE=true ;;
|
|
71
|
+
--silent|-s) SILENT_MODE=true ;;
|
|
72
|
+
--with-makefile) WITH_MAKEFILE=true ;;
|
|
73
|
+
--publish) PUBLISH_TARGET="all" ;;
|
|
74
|
+
--publish=*) PUBLISH_TARGET="${arg#--publish=}" ;;
|
|
75
|
+
--help|-h)
|
|
76
|
+
echo ""
|
|
77
|
+
echo "Usage: bash setup-project.sh [options]"
|
|
78
|
+
echo ""
|
|
79
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
80
|
+
echo " Options"
|
|
81
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
82
|
+
echo " (no options) Normal setup (Makefile + .editorconfig + eslint baseline)"
|
|
83
|
+
echo " --publish Publish ALL configs to config/dev-tools/"
|
|
84
|
+
echo " --publish=<group> Publish a config group"
|
|
85
|
+
echo " --publish=<key> Publish a specific config"
|
|
86
|
+
echo " --with-makefile Generate or inject Makefile"
|
|
87
|
+
echo " --force, -f Overwrite existing files"
|
|
88
|
+
echo " --silent, -s Suppress output (for postinstall)"
|
|
89
|
+
echo " --help, -h Show this help"
|
|
90
|
+
echo ""
|
|
91
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
92
|
+
echo " Groups (--publish=<group>)"
|
|
93
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
94
|
+
echo " quality eslint"
|
|
95
|
+
echo " style prettier, stylelint, markdownlint, .prettierignore, .stylelintignore, .markdownlintignore"
|
|
96
|
+
echo " testing vitest"
|
|
97
|
+
echo " typescript tsconfig"
|
|
98
|
+
echo " all all configs (except gitlab-ci)"
|
|
99
|
+
echo ""
|
|
100
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
101
|
+
echo " Specific configs (--publish=<key>)"
|
|
102
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
103
|
+
echo " eslint → config/dev-tools/eslint.config.js"
|
|
104
|
+
echo " prettier → config/dev-tools/prettier.config.js"
|
|
105
|
+
echo " stylelint → config/dev-tools/stylelint.config.js"
|
|
106
|
+
echo " prettierignore → config/dev-tools/.prettierignore"
|
|
107
|
+
echo " stylelintignore → config/dev-tools/.stylelintignore"
|
|
108
|
+
echo " markdownlint → config/dev-tools/.markdownlint.json"
|
|
109
|
+
echo " markdownlintignore → config/dev-tools/.markdownlintignore"
|
|
110
|
+
echo " vitest → config/dev-tools/vitest.config.js"
|
|
111
|
+
echo " tsconfig → tsconfig.json (extends bundled base)"
|
|
112
|
+
echo " gitlab-ci → auto-detect: .gitlab-ci.yml or .gitlab/pipeline-js-app.yml"
|
|
113
|
+
echo " governance → SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md"
|
|
114
|
+
echo ""
|
|
115
|
+
exit 0
|
|
116
|
+
;;
|
|
117
|
+
*)
|
|
118
|
+
echo "ERROR: Unknown option: $arg" >&2
|
|
119
|
+
echo "Use --help for usage information" >&2
|
|
120
|
+
exit 1
|
|
121
|
+
;;
|
|
122
|
+
esac
|
|
123
|
+
done
|
|
124
|
+
|
|
125
|
+
# ============================================================================
|
|
126
|
+
# Silent Mode Override
|
|
127
|
+
# ============================================================================
|
|
128
|
+
|
|
129
|
+
if [[ "$SILENT_MODE" == "true" ]]; then
|
|
130
|
+
log_header() { :; }
|
|
131
|
+
log_step() { :; }
|
|
132
|
+
log_info() { :; }
|
|
133
|
+
log_success() { :; }
|
|
134
|
+
log_warning() { :; }
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# ============================================================================
|
|
138
|
+
# Optional Dependencies Check
|
|
139
|
+
# Runs after setup — shows informative messages even in silent mode (postinstall)
|
|
140
|
+
# ============================================================================
|
|
141
|
+
|
|
142
|
+
check_optional_deps() {
|
|
143
|
+
local -a missing=()
|
|
144
|
+
|
|
145
|
+
# zod — runtime type validation (validates API responses / form inputs at runtime)
|
|
146
|
+
[[ ! -d "${PROJECT_ROOT}/node_modules/zod" ]] \
|
|
147
|
+
&& missing+=("zod|Runtime type validation for JS/Vue (validates API responses, forms)|${PM} install zod")
|
|
148
|
+
|
|
149
|
+
# typescript — enables make typecheck and make build
|
|
150
|
+
[[ ! -d "${PROJECT_ROOT}/node_modules/typescript" ]] \
|
|
151
|
+
&& missing+=("typescript|TypeScript compiler — enables make typecheck + make build|${PM} install --save-dev typescript")
|
|
152
|
+
|
|
153
|
+
# tsup — fast TS bundler (recommended for npm packages to publish)
|
|
154
|
+
[[ ! -d "${PROJECT_ROOT}/node_modules/tsup" ]] \
|
|
155
|
+
&& missing+=("tsup|Fast TypeScript bundler for npm packages (esbuild-based)|${PM} install --save-dev tsup")
|
|
156
|
+
|
|
157
|
+
# knip — unused exports, files and dependencies detector
|
|
158
|
+
[[ ! -d "${PROJECT_ROOT}/node_modules/knip" ]] \
|
|
159
|
+
&& missing+=("knip|Unused exports and dependencies detector (make knip)|${PM} install --save-dev knip")
|
|
160
|
+
|
|
161
|
+
[[ ${#missing[@]} -eq 0 ]] && return 0
|
|
162
|
+
|
|
163
|
+
if [[ "$SILENT_MODE" == "true" ]]; then
|
|
164
|
+
echo ""
|
|
165
|
+
echo " ┌─ @zairakai/js-dev-tools — optional packages not installed ─┐"
|
|
166
|
+
for entry in "${missing[@]}"; do
|
|
167
|
+
local pkg="${entry%%|*}"
|
|
168
|
+
local rest="${entry#*|}"
|
|
169
|
+
local install_cmd="${rest#*|}"
|
|
170
|
+
printf " │ %-12s %s\n" "${pkg}" "${install_cmd}"
|
|
171
|
+
done
|
|
172
|
+
echo " └─ Run: bash setup-project.sh (without --silent) for details ┘"
|
|
173
|
+
echo ""
|
|
174
|
+
return 0
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
echo ""
|
|
178
|
+
echo -e "${YELLOW}┌──────────────────────────────────────────────────────┐${NC}"
|
|
179
|
+
echo -e "${YELLOW}│${NC} ${YELLOW}Recommended Optional Packages${NC} ${YELLOW}│${NC}"
|
|
180
|
+
echo -e "${YELLOW}├──────────────────────────────────────────────────────┤${NC}"
|
|
181
|
+
for entry in "${missing[@]}"; do
|
|
182
|
+
local pkg="${entry%%|*}"
|
|
183
|
+
local rest="${entry#*|}"
|
|
184
|
+
local reason="${rest%%|*}"
|
|
185
|
+
local install_cmd="${rest#*|}"
|
|
186
|
+
echo -e "${YELLOW}│${NC} ${CYAN}${pkg}${NC}"
|
|
187
|
+
echo -e "${YELLOW}│${NC} ${reason}"
|
|
188
|
+
echo -e "${YELLOW}│${NC} ${GREEN}${install_cmd}${NC}"
|
|
189
|
+
echo -e "${YELLOW}│${NC}"
|
|
190
|
+
done
|
|
191
|
+
echo -e "${YELLOW}└──────────────────────────────────────────────────────┘${NC}"
|
|
192
|
+
echo ""
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
# ============================================================================
|
|
196
|
+
# Result Tracking
|
|
197
|
+
# ============================================================================
|
|
198
|
+
|
|
199
|
+
declare -a CREATED_FILES=()
|
|
200
|
+
declare -a SKIPPED_FILES=()
|
|
201
|
+
declare -a BACKED_UP_FILES=()
|
|
202
|
+
declare -a PUBLISHED_FILES=()
|
|
203
|
+
|
|
204
|
+
track_created() { CREATED_FILES+=("$1"); }
|
|
205
|
+
track_skipped() { SKIPPED_FILES+=("$1"); }
|
|
206
|
+
track_backed_up() { BACKED_UP_FILES+=("$1"); }
|
|
207
|
+
track_published() { PUBLISHED_FILES+=("$1"); }
|
|
208
|
+
|
|
209
|
+
# ============================================================================
|
|
210
|
+
# File Helpers
|
|
211
|
+
# ============================================================================
|
|
212
|
+
|
|
213
|
+
# Publish a config to config/dev-tools/ (user-facing, hash-protected)
|
|
214
|
+
publish_file() {
|
|
215
|
+
local source="$1"
|
|
216
|
+
local target="$2"
|
|
217
|
+
local name="$3"
|
|
218
|
+
|
|
219
|
+
if [[ ! -f "$source" ]]; then
|
|
220
|
+
log_warning "Source not found for ${name}: ${source#"$DEV_TOOLS_ROOT"/}"
|
|
221
|
+
return 0
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" != "true" ]]; then
|
|
225
|
+
local src_hash tgt_hash
|
|
226
|
+
src_hash="$(file_hash "$source")"
|
|
227
|
+
tgt_hash="$(file_hash "$target")"
|
|
228
|
+
|
|
229
|
+
if [[ -n "$src_hash" ]] && [[ "$src_hash" == "$tgt_hash" ]]; then
|
|
230
|
+
cp "$source" "$target"
|
|
231
|
+
track_published "${name} → ${target#"$PROJECT_ROOT"/} (refreshed)"
|
|
232
|
+
else
|
|
233
|
+
track_skipped "$name"
|
|
234
|
+
log_info "Skipping modified: ${name} (use --force to overwrite)"
|
|
235
|
+
fi
|
|
236
|
+
return 0
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" == "true" ]]; then
|
|
240
|
+
if backup_file "$target" 2>/dev/null; then
|
|
241
|
+
track_backed_up "$name"
|
|
242
|
+
fi
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
mkdir -p "$(dirname "$target")"
|
|
246
|
+
cp "$source" "$target"
|
|
247
|
+
track_published "${name} → ${target#"$PROJECT_ROOT"/}"
|
|
248
|
+
log_success "Published: ${name} → ${target#"$PROJECT_ROOT"/}"
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
# Copy file for standard setup (skips if exists unless --force or CI)
|
|
252
|
+
setup_file() {
|
|
253
|
+
local source="$1"
|
|
254
|
+
local target="$2"
|
|
255
|
+
local name="$3"
|
|
256
|
+
|
|
257
|
+
if [[ "$CI_MODE" == "true" ]] || [[ "$FORCE_OVERWRITE" == "true" ]]; then
|
|
258
|
+
if [[ -f "$target" ]] && [[ ! -L "$target" ]] && [[ "$CI_MODE" != "true" ]]; then
|
|
259
|
+
if backup_file "$target" 2>/dev/null; then
|
|
260
|
+
track_backed_up "$name"
|
|
261
|
+
fi
|
|
262
|
+
fi
|
|
263
|
+
rm -f "$target" 2>/dev/null || true
|
|
264
|
+
mkdir -p "$(dirname "$target")"
|
|
265
|
+
if cp "$source" "$target" 2>/dev/null; then
|
|
266
|
+
track_created "$name"
|
|
267
|
+
log_success "Created: $name"
|
|
268
|
+
fi
|
|
269
|
+
else
|
|
270
|
+
if [[ -f "$target" ]] || [[ -L "$target" ]]; then
|
|
271
|
+
track_skipped "$name"
|
|
272
|
+
return 0
|
|
273
|
+
fi
|
|
274
|
+
mkdir -p "$(dirname "$target")"
|
|
275
|
+
if cp "$source" "$target" 2>/dev/null; then
|
|
276
|
+
track_created "$name"
|
|
277
|
+
log_success "Created: $name"
|
|
278
|
+
fi
|
|
279
|
+
fi
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
# ============================================================================
|
|
283
|
+
# Governance Files Publisher
|
|
284
|
+
# Publishes SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md to project root.
|
|
285
|
+
# Replaces PACKAGE_GITLAB_ISSUES with the actual GitLab issues URL.
|
|
286
|
+
# Hash-protected: skips files modified by the user (use --force to overwrite).
|
|
287
|
+
# Not included in "all" — requires explicit opt-in (--publish=governance).
|
|
288
|
+
# ============================================================================
|
|
289
|
+
|
|
290
|
+
publish_governance_file() {
|
|
291
|
+
local source="$1"
|
|
292
|
+
local target="$2"
|
|
293
|
+
local name="$3"
|
|
294
|
+
local issues_url="$4"
|
|
295
|
+
|
|
296
|
+
if [[ ! -f "$source" ]]; then
|
|
297
|
+
log_warning "Stub not found: stubs/governance/${name}"
|
|
298
|
+
return 0
|
|
299
|
+
fi
|
|
300
|
+
|
|
301
|
+
# Process placeholders into a temp file for hash comparison and copy
|
|
302
|
+
local processed
|
|
303
|
+
processed="$(mktemp)"
|
|
304
|
+
sed "s|PACKAGE_GITLAB_ISSUES|${issues_url}|g" "$source" > "$processed"
|
|
305
|
+
|
|
306
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" != "true" ]]; then
|
|
307
|
+
local src_hash tgt_hash
|
|
308
|
+
src_hash="$(file_hash "$processed")"
|
|
309
|
+
tgt_hash="$(file_hash "$target")"
|
|
310
|
+
|
|
311
|
+
if [[ -n "$src_hash" ]] && [[ "$src_hash" == "$tgt_hash" ]]; then
|
|
312
|
+
cp "$processed" "$target"
|
|
313
|
+
track_published "${name} (refreshed)"
|
|
314
|
+
else
|
|
315
|
+
track_skipped "$name"
|
|
316
|
+
log_info "Skipping modified: ${name} (use --force to overwrite)"
|
|
317
|
+
fi
|
|
318
|
+
rm -f "$processed"
|
|
319
|
+
return 0
|
|
320
|
+
fi
|
|
321
|
+
|
|
322
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" == "true" ]]; then
|
|
323
|
+
backup_file "$target" 2>/dev/null || true
|
|
324
|
+
track_backed_up "$name"
|
|
325
|
+
fi
|
|
326
|
+
|
|
327
|
+
cp "$processed" "$target"
|
|
328
|
+
rm -f "$processed"
|
|
329
|
+
track_published "$name"
|
|
330
|
+
log_success "Published: ${name}"
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
publish_governance_files() {
|
|
334
|
+
local pkg_name
|
|
335
|
+
pkg_name="$(node -e "try{const p=require('${PROJECT_ROOT}/package.json');console.log(p.name||'')}catch(e){}" 2>/dev/null || echo "")"
|
|
336
|
+
|
|
337
|
+
local pkg_short="${pkg_name##*/}" # strip scope: @zairakai/js-dev-tools → dev-tools
|
|
338
|
+
local issues_url="https://gitlab.com/zairakai/npm-packages/${pkg_short}/-/issues"
|
|
339
|
+
|
|
340
|
+
local -a docs=("SECURITY.md" "CONTRIBUTING.md" "CODE_OF_CONDUCT.md")
|
|
341
|
+
|
|
342
|
+
for filename in "${docs[@]}"; do
|
|
343
|
+
publish_governance_file \
|
|
344
|
+
"${DEV_TOOLS_ROOT}/stubs/governance/${filename}.stub" \
|
|
345
|
+
"${PROJECT_ROOT}/${filename}" \
|
|
346
|
+
"$filename" \
|
|
347
|
+
"$issues_url"
|
|
348
|
+
done
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
# ============================================================================
|
|
352
|
+
# GitLab CI — Placeholder Replacement Helper
|
|
353
|
+
# ============================================================================
|
|
354
|
+
|
|
355
|
+
# Extract package name and derive cache key from package.json
|
|
356
|
+
get_package_info() {
|
|
357
|
+
local pkg_name pkg_cache_key
|
|
358
|
+
|
|
359
|
+
pkg_name="$(node -e "try{const p=require('${PROJECT_ROOT}/package.json');console.log(p.name||'')}catch(e){}" 2>/dev/null || echo "")"
|
|
360
|
+
pkg_cache_key="${pkg_name##*/}" # strip scope: @org/my-pkg → my-pkg
|
|
361
|
+
pkg_cache_key="${pkg_cache_key}-v1"
|
|
362
|
+
|
|
363
|
+
echo "${pkg_name}|${pkg_cache_key}"
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
# Replace placeholders in a published GitLab CI file
|
|
367
|
+
replace_gitlab_ci_placeholders() {
|
|
368
|
+
local target="$1"
|
|
369
|
+
local pkg_info
|
|
370
|
+
pkg_info="$(get_package_info)"
|
|
371
|
+
|
|
372
|
+
local pkg_name="${pkg_info%%|*}"
|
|
373
|
+
local pkg_cache_key="${pkg_info#*|}"
|
|
374
|
+
|
|
375
|
+
# Get current version of @zairakai/js-dev-tools
|
|
376
|
+
local dev_tools_version
|
|
377
|
+
dev_tools_version="$(node -e "try{const p=require('${DEV_TOOLS_ROOT}/package.json');console.log(p.version||'0.0.0')}catch(e){}" 2>/dev/null || echo "0.0.0")"
|
|
378
|
+
|
|
379
|
+
if [[ -n "$pkg_name" ]]; then
|
|
380
|
+
sed -i "s|PACKAGE_NPM_NAME|${pkg_name}|g" "$target"
|
|
381
|
+
sed -i "s|PACKAGE_CACHE_KEY|${pkg_cache_key}|g" "$target"
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
if [[ -n "$dev_tools_version" ]]; then
|
|
385
|
+
sed -i "s|v0.0.0|v${dev_tools_version}|g" "$target"
|
|
386
|
+
fi
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
# ============================================================================
|
|
390
|
+
# GitLab CI — NPM Package (.gitlab-ci.yml)
|
|
391
|
+
# ============================================================================
|
|
392
|
+
|
|
393
|
+
publish_gitlab_ci_npm() {
|
|
394
|
+
local source="${DEV_TOOLS_ROOT}/stubs/gitlab-ci/gitlab-ci.yml.stub"
|
|
395
|
+
local target="${PROJECT_ROOT}/.gitlab-ci.yml"
|
|
396
|
+
local name="gitlab-ci"
|
|
397
|
+
|
|
398
|
+
if [[ ! -f "$source" ]]; then
|
|
399
|
+
log_warning "Stub not found: stubs/gitlab-ci/gitlab-ci.yml.stub"
|
|
400
|
+
return 0
|
|
401
|
+
fi
|
|
402
|
+
|
|
403
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" != "true" ]]; then
|
|
404
|
+
track_skipped "$name"
|
|
405
|
+
log_info "Already exists: .gitlab-ci.yml (use --force to overwrite)"
|
|
406
|
+
return 0
|
|
407
|
+
fi
|
|
408
|
+
|
|
409
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" == "true" ]]; then
|
|
410
|
+
if backup_file "$target" 2>/dev/null; then
|
|
411
|
+
track_backed_up ".gitlab-ci.yml"
|
|
412
|
+
fi
|
|
413
|
+
fi
|
|
414
|
+
|
|
415
|
+
cp "$source" "$target"
|
|
416
|
+
replace_gitlab_ci_placeholders "$target"
|
|
417
|
+
|
|
418
|
+
track_published ".gitlab-ci.yml"
|
|
419
|
+
log_success "Published: .gitlab-ci.yml"
|
|
420
|
+
log_info "ref: v0.0.0 will be updated automatically on: ${PM} update @zairakai/js-dev-tools"
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
# ============================================================================
|
|
424
|
+
# GitLab CI — Laravel App (.gitlab/pipeline-js-app.yml + inject .gitlab-ci.yml)
|
|
425
|
+
# ============================================================================
|
|
426
|
+
|
|
427
|
+
# Publish .gitlab/pipeline-js-app.yml (the JS pipeline fragment)
|
|
428
|
+
publish_gitlab_pipeline_js() {
|
|
429
|
+
local source="${DEV_TOOLS_ROOT}/stubs/gitlab-ci/gitlab-pipeline-js-app.yml.stub"
|
|
430
|
+
local target="${PROJECT_ROOT}/.gitlab/pipeline-js-app.yml"
|
|
431
|
+
local name="gitlab/pipeline-js-app.yml"
|
|
432
|
+
|
|
433
|
+
if [[ ! -f "$source" ]]; then
|
|
434
|
+
log_warning "Stub not found: stubs/gitlab-ci/gitlab-pipeline-js-app.yml.stub"
|
|
435
|
+
return 0
|
|
436
|
+
fi
|
|
437
|
+
|
|
438
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" != "true" ]]; then
|
|
439
|
+
track_skipped "$name"
|
|
440
|
+
log_info "Already exists: .gitlab/pipeline-js-app.yml (use --force to overwrite)"
|
|
441
|
+
return 0
|
|
442
|
+
fi
|
|
443
|
+
|
|
444
|
+
if [[ -f "$target" ]] && [[ "$FORCE_OVERWRITE" == "true" ]]; then
|
|
445
|
+
if backup_file "$target" 2>/dev/null; then
|
|
446
|
+
track_backed_up ".gitlab/pipeline-js-app.yml"
|
|
447
|
+
fi
|
|
448
|
+
fi
|
|
449
|
+
|
|
450
|
+
mkdir -p "${PROJECT_ROOT}/.gitlab"
|
|
451
|
+
cp "$source" "$target"
|
|
452
|
+
replace_gitlab_ci_placeholders "$target"
|
|
453
|
+
|
|
454
|
+
track_published ".gitlab/pipeline-js-app.yml"
|
|
455
|
+
log_success "Published: .gitlab/pipeline-js-app.yml"
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
# Inject the local pipeline-js-app.yml include into .gitlab-ci.yml (or create it)
|
|
459
|
+
inject_or_create_gitlab_ci() {
|
|
460
|
+
local target="${PROJECT_ROOT}/.gitlab-ci.yml"
|
|
461
|
+
local marker="# @zairakai/js-dev-tools — JS"
|
|
462
|
+
|
|
463
|
+
if [[ ! -f "$target" ]]; then
|
|
464
|
+
# No .gitlab-ci.yml yet — create a minimal one
|
|
465
|
+
cat > "$target" << 'GITLAB_EOF'
|
|
466
|
+
# .gitlab-ci.yml
|
|
467
|
+
# Generated by @zairakai/js-dev-tools setup-project.sh
|
|
468
|
+
# To regenerate:
|
|
469
|
+
# bash node_modules/@zairakai/js-dev-tools/scripts/setup-project.sh --publish=gitlab-ci --force
|
|
470
|
+
|
|
471
|
+
include:
|
|
472
|
+
# JavaScript/frontend pipeline:
|
|
473
|
+
- local: '.gitlab/pipeline-js-app.yml'
|
|
474
|
+
|
|
475
|
+
# @zairakai/js-dev-tools — JS ────────────────────────────────────────────────────
|
|
476
|
+
GITLAB_EOF
|
|
477
|
+
track_created ".gitlab-ci.yml"
|
|
478
|
+
log_success "Created: .gitlab-ci.yml (includes .gitlab/pipeline-js-app.yml)"
|
|
479
|
+
return 0
|
|
480
|
+
fi
|
|
481
|
+
|
|
482
|
+
# .gitlab-ci.yml exists — check if already injected
|
|
483
|
+
if grep -qF "$marker" "$target" 2>/dev/null; then
|
|
484
|
+
log_info ".gitlab-ci.yml already includes pipeline-js-app.yml — skipping"
|
|
485
|
+
track_skipped ".gitlab-ci.yml (already injected)"
|
|
486
|
+
return 0
|
|
487
|
+
fi
|
|
488
|
+
|
|
489
|
+
log_info "Existing .gitlab-ci.yml detected — injecting pipeline-js-app.yml include"
|
|
490
|
+
|
|
491
|
+
if [[ "$FORCE_OVERWRITE" == "true" ]]; then
|
|
492
|
+
if backup_file "$target" 2>/dev/null; then
|
|
493
|
+
track_backed_up ".gitlab-ci.yml"
|
|
494
|
+
fi
|
|
495
|
+
fi
|
|
496
|
+
|
|
497
|
+
cat >> "$target" << 'INJECT_EOF'
|
|
498
|
+
|
|
499
|
+
# @zairakai/js-dev-tools — JS ────────────────────────────────────────────────────
|
|
500
|
+
# Injected by: bash node_modules/@zairakai/js-dev-tools/scripts/setup-project.sh --publish=gitlab-ci
|
|
501
|
+
# Adds JavaScript quality and test jobs.
|
|
502
|
+
include:
|
|
503
|
+
- local: '.gitlab/pipeline-js-app.yml'
|
|
504
|
+
INJECT_EOF
|
|
505
|
+
|
|
506
|
+
track_created ".gitlab-ci.yml (injected)"
|
|
507
|
+
log_success "Injected pipeline-js-app.yml include into .gitlab-ci.yml"
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
publish_gitlab_ci_laravel() {
|
|
511
|
+
publish_gitlab_pipeline_js
|
|
512
|
+
inject_or_create_gitlab_ci
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
# ============================================================================
|
|
516
|
+
# Git Hooks — Install into .git/hooks
|
|
517
|
+
# ============================================================================
|
|
518
|
+
|
|
519
|
+
publish_hooks() {
|
|
520
|
+
local installer="${DEV_TOOLS_ROOT}/scripts/install-hooks.sh"
|
|
521
|
+
|
|
522
|
+
if [[ ! -f "$installer" ]]; then
|
|
523
|
+
log_warning "Hooks installer not found: scripts/install-hooks.sh"
|
|
524
|
+
return 0
|
|
525
|
+
fi
|
|
526
|
+
|
|
527
|
+
log_info "Git hooks detected → installing hooks via scripts/install-hooks.sh"
|
|
528
|
+
bash "$installer" --install
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
# ============================================================================
|
|
532
|
+
# Publish Logic
|
|
533
|
+
# ============================================================================
|
|
534
|
+
|
|
535
|
+
resolve_publish_keys() {
|
|
536
|
+
local target="$1"
|
|
537
|
+
|
|
538
|
+
# Special handlers — not in PUBLISHABLE
|
|
539
|
+
if [[ "$target" == "gitlab-ci" || "$target" == "hooks" ]]; then
|
|
540
|
+
echo "$target"
|
|
541
|
+
return 0
|
|
542
|
+
fi
|
|
543
|
+
|
|
544
|
+
if [[ -n "${PUBLISH_GROUPS[$target]:-}" ]]; then
|
|
545
|
+
echo "${PUBLISH_GROUPS[$target]}"
|
|
546
|
+
return 0
|
|
547
|
+
fi
|
|
548
|
+
|
|
549
|
+
if [[ -n "${PUBLISHABLE[$target]:-}" ]]; then
|
|
550
|
+
echo "$target"
|
|
551
|
+
return 0
|
|
552
|
+
fi
|
|
553
|
+
|
|
554
|
+
log_error "Unknown publish target: '${target}'"
|
|
555
|
+
echo "" >&2
|
|
556
|
+
echo "Valid groups: ${!PUBLISH_GROUPS[*]}" >&2
|
|
557
|
+
echo "Valid configs: ${!PUBLISHABLE[*]} gitlab-ci hooks" >&2
|
|
558
|
+
echo "Run --help for details" >&2
|
|
559
|
+
exit 1
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
# Dispatch --publish=gitlab-ci based on detected project type.
|
|
563
|
+
# When laravel-dev-tools is present, delegates to it so the fullstack stub
|
|
564
|
+
# (single source of truth in laravel-dev-tools) is used automatically.
|
|
565
|
+
publish_gitlab_ci() {
|
|
566
|
+
if [[ "$PROJECT_TYPE" == "laravel-app" ]]; then
|
|
567
|
+
local laravel_setup="${PROJECT_ROOT}/vendor/zairakai/laravel-dev-tools/scripts/setup-package.sh"
|
|
568
|
+
if [[ -f "$laravel_setup" ]]; then
|
|
569
|
+
log_info "laravel-dev-tools detected → delegating gitlab-ci publish (fullstack)"
|
|
570
|
+
local extra_args=()
|
|
571
|
+
[[ "$FORCE_OVERWRITE" == "true" ]] && extra_args+=("--force")
|
|
572
|
+
[[ "$SILENT_MODE" == "true" ]] && extra_args+=("--silent")
|
|
573
|
+
bash "$laravel_setup" --publish=gitlab-ci "${extra_args[@]}"
|
|
574
|
+
return 0
|
|
575
|
+
fi
|
|
576
|
+
log_info "Project type: laravel-app → publishing .gitlab/pipeline-js-app.yml"
|
|
577
|
+
publish_gitlab_ci_laravel
|
|
578
|
+
else
|
|
579
|
+
log_info "Project type: npm-package → publishing .gitlab-ci.yml"
|
|
580
|
+
publish_gitlab_ci_npm
|
|
581
|
+
fi
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
do_publish() {
|
|
585
|
+
local -a keys
|
|
586
|
+
read -ra keys <<< "$(resolve_publish_keys "$PUBLISH_TARGET")"
|
|
587
|
+
|
|
588
|
+
log_header "Publishing Dev Tools Configs"
|
|
589
|
+
|
|
590
|
+
for key in "${keys[@]}"; do
|
|
591
|
+
# Dispatch special handler — project-type aware
|
|
592
|
+
if [[ "$key" == "gitlab-ci" ]]; then
|
|
593
|
+
publish_gitlab_ci
|
|
594
|
+
continue
|
|
595
|
+
fi
|
|
596
|
+
|
|
597
|
+
# Dispatch special handler — git hooks
|
|
598
|
+
if [[ "$key" == "hooks" ]]; then
|
|
599
|
+
publish_hooks
|
|
600
|
+
continue
|
|
601
|
+
fi
|
|
602
|
+
|
|
603
|
+
# Dispatch special handler — governance files
|
|
604
|
+
if [[ "$key" == "governance" ]]; then
|
|
605
|
+
publish_governance_files
|
|
606
|
+
continue
|
|
607
|
+
fi
|
|
608
|
+
|
|
609
|
+
local entry="${PUBLISHABLE[$key]:-}"
|
|
610
|
+
[[ -z "$entry" ]] && continue
|
|
611
|
+
|
|
612
|
+
local source_rel="${entry%%|*}"
|
|
613
|
+
local rest="${entry#*|}"
|
|
614
|
+
local target_rel="${rest%%|*}"
|
|
615
|
+
|
|
616
|
+
publish_file \
|
|
617
|
+
"${DEV_TOOLS_ROOT}/${source_rel}" \
|
|
618
|
+
"${PROJECT_ROOT}/${target_rel}" \
|
|
619
|
+
"$key"
|
|
620
|
+
done
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
# ============================================================================
|
|
624
|
+
# Makefile Setup
|
|
625
|
+
# ============================================================================
|
|
626
|
+
|
|
627
|
+
generate_makefile() {
|
|
628
|
+
local target="${PROJECT_ROOT}/Makefile"
|
|
629
|
+
local package_name
|
|
630
|
+
|
|
631
|
+
package_name="$(node -e "try{const p=require('${PROJECT_ROOT}/package.json');console.log(p.name||'')}catch(e){}" 2>/dev/null || echo "")"
|
|
632
|
+
|
|
633
|
+
cat > "$target" << 'MAKEFILE_EOF'
|
|
634
|
+
# Makefile
|
|
635
|
+
# Generated by @zairakai/js-dev-tools setup-project.sh
|
|
636
|
+
# Run `make help` to see available commands.
|
|
637
|
+
#
|
|
638
|
+
# To regenerate:
|
|
639
|
+
# bash node_modules/@zairakai/js-dev-tools/scripts/setup-project.sh --with-makefile --force
|
|
640
|
+
|
|
641
|
+
MAKEFILE_EOF
|
|
642
|
+
|
|
643
|
+
if [[ -n "$package_name" ]]; then
|
|
644
|
+
echo "NPM_DIRECTORY_TOOLS_PROJECT_NAME := \"${package_name}\"" >> "$target"
|
|
645
|
+
echo "" >> "$target"
|
|
646
|
+
fi
|
|
647
|
+
|
|
648
|
+
cat >> "$target" << 'MAKEFILE_EOF'
|
|
649
|
+
DEV_TOOLS_NPM := node_modules/@zairakai/js-dev-tools
|
|
650
|
+
|
|
651
|
+
include $(DEV_TOOLS_NPM)/tools/make/core.mk
|
|
652
|
+
MAKEFILE_EOF
|
|
653
|
+
|
|
654
|
+
track_created "Makefile"
|
|
655
|
+
log_success "Created: Makefile"
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
inject_makefile() {
|
|
659
|
+
local target="${PROJECT_ROOT}/Makefile"
|
|
660
|
+
local marker="# @zairakai/js-dev-tools"
|
|
661
|
+
|
|
662
|
+
if grep -qF "$marker" "$target" 2>/dev/null; then
|
|
663
|
+
log_info "Makefile already includes @zairakai/js-dev-tools — skipping"
|
|
664
|
+
track_skipped "Makefile (already injected)"
|
|
665
|
+
return 0
|
|
666
|
+
fi
|
|
667
|
+
|
|
668
|
+
log_info "Existing Makefile detected — injecting @zairakai/js-dev-tools includes"
|
|
669
|
+
|
|
670
|
+
cat >> "$target" << 'INJECT_EOF'
|
|
671
|
+
|
|
672
|
+
# ─── @zairakai/js-dev-tools ─────────────────────────────────────────────────────
|
|
673
|
+
# Injected by: bash node_modules/@zairakai/js-dev-tools/scripts/setup-project.sh --with-makefile
|
|
674
|
+
# Provides: eslint, prettier, stylelint, markdownlint, shellcheck, typecheck, build, knip, test, quality, bats targets
|
|
675
|
+
DEV_TOOLS_NPM := node_modules/@zairakai/js-dev-tools
|
|
676
|
+
-include $(DEV_TOOLS_NPM)/tools/make/variables.mk
|
|
677
|
+
-include $(DEV_TOOLS_NPM)/tools/make/help.mk
|
|
678
|
+
-include $(DEV_TOOLS_NPM)/tools/make/code-style.mk
|
|
679
|
+
-include $(DEV_TOOLS_NPM)/tools/make/stylelint.mk
|
|
680
|
+
-include $(DEV_TOOLS_NPM)/tools/make/markdownlint.mk
|
|
681
|
+
-include $(DEV_TOOLS_NPM)/tools/make/shellcheck.mk
|
|
682
|
+
-include $(DEV_TOOLS_NPM)/tools/make/typescript.mk
|
|
683
|
+
-include $(DEV_TOOLS_NPM)/tools/make/quality.mk
|
|
684
|
+
-include $(DEV_TOOLS_NPM)/tools/make/test.mk
|
|
685
|
+
-include $(DEV_TOOLS_NPM)/tools/make/bats.mk
|
|
686
|
+
INJECT_EOF
|
|
687
|
+
|
|
688
|
+
track_created "Makefile (injected)"
|
|
689
|
+
log_success "Injected @zairakai/js-dev-tools targets into existing Makefile"
|
|
690
|
+
log_info "Note: 'make help' will show JS targets alongside your existing targets"
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
setup_makefile() {
|
|
694
|
+
local target="${PROJECT_ROOT}/Makefile"
|
|
695
|
+
|
|
696
|
+
if [[ -f "$target" ]]; then
|
|
697
|
+
inject_makefile
|
|
698
|
+
else
|
|
699
|
+
generate_makefile
|
|
700
|
+
fi
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
# ============================================================================
|
|
704
|
+
# Main Setup
|
|
705
|
+
# ============================================================================
|
|
706
|
+
|
|
707
|
+
setup_project() {
|
|
708
|
+
[[ "$SILENT_MODE" != "true" ]] && {
|
|
709
|
+
echo ""
|
|
710
|
+
echo -e "${MAGENTA}📦 NPM Dev Tools Setup${NC}"
|
|
711
|
+
echo -e "${CYAN}Type:${NC} ${PROJECT_TYPE} | ${CYAN}Package manager:${NC} ${PM}"
|
|
712
|
+
echo ""
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
# ─── Publish mode ────────────────────────────────────────────────────────
|
|
716
|
+
if [[ -n "$PUBLISH_TARGET" ]]; then
|
|
717
|
+
do_publish
|
|
718
|
+
|
|
719
|
+
[[ "$WITH_MAKEFILE" == "true" ]] && setup_makefile
|
|
720
|
+
|
|
721
|
+
echo ""
|
|
722
|
+
echo -e "${MAGENTA}┌────────────────────────────────────────┐${NC}"
|
|
723
|
+
echo -e "${MAGENTA}│${NC} ${GREEN}Publish Complete${NC} ${MAGENTA}│${NC}"
|
|
724
|
+
echo -e "${MAGENTA}├────────────────────────────────────────┤${NC}"
|
|
725
|
+
|
|
726
|
+
for f in "${PUBLISHED_FILES[@]}"; do
|
|
727
|
+
echo -e "${MAGENTA}│${NC} ${GREEN}✓${NC} ${f}"
|
|
728
|
+
done
|
|
729
|
+
|
|
730
|
+
if [[ ${#CREATED_FILES[@]} -gt 0 ]]; then
|
|
731
|
+
for f in "${CREATED_FILES[@]}"; do
|
|
732
|
+
echo -e "${MAGENTA}│${NC} ${GREEN}✓${NC} ${f}"
|
|
733
|
+
done
|
|
734
|
+
fi
|
|
735
|
+
|
|
736
|
+
if [[ ${#SKIPPED_FILES[@]} -gt 0 ]]; then
|
|
737
|
+
echo -e "${MAGENTA}│${NC} ${YELLOW}○ Skipped (modified):${NC} ${SKIPPED_FILES[*]}"
|
|
738
|
+
echo -e "${MAGENTA}│${NC} ${YELLOW}→ Use --force to overwrite${NC}"
|
|
739
|
+
fi
|
|
740
|
+
|
|
741
|
+
if [[ ${#BACKED_UP_FILES[@]} -gt 0 ]]; then
|
|
742
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}↩ Backed up:${NC} ${BACKED_UP_FILES[*]}"
|
|
743
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}→ ${BACKUP_DIR}${NC}"
|
|
744
|
+
fi
|
|
745
|
+
|
|
746
|
+
echo -e "${MAGENTA}├────────────────────────────────────────┤${NC}"
|
|
747
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}Edit configs in:${NC} config/dev-tools/"
|
|
748
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}Help:${NC} bash setup-project.sh --help"
|
|
749
|
+
echo -e "${MAGENTA}└────────────────────────────────────────┘${NC}"
|
|
750
|
+
echo ""
|
|
751
|
+
exit 0
|
|
752
|
+
fi
|
|
753
|
+
|
|
754
|
+
# ─── Normal setup ────────────────────────────────────────────────────────
|
|
755
|
+
|
|
756
|
+
ensure_dir "${PROJECT_ROOT}/config/dev-tools"
|
|
757
|
+
|
|
758
|
+
if [[ "$PROJECT_TYPE" == "laravel-app" ]] \
|
|
759
|
+
&& [[ -f "${PROJECT_ROOT}/vendor/zairakai/laravel-dev-tools/scripts/setup-package.sh" ]]; then
|
|
760
|
+
log_info "Laravel app detected — delegating setup to laravel-dev-tools (full-stack)"
|
|
761
|
+
extra_args=()
|
|
762
|
+
[[ "$FORCE_OVERWRITE" == "true" ]] && extra_args+=("--force")
|
|
763
|
+
[[ "$SILENT_MODE" == "true" ]] && extra_args+=("--silent")
|
|
764
|
+
bash "${PROJECT_ROOT}/vendor/zairakai/laravel-dev-tools/scripts/setup-package.sh" --fullstack "${extra_args[@]}"
|
|
765
|
+
else
|
|
766
|
+
if [[ "$WITH_MAKEFILE" == "true" ]] || [[ ! -f "${PROJECT_ROOT}/Makefile" ]]; then
|
|
767
|
+
setup_makefile
|
|
768
|
+
fi
|
|
769
|
+
|
|
770
|
+
# .editorconfig (always copied - needed by IDEs)
|
|
771
|
+
setup_file "${DEV_TOOLS_ROOT}/.editorconfig" "${PROJECT_ROOT}/.editorconfig" ".editorconfig"
|
|
772
|
+
|
|
773
|
+
# ESLint baseline (published config only)
|
|
774
|
+
setup_file "${DEV_TOOLS_ROOT}/stubs/quality/eslint.config.js.stub" \
|
|
775
|
+
"${PROJECT_ROOT}/config/dev-tools/eslint.config.js" \
|
|
776
|
+
"config/dev-tools/eslint.config.js"
|
|
777
|
+
fi
|
|
778
|
+
|
|
779
|
+
# ─── Summary ─────────────────────────────────────────────────────────────
|
|
780
|
+
if [[ "$SILENT_MODE" == "true" ]]; then
|
|
781
|
+
check_optional_deps
|
|
782
|
+
[[ ${#CREATED_FILES[@]} -eq 0 ]] && exit 0
|
|
783
|
+
fi
|
|
784
|
+
|
|
785
|
+
echo ""
|
|
786
|
+
echo -e "${MAGENTA}┌────────────────────────────────────────┐${NC}"
|
|
787
|
+
echo -e "${MAGENTA}│${NC} ${GREEN}Setup Complete${NC} ${MAGENTA}│${NC}"
|
|
788
|
+
echo -e "${MAGENTA}├────────────────────────────────────────┤${NC}"
|
|
789
|
+
|
|
790
|
+
if [[ ${#CREATED_FILES[@]} -gt 0 ]]; then
|
|
791
|
+
echo -e "${MAGENTA}│${NC} ${GREEN}✓ Created:${NC} ${CREATED_FILES[*]}"
|
|
792
|
+
fi
|
|
793
|
+
|
|
794
|
+
if [[ ${#SKIPPED_FILES[@]} -gt 0 ]]; then
|
|
795
|
+
echo -e "${MAGENTA}│${NC} ${YELLOW}○ Skipped:${NC} ${SKIPPED_FILES[*]}"
|
|
796
|
+
fi
|
|
797
|
+
|
|
798
|
+
if [[ ${#BACKED_UP_FILES[@]} -gt 0 ]]; then
|
|
799
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}↩ Backed up:${NC} ${BACKED_UP_FILES[*]}"
|
|
800
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}→ ${BACKUP_DIR}${NC}"
|
|
801
|
+
fi
|
|
802
|
+
|
|
803
|
+
echo -e "${MAGENTA}├────────────────────────────────────────┤${NC}"
|
|
804
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}Type:${NC} ${PROJECT_TYPE} | ${CYAN}PM:${NC} ${PM}"
|
|
805
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}Publish configs:${NC} bash setup-project.sh --publish"
|
|
806
|
+
echo -e "${MAGENTA}│${NC} ${CYAN}Run:${NC} make help"
|
|
807
|
+
echo -e "${MAGENTA}└────────────────────────────────────────┘${NC}"
|
|
808
|
+
|
|
809
|
+
check_optional_deps
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
# ============================================================================
|
|
813
|
+
# Execute
|
|
814
|
+
# ============================================================================
|
|
815
|
+
|
|
816
|
+
setup_project
|