@smartsoft001-mobilems/claude-plugins 2.85.0 → 2.87.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/.claude-plugin/marketplace.json +2 -6
- package/package.json +2 -2
- package/plugins/mobilems/.claude-plugin/README.md +30 -0
- package/plugins/mobilems/.claude-plugin/plugin.json +5 -0
- package/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh +372 -0
- package/plugins/mobilems/skills/mobilems-articles/SKILL.md +84 -0
- package/plugins/mobilems/skills/mobilems-articles/references/lib-contents.md +164 -0
- package/plugins/mobilems/skills/mobilems-articles/references/module-and-routes.md +146 -0
- package/plugins/mobilems/skills/mobilems-articles/references/shared-components.md +56 -0
- package/plugins/mobilems/skills/mobilems-articles/scripts/detect-init.sh +29 -0
- package/plugins/mobilems/skills/mobilems-articles/scripts/verify-module.sh +61 -0
- package/plugins/mobilems/skills/mobilems-docs-reader/SKILL.md +116 -0
- package/plugins/mobilems/skills/mobilems-events/SKILL.md +65 -0
- package/plugins/mobilems/skills/mobilems-events/references/lib-contents.md +212 -0
- package/plugins/mobilems/skills/mobilems-events/references/module-and-routes.md +113 -0
- package/plugins/mobilems/skills/mobilems-events/scripts/detect-init.sh +29 -0
- package/plugins/mobilems/skills/mobilems-events/scripts/verify-module.sh +59 -0
- package/plugins/mobilems/skills/mobilems-object-collections/SKILL.md +52 -0
- package/plugins/mobilems/skills/mobilems-object-collections/references/lib-contents.md +76 -0
- package/plugins/mobilems/skills/mobilems-object-collections/references/module-and-routes.md +116 -0
- package/plugins/mobilems/skills/mobilems-object-collections/references/shared-components.md +61 -0
- package/plugins/mobilems/skills/mobilems-object-collections/scripts/detect-init.sh +29 -0
- package/plugins/mobilems/skills/mobilems-object-collections/scripts/verify-module.sh +44 -0
- package/plugins/mobilems/skills/mobilems-objects/SKILL.md +52 -0
- package/plugins/mobilems/skills/mobilems-objects/references/lib-contents.md +68 -0
- package/plugins/mobilems/skills/mobilems-objects/references/module-and-routes.md +108 -0
- package/plugins/mobilems/skills/mobilems-objects/references/shared-components.md +69 -0
- package/plugins/mobilems/skills/mobilems-objects/scripts/detect-init.sh +29 -0
- package/plugins/mobilems/skills/mobilems-objects/scripts/verify-module.sh +51 -0
- package/plugins/mobilems/skills/mobilems-partners/SKILL.md +65 -0
- package/plugins/mobilems/skills/mobilems-partners/references/lib-contents.md +160 -0
- package/plugins/mobilems/skills/mobilems-partners/references/module-and-routes.md +125 -0
- package/plugins/mobilems/skills/mobilems-partners/scripts/detect-init.sh +29 -0
- package/plugins/mobilems/skills/mobilems-partners/scripts/verify-module.sh +59 -0
- package/plugins/mobilems/skills/mobilems-project-init/SKILL.md +134 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/app-shell.md +107 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/claude-config.md +44 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/config-providers.md +203 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/npm-deps.md +66 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/server-env.md +89 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/shared-lib.md +125 -0
- package/plugins/mobilems/skills/mobilems-project-init/references/tailwind-styles.md +106 -0
- package/plugins/mobilems/skills/mobilems-project-init/scripts/classify-shared-components.py +114 -0
- package/plugins/mobilems/skills/mobilems-project-init/scripts/detect-base.sh +49 -0
- package/plugins/mobilems/skills/mobilems-project-init/scripts/verify-init.sh +73 -0
- package/plugins/mobilems/skills/mobilems-thematic-publications/SKILL.md +60 -0
- package/plugins/mobilems/skills/mobilems-thematic-publications/references/lib-contents.md +134 -0
- package/plugins/mobilems/skills/mobilems-thematic-publications/references/module-and-routes.md +107 -0
- package/plugins/mobilems/skills/mobilems-thematic-publications/scripts/detect-init.sh +29 -0
- package/plugins/mobilems/skills/mobilems-thematic-publications/scripts/verify-module.sh +56 -0
- package/plugins/flow/.claude-plugin/README.md +0 -91
- package/plugins/flow/.claude-plugin/merge-permissions.js +0 -97
- package/plugins/flow/.claude-plugin/plugin.json +0 -5
- package/plugins/flow/.claude-plugin/settings.template.json +0 -86
- package/plugins/flow/agents/angular-component-scaffolder.md +0 -175
- package/plugins/flow/agents/angular-directive-builder.md +0 -153
- package/plugins/flow/agents/angular-guard-builder.md +0 -243
- package/plugins/flow/agents/angular-jest-test-writer.md +0 -474
- package/plugins/flow/agents/angular-pipe-builder.md +0 -169
- package/plugins/flow/agents/angular-resolver-builder.md +0 -286
- package/plugins/flow/agents/angular-service-builder.md +0 -161
- package/plugins/flow/agents/angular-signal-state-builder.md +0 -339
- package/plugins/flow/agents/angular-test-diagnostician.md +0 -279
- package/plugins/flow/agents/angular-testbed-configurator.md +0 -315
- package/plugins/flow/agents/arch-scaffolder.md +0 -278
- package/plugins/flow/agents/e2e-data-testid-injector.md +0 -197
- package/plugins/flow/agents/e2e-project-scaffolder.md +0 -194
- package/plugins/flow/agents/e2e-test-writer.md +0 -350
- package/plugins/flow/agents/shared-agent-evolver.md +0 -294
- package/plugins/flow/agents/shared-build-verifier.md +0 -160
- package/plugins/flow/agents/shared-config-updater.md +0 -310
- package/plugins/flow/agents/shared-coverage-enforcer.md +0 -184
- package/plugins/flow/agents/shared-error-handler.md +0 -217
- package/plugins/flow/agents/shared-file-creator.md +0 -344
- package/plugins/flow/agents/shared-impl-orchestrator.md +0 -312
- package/plugins/flow/agents/shared-impl-reporter.md +0 -368
- package/plugins/flow/agents/shared-impl-teammate.md +0 -201
- package/plugins/flow/agents/shared-linear-subtask-iterator.md +0 -337
- package/plugins/flow/agents/shared-logic-implementer.md +0 -243
- package/plugins/flow/agents/shared-maia-api.md +0 -26
- package/plugins/flow/agents/shared-parallelization-analyzer.md +0 -343
- package/plugins/flow/agents/shared-performance-validator.md +0 -168
- package/plugins/flow/agents/shared-plan-perspective.md +0 -269
- package/plugins/flow/agents/shared-project-standardizer.md +0 -205
- package/plugins/flow/agents/shared-report-synthesizer.md +0 -188
- package/plugins/flow/agents/shared-review-teammate.md +0 -189
- package/plugins/flow/agents/shared-security-scanner.md +0 -186
- package/plugins/flow/agents/shared-style-enforcer.md +0 -230
- package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +0 -188
- package/plugins/flow/agents/shared-tdd-developer.md +0 -350
- package/plugins/flow/agents/shared-team-coordinator.md +0 -189
- package/plugins/flow/agents/shared-test-fixer.md +0 -186
- package/plugins/flow/agents/shared-test-runner.md +0 -191
- package/plugins/flow/agents/shared-ui-classifier.md +0 -263
- package/plugins/flow/agents/shared-verification-orchestrator.md +0 -194
- package/plugins/flow/agents/shared-verification-runner.md +0 -140
- package/plugins/flow/agents/ui-a11y-validator.md +0 -305
- package/plugins/flow/agents/ui-screenshot-reporter.md +0 -329
- package/plugins/flow/agents/ui-web-designer.md +0 -214
- package/plugins/flow/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow/skills/a11y-audit/SKILL.md +0 -214
- package/plugins/flow/skills/angular-patterns/SKILL.md +0 -191
- package/plugins/flow/skills/browser-capture/SKILL.md +0 -238
- package/plugins/flow/skills/commit/SKILL.md +0 -259
- package/plugins/flow/skills/debug-helper/SKILL.md +0 -375
- package/plugins/flow/skills/impl/SKILL.md +0 -992
- package/plugins/flow/skills/linear-suggestion/SKILL.md +0 -132
- package/plugins/flow/skills/maia-files-delete/SKILL.md +0 -59
- package/plugins/flow/skills/maia-files-upload/SKILL.md +0 -57
- package/plugins/flow/skills/nx-conventions/SKILL.md +0 -326
- package/plugins/flow/skills/plan/SKILL.md +0 -1033
- package/plugins/flow/skills/push/SKILL.md +0 -759
- package/plugins/flow/skills/review/SKILL.md +0 -443
- package/plugins/flow/skills/test-e2e/SKILL.md +0 -161
- package/plugins/flow/skills/test-unit/SKILL.md +0 -456
- package/plugins/flow-external/.claude-plugin/README.md +0 -152
- package/plugins/flow-external/.claude-plugin/merge-permissions.js +0 -80
- package/plugins/flow-external/.claude-plugin/plugin.json +0 -5
- package/plugins/flow-external/.claude-plugin/settings.template.json +0 -78
- package/plugins/flow-external/agents/angular-component-scaffolder.md +0 -269
- package/plugins/flow-external/agents/angular-directive-builder.md +0 -130
- package/plugins/flow-external/agents/angular-guard-builder.md +0 -70
- package/plugins/flow-external/agents/angular-pipe-builder.md +0 -82
- package/plugins/flow-external/agents/angular-resolver-builder.md +0 -74
- package/plugins/flow-external/agents/angular-service-builder.md +0 -160
- package/plugins/flow-external/agents/angular-state-builder.md +0 -254
- package/plugins/flow-external/agents/shared-build-verifier.md +0 -67
- package/plugins/flow-external/agents/shared-impl-orchestrator.md +0 -88
- package/plugins/flow-external/agents/shared-impl-reporter.md +0 -135
- package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +0 -70
- package/plugins/flow-external/agents/shared-ui-classifier.md +0 -38
- package/plugins/flow-external/agents/ui-web-designer.md +0 -179
- package/plugins/flow-external/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow-external/skills/a11y-audit/SKILL.md +0 -96
- package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +0 -267
- package/plugins/flow-external/skills/angular-patterns/SKILL.md +0 -170
- package/plugins/flow-external/skills/browser-capture/SKILL.md +0 -68
- package/plugins/flow-external/skills/commit/SKILL.md +0 -114
- package/plugins/flow-external/skills/debug-helper/SKILL.md +0 -131
- package/plugins/flow-external/skills/impl/SKILL.md +0 -217
- package/plugins/flow-external/skills/linear-suggestion/SKILL.md +0 -62
- package/plugins/flow-external/skills/maia-files-delete/SKILL.md +0 -34
- package/plugins/flow-external/skills/maia-files-upload/SKILL.md +0 -41
- package/plugins/flow-external/skills/plan/SKILL.md +0 -334
- package/plugins/flow-external/skills/push/SKILL.md +0 -232
- package/plugins/flow-legacy/.claude-plugin/README.md +0 -143
- package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +0 -94
- package/plugins/flow-legacy/.claude-plugin/plugin.json +0 -5
- package/plugins/flow-legacy/.claude-plugin/settings.template.json +0 -79
- package/plugins/flow-legacy/agents/angular-component-scaffolder.md +0 -323
- package/plugins/flow-legacy/agents/angular-directive-builder.md +0 -258
- package/plugins/flow-legacy/agents/angular-guard-builder.md +0 -322
- package/plugins/flow-legacy/agents/angular-pipe-builder.md +0 -227
- package/plugins/flow-legacy/agents/angular-resolver-builder.md +0 -332
- package/plugins/flow-legacy/agents/angular-service-builder.md +0 -271
- package/plugins/flow-legacy/agents/angular-state-builder.md +0 -479
- package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +0 -174
- package/plugins/flow-legacy/agents/shared-impl-reporter.md +0 -232
- package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +0 -187
- package/plugins/flow-legacy/agents/shared-tdd-developer.md +0 -306
- package/plugins/flow-legacy/agents/shared-test-runner.md +0 -131
- package/plugins/flow-legacy/agents/shared-ui-classifier.md +0 -145
- package/plugins/flow-legacy/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +0 -214
- package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +0 -346
- package/plugins/flow-legacy/skills/browser-capture/SKILL.md +0 -238
- package/plugins/flow-legacy/skills/commit/SKILL.md +0 -215
- package/plugins/flow-legacy/skills/debug-helper/SKILL.md +0 -395
- package/plugins/flow-legacy/skills/impl/SKILL.md +0 -710
- package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +0 -132
- package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +0 -59
- package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +0 -57
- package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +0 -368
- package/plugins/flow-legacy/skills/plan/SKILL.md +0 -742
- package/plugins/flow-legacy/skills/push/SKILL.md +0 -645
- package/plugins/flow-legacy/skills/test-unit/SKILL.md +0 -500
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartsoft001-mobilems/claude-plugins",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.87.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"scripts": {
|
|
8
|
-
"postinstall": "claude plugin update
|
|
8
|
+
"postinstall": "claude plugin update mobilems@mobilems --scope project || true"
|
|
9
9
|
},
|
|
10
10
|
"types": "./src/index.d.ts",
|
|
11
11
|
"main": "./src/index.js",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Mobilems Plugin for Claude Code
|
|
2
|
+
|
|
3
|
+
MobileMS-specific skills for the MuzaCMS / MobileMS indexer API. This plugin is a thin complement to the generic `flow@smart-pro` workflow plugins — it provides skills that are tied to the MobileMS backend.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
| Type | Name | Purpose |
|
|
8
|
+
|------|------|---------|
|
|
9
|
+
| Skill | `mobilems-docs-reader` | Answer questions about the MuzaCMS / MobileMS indexer OpenAPI spec; fetches a fresh copy via the bundled refresh script |
|
|
10
|
+
|
|
11
|
+
The skill ships with `scripts/refresh-mobilems-api-spec.sh`, which logs into `https://develop-indexer.mobilems.pl` using `MOBILEMS_LOGIN` / `MOBILEMS_PASSWORD` (read from env or `.env`) and writes the spec to `shared-assets/mobilems-api.json` inside the installed package. The script caches the fetched spec per Claude Code session (8h TTL).
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Enable in the consumer project's `.claude/settings.json`:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"enabledPlugins": {
|
|
20
|
+
"mobilems@mobilems": true
|
|
21
|
+
},
|
|
22
|
+
"permissions": {
|
|
23
|
+
"allow": [
|
|
24
|
+
"Bash(bash ./node_modules/@smartsoft001-mobilems/claude-plugins/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh:*)"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Generic workflow skills (`/commit`, `/impl`, `/plan`, `/push`, etc.) come from `flow@smart-pro` — see `@smartsoft001/pro-claude-plugins`. Maia API skills (`maia-files-upload`, `maia-files-delete`, `shared-maia-api`) are not MobilEMS-specific and live in `flow@smart-pro`.
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Refresh the MuzaCMS / MobileMS indexer OpenAPI spec.
|
|
3
|
+
#
|
|
4
|
+
# Logs in to https://develop-indexer.mobilems.pl via Symfony form-login,
|
|
5
|
+
# scrapes the Swagger 2.0 JSON from /docs/api, and writes it next to this
|
|
6
|
+
# skill's owning package under shared-assets/mobilems-api.json.
|
|
7
|
+
#
|
|
8
|
+
# Required tools: bash, curl, jq.
|
|
9
|
+
# Required env vars (read from shell or auto-loaded from $PWD/.env):
|
|
10
|
+
# MOBILEMS_LOGIN — MuzaCMS username
|
|
11
|
+
# MOBILEMS_PASSWORD — MuzaCMS password
|
|
12
|
+
#
|
|
13
|
+
# Cache: a sibling mobilems-api.meta.json stores { sessionId, fetchedAt }.
|
|
14
|
+
# The script skips the network call when the same Claude Code session
|
|
15
|
+
# (CLAUDE_CODE_SESSION_ID) already fetched the spec less than 8h ago.
|
|
16
|
+
|
|
17
|
+
set -u
|
|
18
|
+
|
|
19
|
+
BASE='https://develop-indexer.mobilems.pl'
|
|
20
|
+
LOGIN_URL="${BASE}/admin/login"
|
|
21
|
+
DOCS_URL="${BASE}/docs/api"
|
|
22
|
+
|
|
23
|
+
QUIET=0
|
|
24
|
+
for arg in "$@"; do
|
|
25
|
+
case "$arg" in
|
|
26
|
+
--quiet) QUIET=1 ;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
if [[ "${CLAUDE_AGENT_INVOCATION:-0}" == "1" ]]; then
|
|
30
|
+
QUIET=1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
log() {
|
|
34
|
+
if [[ "$QUIET" -eq 0 ]]; then
|
|
35
|
+
printf '%s\n' "$*"
|
|
36
|
+
fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
err() {
|
|
40
|
+
printf '%s\n' "$*" >&2
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
die() {
|
|
44
|
+
err "$*"
|
|
45
|
+
exit 1
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# --- dependency check --------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
check_deps() {
|
|
51
|
+
local missing=()
|
|
52
|
+
command -v curl >/dev/null 2>&1 || missing+=("curl")
|
|
53
|
+
command -v jq >/dev/null 2>&1 || missing+=("jq")
|
|
54
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
55
|
+
err "✗ Brak wymaganych narzędzi: ${missing[*]}"
|
|
56
|
+
err ""
|
|
57
|
+
err "Zainstaluj:"
|
|
58
|
+
err " macOS: brew install ${missing[*]}"
|
|
59
|
+
err " Debian/Ubuntu: sudo apt install ${missing[*]}"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# --- .env loader -------------------------------------------------------------
|
|
65
|
+
# Minimal KEY=value parser. Ignores blank lines and #-comments, strips matching
|
|
66
|
+
# surrounding quotes, and never overrides already-set env vars (parity with the
|
|
67
|
+
# old refresh-mobilems-api-spec.js loader).
|
|
68
|
+
|
|
69
|
+
load_dotenv() {
|
|
70
|
+
local env_path="${PWD}/.env"
|
|
71
|
+
[[ -f "$env_path" ]] || return 0
|
|
72
|
+
local line key value first last
|
|
73
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
74
|
+
# trim leading/trailing whitespace
|
|
75
|
+
line="${line#"${line%%[![:space:]]*}"}"
|
|
76
|
+
line="${line%"${line##*[![:space:]]}"}"
|
|
77
|
+
[[ -z "$line" ]] && continue
|
|
78
|
+
[[ "${line:0:1}" == "#" ]] && continue
|
|
79
|
+
[[ "$line" != *"="* ]] && continue
|
|
80
|
+
key="${line%%=*}"
|
|
81
|
+
value="${line#*=}"
|
|
82
|
+
# trim whitespace around key/value
|
|
83
|
+
key="${key#"${key%%[![:space:]]*}"}"
|
|
84
|
+
key="${key%"${key##*[![:space:]]}"}"
|
|
85
|
+
value="${value#"${value%%[![:space:]]*}"}"
|
|
86
|
+
value="${value%"${value##*[![:space:]]}"}"
|
|
87
|
+
[[ -z "$key" ]] && continue
|
|
88
|
+
# strip matching surrounding quotes (single or double)
|
|
89
|
+
first="${value:0:1}"
|
|
90
|
+
last="${value: -1}"
|
|
91
|
+
if [[ ${#value} -ge 2 ]] && { [[ "$first" == '"' && "$last" == '"' ]] || [[ "$first" == "'" && "$last" == "'" ]]; }; then
|
|
92
|
+
value="${value:1:${#value}-2}"
|
|
93
|
+
fi
|
|
94
|
+
# only set if not already in env
|
|
95
|
+
if [[ -z "${!key+x}" ]]; then
|
|
96
|
+
export "$key=$value"
|
|
97
|
+
fi
|
|
98
|
+
done < "$env_path"
|
|
99
|
+
log "→ loaded .env from $env_path"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# --- env-var validation (per Linear FRA-95 — Emil's request) ----------------
|
|
103
|
+
# This runs as the very first step after .env loading. We MUST NOT attempt any
|
|
104
|
+
# HTTP call until both credentials are present.
|
|
105
|
+
|
|
106
|
+
validate_env_vars() {
|
|
107
|
+
if [[ -z "${MOBILEMS_LOGIN:-}" || -z "${MOBILEMS_PASSWORD:-}" ]]; then
|
|
108
|
+
err "✗ Brak wymaganych zmiennych środowiskowych dla MuzaCMS API:"
|
|
109
|
+
err " MOBILEMS_LOGIN, MOBILEMS_PASSWORD"
|
|
110
|
+
err ""
|
|
111
|
+
err "Ustaw je w shellu:"
|
|
112
|
+
err " export MOBILEMS_LOGIN=..."
|
|
113
|
+
err " export MOBILEMS_PASSWORD=..."
|
|
114
|
+
err ""
|
|
115
|
+
err "Lub w pliku .env w katalogu głównym projektu:"
|
|
116
|
+
err " MOBILEMS_LOGIN=..."
|
|
117
|
+
err " MOBILEMS_PASSWORD=..."
|
|
118
|
+
err ""
|
|
119
|
+
err "Szczegóły: @smartsoft001-mobilems/claude-plugins README.md"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# --- output dir resolution ---------------------------------------------------
|
|
125
|
+
# Mirrors resolveOutDir() in the old JS. Looks for shared-assets/ walking up
|
|
126
|
+
# from this script's directory.
|
|
127
|
+
|
|
128
|
+
resolve_out_dir() {
|
|
129
|
+
local script_dir
|
|
130
|
+
script_dir="$(cd "$(dirname "$0")" && pwd)"
|
|
131
|
+
# Installed layout (per-variant copy made by nx build):
|
|
132
|
+
# <pkg-root>/plugins/<variant>/scripts/refresh-mobilems-api-spec.sh
|
|
133
|
+
# <pkg-root>/shared-assets/mobilems-api.json
|
|
134
|
+
# Source layout:
|
|
135
|
+
# packages/shared/claude-plugins/scripts/refresh-mobilems-api-spec.sh
|
|
136
|
+
# packages/shared/claude-plugins/src/shared-assets/
|
|
137
|
+
local candidates=(
|
|
138
|
+
"$script_dir/../../../shared-assets"
|
|
139
|
+
"$script_dir/../shared-assets"
|
|
140
|
+
"$script_dir/../src/shared-assets"
|
|
141
|
+
)
|
|
142
|
+
local c
|
|
143
|
+
for c in "${candidates[@]}"; do
|
|
144
|
+
if [[ -d "$c" ]]; then
|
|
145
|
+
(cd "$c" && pwd)
|
|
146
|
+
return 0
|
|
147
|
+
fi
|
|
148
|
+
done
|
|
149
|
+
# No existing dir — pick the first candidate whose parent exists so we can
|
|
150
|
+
# mkdir into it.
|
|
151
|
+
for c in "${candidates[@]}"; do
|
|
152
|
+
if [[ -d "$(dirname "$c")" ]]; then
|
|
153
|
+
mkdir -p "$c"
|
|
154
|
+
(cd "$c" && pwd)
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
157
|
+
done
|
|
158
|
+
# Last resort: create alongside the script.
|
|
159
|
+
mkdir -p "$script_dir/shared-assets"
|
|
160
|
+
(cd "$script_dir/shared-assets" && pwd)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# --- cache decision ----------------------------------------------------------
|
|
164
|
+
# Mirrors cacheDecision() in the old JS.
|
|
165
|
+
|
|
166
|
+
MAX_CACHE_AGE_S=$((8 * 60 * 60))
|
|
167
|
+
|
|
168
|
+
iso_to_epoch() {
|
|
169
|
+
# macOS BSD date and GNU date diverge — try both forms.
|
|
170
|
+
local iso="$1"
|
|
171
|
+
if date -j -f "%Y-%m-%dT%H:%M:%SZ" "${iso%%.*}Z" "+%s" >/dev/null 2>&1; then
|
|
172
|
+
date -j -f "%Y-%m-%dT%H:%M:%SZ" "${iso%%.*}Z" "+%s"
|
|
173
|
+
elif date -d "$iso" "+%s" >/dev/null 2>&1; then
|
|
174
|
+
date -d "$iso" "+%s"
|
|
175
|
+
else
|
|
176
|
+
echo "0"
|
|
177
|
+
fi
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
cache_decision() {
|
|
181
|
+
# Echoes either "fetch:<reason>" or "skip:<age_seconds>".
|
|
182
|
+
local session_id="$1"
|
|
183
|
+
if [[ -z "$session_id" ]]; then
|
|
184
|
+
echo "fetch:manual/terminal invocation"
|
|
185
|
+
return
|
|
186
|
+
fi
|
|
187
|
+
if [[ ! -f "$SPEC_PATH" ]]; then
|
|
188
|
+
echo "fetch:spec file missing"
|
|
189
|
+
return
|
|
190
|
+
fi
|
|
191
|
+
if [[ ! -f "$META_PATH" ]]; then
|
|
192
|
+
echo "fetch:meta file missing"
|
|
193
|
+
return
|
|
194
|
+
fi
|
|
195
|
+
local meta_session meta_fetched_at meta_epoch now age
|
|
196
|
+
meta_session="$(jq -r '.sessionId // ""' "$META_PATH" 2>/dev/null)"
|
|
197
|
+
meta_fetched_at="$(jq -r '.fetchedAt // ""' "$META_PATH" 2>/dev/null)"
|
|
198
|
+
if [[ "$meta_session" != "$session_id" ]]; then
|
|
199
|
+
echo "fetch:new Claude Code session"
|
|
200
|
+
return
|
|
201
|
+
fi
|
|
202
|
+
if [[ -z "$meta_fetched_at" ]]; then
|
|
203
|
+
echo "fetch:meta missing fetchedAt"
|
|
204
|
+
return
|
|
205
|
+
fi
|
|
206
|
+
meta_epoch="$(iso_to_epoch "$meta_fetched_at")"
|
|
207
|
+
now="$(date +%s)"
|
|
208
|
+
age=$((now - meta_epoch))
|
|
209
|
+
if [[ "$meta_epoch" -le 0 || "$age" -gt "$MAX_CACHE_AGE_S" ]]; then
|
|
210
|
+
echo "fetch:cache older than 8 hours"
|
|
211
|
+
return
|
|
212
|
+
fi
|
|
213
|
+
echo "skip:$age"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# --- HTML extraction helpers -------------------------------------------------
|
|
217
|
+
|
|
218
|
+
extract_csrf() {
|
|
219
|
+
# Mirrors extractCsrf() in the old JS.
|
|
220
|
+
local html="$1"
|
|
221
|
+
local token
|
|
222
|
+
token="$(printf '%s' "$html" | grep -oE 'name="_csrf_token"[[:space:]]+value="[^"]+"' | head -n 1 | sed -E 's/.*value="([^"]+)".*/\1/')"
|
|
223
|
+
if [[ -z "$token" ]]; then
|
|
224
|
+
die "✗ Could not find _csrf_token in login form HTML."
|
|
225
|
+
fi
|
|
226
|
+
printf '%s' "$token"
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
extract_swagger_data() {
|
|
230
|
+
# Mirrors extractSwaggerData() in the old JS.
|
|
231
|
+
# The <script id="swagger-data" type="application/json"> tag wraps a JSON blob.
|
|
232
|
+
local html="$1"
|
|
233
|
+
local json
|
|
234
|
+
# awk lets us span newlines safely, where sed's portability gets hairy.
|
|
235
|
+
json="$(printf '%s' "$html" | awk '
|
|
236
|
+
BEGIN { in_block = 0 }
|
|
237
|
+
{
|
|
238
|
+
line = $0
|
|
239
|
+
if (in_block == 0) {
|
|
240
|
+
idx = index(line, "<script id=\"swagger-data\" type=\"application/json\">")
|
|
241
|
+
if (idx > 0) {
|
|
242
|
+
in_block = 1
|
|
243
|
+
line = substr(line, idx + length("<script id=\"swagger-data\" type=\"application/json\">"))
|
|
244
|
+
} else {
|
|
245
|
+
next
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
end_idx = index(line, "</script>")
|
|
249
|
+
if (end_idx > 0) {
|
|
250
|
+
printf "%s", substr(line, 1, end_idx - 1)
|
|
251
|
+
exit
|
|
252
|
+
} else {
|
|
253
|
+
printf "%s\n", line
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
')"
|
|
257
|
+
# trim leading/trailing whitespace
|
|
258
|
+
json="${json#"${json%%[![:space:]]*}"}"
|
|
259
|
+
json="${json%"${json##*[![:space:]]}"}"
|
|
260
|
+
if [[ -z "$json" ]]; then
|
|
261
|
+
die "✗ Could not find <script id=\"swagger-data\"> tag in /docs/api response. Login may have silently failed, or the docs page structure changed."
|
|
262
|
+
fi
|
|
263
|
+
printf '%s' "$json"
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
# --- main --------------------------------------------------------------------
|
|
267
|
+
|
|
268
|
+
check_deps
|
|
269
|
+
load_dotenv
|
|
270
|
+
validate_env_vars
|
|
271
|
+
|
|
272
|
+
OUT_DIR="$(resolve_out_dir)"
|
|
273
|
+
SPEC_PATH="$OUT_DIR/mobilems-api.json"
|
|
274
|
+
META_PATH="$OUT_DIR/mobilems-api.meta.json"
|
|
275
|
+
|
|
276
|
+
SESSION_ID="${CLAUDE_CODE_SESSION_ID:-}"
|
|
277
|
+
DECISION="$(cache_decision "$SESSION_ID")"
|
|
278
|
+
|
|
279
|
+
if [[ "$DECISION" == skip:* ]]; then
|
|
280
|
+
age_s="${DECISION#skip:}"
|
|
281
|
+
age_min=$(( (age_s + 30) / 60 ))
|
|
282
|
+
fetched_at="$(jq -r '.fetchedAt // "unknown"' "$META_PATH" 2>/dev/null)"
|
|
283
|
+
log "✓ spec cached for this Claude Code session (refreshed ${age_min} min ago at ${fetched_at}), skipping fetch"
|
|
284
|
+
exit 0
|
|
285
|
+
fi
|
|
286
|
+
|
|
287
|
+
REASON="${DECISION#fetch:}"
|
|
288
|
+
log "Refreshing MuzaCMS API spec from $BASE ($REASON)"
|
|
289
|
+
|
|
290
|
+
JAR="$(mktemp -t mobilems-cookies.XXXXXX)"
|
|
291
|
+
trap 'rm -f "$JAR"' EXIT
|
|
292
|
+
|
|
293
|
+
log "→ GET /admin/login (CSRF + session)"
|
|
294
|
+
LOGIN_HTML="$(curl --silent --show-error \
|
|
295
|
+
--cookie-jar "$JAR" \
|
|
296
|
+
"$LOGIN_URL")" || die "✗ Could not fetch $LOGIN_URL"
|
|
297
|
+
|
|
298
|
+
CSRF="$(extract_csrf "$LOGIN_HTML")"
|
|
299
|
+
|
|
300
|
+
log "→ POST /admin/login"
|
|
301
|
+
# We need the HTTP status of the POST without following the redirect.
|
|
302
|
+
LOGIN_POST_STATUS_BODY="$(curl --silent --show-error \
|
|
303
|
+
--output /dev/null \
|
|
304
|
+
--write-out '%{http_code} %{redirect_url}' \
|
|
305
|
+
--cookie-jar "$JAR" --cookie "$JAR" \
|
|
306
|
+
--data-urlencode "_username=${MOBILEMS_LOGIN}" \
|
|
307
|
+
--data-urlencode "_password=${MOBILEMS_PASSWORD}" \
|
|
308
|
+
--data-urlencode "_csrf_token=${CSRF}" \
|
|
309
|
+
--data-urlencode "_remember_me=on" \
|
|
310
|
+
-X POST \
|
|
311
|
+
"$LOGIN_URL")" || die "✗ POST $LOGIN_URL failed."
|
|
312
|
+
|
|
313
|
+
LOGIN_STATUS="${LOGIN_POST_STATUS_BODY%% *}"
|
|
314
|
+
LOGIN_REDIRECT="${LOGIN_POST_STATUS_BODY#* }"
|
|
315
|
+
|
|
316
|
+
if [[ "$LOGIN_STATUS" != "302" ]]; then
|
|
317
|
+
die "✗ Login failed: expected 302 redirect, got HTTP ${LOGIN_STATUS}. Check MOBILEMS_LOGIN and MOBILEMS_PASSWORD."
|
|
318
|
+
fi
|
|
319
|
+
if [[ "$LOGIN_REDIRECT" == *"/admin/login"* ]]; then
|
|
320
|
+
die "✗ Login failed: server redirected back to /admin/login. Credentials were likely rejected."
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
log "→ GET /docs/api"
|
|
324
|
+
DOCS_STATUS_FILE="$(mktemp -t mobilems-docs-status.XXXXXX)"
|
|
325
|
+
trap 'rm -f "$JAR" "$DOCS_STATUS_FILE"' EXIT
|
|
326
|
+
|
|
327
|
+
DOCS_HTML="$(curl --silent --show-error \
|
|
328
|
+
--write-out '%{http_code}' \
|
|
329
|
+
--cookie-jar "$JAR" --cookie "$JAR" \
|
|
330
|
+
--output - \
|
|
331
|
+
"$DOCS_URL" 2>/dev/null | tee >(tail -c 3 > "$DOCS_STATUS_FILE"))"
|
|
332
|
+
|
|
333
|
+
# Strip the trailing 3-char status code from the body
|
|
334
|
+
DOCS_STATUS="$(cat "$DOCS_STATUS_FILE")"
|
|
335
|
+
DOCS_HTML="${DOCS_HTML%$DOCS_STATUS}"
|
|
336
|
+
|
|
337
|
+
if [[ "$DOCS_STATUS" != "200" ]]; then
|
|
338
|
+
die "✗ Docs page returned HTTP ${DOCS_STATUS}. Session may not be authenticated."
|
|
339
|
+
fi
|
|
340
|
+
if [[ "$DOCS_HTML" == *"login-card-body"* ]]; then
|
|
341
|
+
die "✗ Docs page returned the login form — session not authenticated."
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
SPEC_JSON="$(extract_swagger_data "$DOCS_HTML")"
|
|
345
|
+
|
|
346
|
+
# Validate + pretty-print through jq.
|
|
347
|
+
if ! printf '%s' "$SPEC_JSON" | jq '.' > "${SPEC_PATH}.tmp"; then
|
|
348
|
+
rm -f "${SPEC_PATH}.tmp"
|
|
349
|
+
die "✗ Swagger JSON failed to parse."
|
|
350
|
+
fi
|
|
351
|
+
mv -f "${SPEC_PATH}.tmp" "$SPEC_PATH"
|
|
352
|
+
|
|
353
|
+
SPEC_TITLE="$(jq -r '.spec.info.title // .info.title // "unknown"' "$SPEC_PATH")"
|
|
354
|
+
SPEC_VERSION="$(jq -r '.spec.info.version // .info.version // "unknown"' "$SPEC_PATH")"
|
|
355
|
+
|
|
356
|
+
# Preserve cached sessionId when running outside Claude Code (manual/terminal)
|
|
357
|
+
# so a future in-session call still hits the cache. In-Claude-Code calls always
|
|
358
|
+
# overwrite with the current session id.
|
|
359
|
+
EFFECTIVE_SESSION_ID="$SESSION_ID"
|
|
360
|
+
if [[ -z "$EFFECTIVE_SESSION_ID" && -f "$META_PATH" ]]; then
|
|
361
|
+
EFFECTIVE_SESSION_ID="$(jq -r '.sessionId // ""' "$META_PATH" 2>/dev/null)"
|
|
362
|
+
fi
|
|
363
|
+
ISO_NOW="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
364
|
+
jq -n \
|
|
365
|
+
--arg sid "$EFFECTIVE_SESSION_ID" \
|
|
366
|
+
--arg ts "$ISO_NOW" \
|
|
367
|
+
'{sessionId: (if $sid == "" then null else $sid end), fetchedAt: $ts}' \
|
|
368
|
+
> "$META_PATH"
|
|
369
|
+
|
|
370
|
+
BYTES="$(wc -c < "$SPEC_PATH" | tr -d ' ')"
|
|
371
|
+
log "✓ Refreshed ${BYTES} bytes — ${SPEC_TITLE} ${SPEC_VERSION}"
|
|
372
|
+
log " $SPEC_PATH"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobilems-articles
|
|
3
|
+
description: Add an article (content) feature module to a MobilEMS app initialized with mobilems-project-init. The module is parametrized — you give it a NAME and a TEMPLATE value, and it builds an Article-backed list+detail module whose API requests are filtered by that template. Use whenever the user wants to add / scaffold / wire an articles, news (aktualności), education, or any template-filtered content module, or asks to "dodaj moduł artykułów / aktualności". One run builds one named module; run it again for each additional content type. Creates libs/museum-<name> (domain + shell/angular), registers its route, builds its article card shared components, and adds the articles npm packages. Requires the MobilEMS foundation to exist first.
|
|
4
|
+
user-invocable: true
|
|
5
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# MobilEMS article module
|
|
9
|
+
|
|
10
|
+
Build a **parametrized article module** on top of a MobilEMS foundation produced by
|
|
11
|
+
`mobilems-project-init`. An article module is an Article-backed list + detail feature whose API
|
|
12
|
+
requests carry a fixed `template` filter, so the same module shape powers any number of content
|
|
13
|
+
types — you choose the **name** and the **template value**. A project may have several article
|
|
14
|
+
modules under different names (e.g. one per content category), and the same skill builds each.
|
|
15
|
+
|
|
16
|
+
The module wraps `ArticlesSharedModule.forFeature` over the npm `Article` entity. The only thing that
|
|
17
|
+
distinguishes one article module from another is its name, its route, its `entity` key, the
|
|
18
|
+
`template` value it filters on, and whether it keeps feature-local ngrx state.
|
|
19
|
+
|
|
20
|
+
## Parameters
|
|
21
|
+
|
|
22
|
+
Collect these in Step 1 with `AskUserQuestion` (or accept them from the invocation if the user already
|
|
23
|
+
gave them). The first two are the essentials:
|
|
24
|
+
|
|
25
|
+
| Parameter | What it is | Example |
|
|
26
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
27
|
+
| **name** | the module name → folder `museum-<name>`, class `Museum<Name>Module`, lib alias `@<PREFIX>/museum-<name>` | `news` |
|
|
28
|
+
| **template** | the value sent in the API request filter `baseQuery: [{ key: 'template', value: '<template>', type: '=', hidden: true }]` | `AKTUALNOŚCI` |
|
|
29
|
+
| route | the URL path segment for the module's pages | `aktualnosci` |
|
|
30
|
+
| entity | the `forFeature` `entity` key (API entity + ngrx state key); often equals the name | `news` |
|
|
31
|
+
| feature state? | whether the module keeps its own ngrx state (adds a `reducerFactory`) | yes / no |
|
|
32
|
+
|
|
33
|
+
> The filter **key is always `template`** — only the **value** changes per module. Copy the file
|
|
34
|
+
> structure from any existing article module in the reference MobilEMS app the project was built from,
|
|
35
|
+
> adapting its name/route/entity/template; don't treat that app's particular modules as a fixed set to
|
|
36
|
+
> reproduce.
|
|
37
|
+
|
|
38
|
+
## Precondition
|
|
39
|
+
|
|
40
|
+
Run `scripts/detect-init.sh <workspace-root>`. It confirms the MobilEMS foundation is present
|
|
41
|
+
(`SharedModule.forRoot` in `app.config.ts`, a populated shared-lib barrel). If not, tell the user to
|
|
42
|
+
run `/mobilems:project-init` first. Hold `<PREFIX>` (from `tsconfig.base.json`; reference uses `@msr`)
|
|
43
|
+
and the reference repo path (same one init used).
|
|
44
|
+
|
|
45
|
+
## Steps
|
|
46
|
+
|
|
47
|
+
1. **Gather the parameters** above. Ask for the **name** and **template** at minimum; default `route`
|
|
48
|
+
and `entity` to the name unless the user specifies otherwise; ask whether the module needs feature
|
|
49
|
+
state.
|
|
50
|
+
2. **npm deps** — add `@smartsoft001-mobilems/articles-domain`, `@smartsoft001-mobilems/articles-shell-angular`,
|
|
51
|
+
`@smartsoft001-mobilems/articles-shell-dtos` (match the installed mobilems line). Every article
|
|
52
|
+
module shares these three — if a previous article module already added them, skip. Resolve versions
|
|
53
|
+
at run time; do not `npm install` unless asked. (`@thisissoon/angular-masonry` is already a foundation dep.)
|
|
54
|
+
Also add any **extra third-party packages the copied pages import** that aren't already in the
|
|
55
|
+
workspace — e.g. the reference list page uses `lodash-decorators` (`@debounce`); grep the pages you
|
|
56
|
+
copy for non-`@angular`/`@smartsoft001` imports and add the missing ones.
|
|
57
|
+
3. **Library** — create `libs/museum-<name>/{domain,shell/angular}` per `references/lib-contents.md`:
|
|
58
|
+
the thin domain entity (`Museum<Name> extends Article`), the shell (`Museum<Name>Module`, routes,
|
|
59
|
+
`pages/{list,item}`, services, and — if the module keeps feature state — `+state/<name>.reducer.ts`),
|
|
60
|
+
threading `<PREFIX>` and the chosen name/entity. Add the two `tsconfig.base.json` paths
|
|
61
|
+
(`@<PREFIX>/museum-<name>/domain` + `/shell/angular`).
|
|
62
|
+
4. **Module + route** — see `references/module-and-routes.md`: `Museum<Name>Module` wraps
|
|
63
|
+
`ArticlesSharedModule.forFeature` with `type: Article`, the chosen `entity`, and
|
|
64
|
+
`baseQuery: [{ key: 'template', value: '<template>', type: '=', hidden: true }]`, plus the `Masonry`
|
|
65
|
+
SSR factory. Add the lazy `<route>` route to `appRoutes` in `apps/web/src/app/app.routes.ts`, and a
|
|
66
|
+
matching child under the `wyszukaj/:text` search route if the module's results belong in site search.
|
|
67
|
+
Also build the app's **`/article-preview` page** if it isn't there yet (it previews an `Article`, so
|
|
68
|
+
it belongs to the articles feature, not the foundation) — idempotent across runs; see
|
|
69
|
+
`references/module-and-routes.md`.
|
|
70
|
+
5. **Article card shared components** — see `references/shared-components.md`: build the module's grid
|
|
71
|
+
and list cards (`<name>-grid-item`, `<name>-list-item`) in `libs/shared/angular` and export them; if
|
|
72
|
+
the module renders article-gallery content blocks, also build the article gallery widget and register
|
|
73
|
+
it in the widget content-type map (build once, idempotent across article modules).
|
|
74
|
+
6. **Verify** — run `scripts/verify-module.sh <workspace-root> <PREFIX> <name> [template]`: asserts the
|
|
75
|
+
library exists, the `forFeature` carries the chosen `entity` (and template, if given), the route is
|
|
76
|
+
registered, and the article card shared components are built and exported. Fix and re-run.
|
|
77
|
+
|
|
78
|
+
## Notes
|
|
79
|
+
|
|
80
|
+
- One run builds one named article module. Run the skill again — with a different name + template — for
|
|
81
|
+
each additional content type the project needs.
|
|
82
|
+
- Article modules reuse the foundation's generic `IArticle` model and the foundation's news carousel —
|
|
83
|
+
this skill does not rebuild them.
|
|
84
|
+
- Bundled `references/` + `scripts/` ship automatically. Do not hand-edit `plugin.json`.
|