@smartsoft001-mobilems/claude-plugins 2.86.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/package.json +1 -1
- package/plugins/mobilems/.claude-plugin/plugin.json +1 -1
- 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-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
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""classify-shared-components.py <shared-lib components dir>
|
|
3
|
+
|
|
4
|
+
Split a MobilEMS shared-lib `components` tree into FOUNDATION shared components (mobilems-project-init
|
|
5
|
+
builds these) and FEATURE-OWNED shared components (built by the owning mobilems-<module> skill,
|
|
6
|
+
because they depend on a feature package).
|
|
7
|
+
|
|
8
|
+
A "component" is a directory holding a non-spec *.component.ts. It is FEATURE-OWNED when it:
|
|
9
|
+
1. imports a feature package (objects/articles/public-collections/news/partners domain|shell,
|
|
10
|
+
or a @.../museum-<x> subpath), OR
|
|
11
|
+
2. imports another FEATURE-OWNED component — by relative path or by that component's exported
|
|
12
|
+
symbol (transitive, to a fixpoint).
|
|
13
|
+
|
|
14
|
+
Trust this over any hand-maintained table: if the reference repo diverges, this is authoritative.
|
|
15
|
+
Exit 0 on success; prints two sections (FEATURE-OWNED, FOUNDATION), one path per line, relative to <dir>.
|
|
16
|
+
"""
|
|
17
|
+
import os
|
|
18
|
+
import re
|
|
19
|
+
import sys
|
|
20
|
+
|
|
21
|
+
FEATURE_RE = re.compile(
|
|
22
|
+
r"(objects|articles|public-collections|news|partners)-(domain|shell-angular|shell-dtos)"
|
|
23
|
+
r"|/museum-[a-z-]+"
|
|
24
|
+
)
|
|
25
|
+
EXPORT_RE = re.compile(r"export\s+(?:class|const|interface|type)\s+([A-Za-z0-9_]+)")
|
|
26
|
+
IMPORT_LINE_RE = re.compile(r"^\s*import\b|from\s+['\"]")
|
|
27
|
+
REL_IMPORT_RE = re.compile(r"from\s+['\"](\.\.?/[^'\"]+)['\"]")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def unit_ts_files(unit):
|
|
31
|
+
return [
|
|
32
|
+
os.path.join(unit, f)
|
|
33
|
+
for f in os.listdir(unit)
|
|
34
|
+
if f.endswith(".ts") and not f.endswith(".spec.ts")
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def read(files):
|
|
39
|
+
out = []
|
|
40
|
+
for f in files:
|
|
41
|
+
try:
|
|
42
|
+
with open(f, encoding="utf-8") as fh:
|
|
43
|
+
out.append(fh.read())
|
|
44
|
+
except OSError:
|
|
45
|
+
pass
|
|
46
|
+
return "\n".join(out)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def main():
|
|
50
|
+
if len(sys.argv) != 2:
|
|
51
|
+
sys.exit("usage: classify-shared-components.py <shared-lib/src/lib/components>")
|
|
52
|
+
root = os.path.abspath(sys.argv[1])
|
|
53
|
+
if not os.path.isdir(root):
|
|
54
|
+
sys.exit(f"ERROR: not a directory: {root}")
|
|
55
|
+
|
|
56
|
+
# discover units (dirs with a non-spec *.component.ts)
|
|
57
|
+
units = sorted(
|
|
58
|
+
{
|
|
59
|
+
dirpath
|
|
60
|
+
for dirpath, _, files in os.walk(root)
|
|
61
|
+
if any(f.endswith(".component.ts") and not f.endswith(".spec.ts") for f in files)
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
text = {u: read(unit_ts_files(u)) for u in units}
|
|
66
|
+
imports = {u: "\n".join(l for l in text[u].splitlines() if IMPORT_LINE_RE.search(l)) for u in units}
|
|
67
|
+
exports = {
|
|
68
|
+
u: set(EXPORT_RE.findall(text[u])) for u in units
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
feature_owned = {u for u in units if FEATURE_RE.search(imports[u])}
|
|
72
|
+
|
|
73
|
+
changed = True
|
|
74
|
+
while changed:
|
|
75
|
+
changed = False
|
|
76
|
+
feature_owned_symbols = {}
|
|
77
|
+
for d in feature_owned:
|
|
78
|
+
for s in exports[d]:
|
|
79
|
+
feature_owned_symbols.setdefault(s, d)
|
|
80
|
+
for u in units:
|
|
81
|
+
if u in feature_owned:
|
|
82
|
+
continue
|
|
83
|
+
hit = False
|
|
84
|
+
# (a) relative import into a feature_owned unit's directory
|
|
85
|
+
for rel in REL_IMPORT_RE.findall(imports[u]):
|
|
86
|
+
target = os.path.normpath(os.path.join(u, rel))
|
|
87
|
+
if any(target == d or target.startswith(d + os.sep) for d in feature_owned):
|
|
88
|
+
hit = True
|
|
89
|
+
break
|
|
90
|
+
# (b) imports a symbol exported by a feature_owned unit
|
|
91
|
+
if not hit:
|
|
92
|
+
for s in feature_owned_symbols:
|
|
93
|
+
if re.search(r"\b" + re.escape(s) + r"\b", imports[u]):
|
|
94
|
+
hit = True
|
|
95
|
+
break
|
|
96
|
+
if hit:
|
|
97
|
+
feature_owned.add(u)
|
|
98
|
+
changed = True
|
|
99
|
+
|
|
100
|
+
def rel(u):
|
|
101
|
+
return os.path.relpath(u, root)
|
|
102
|
+
|
|
103
|
+
print("FEATURE-OWNED:")
|
|
104
|
+
for u in units:
|
|
105
|
+
if u in feature_owned:
|
|
106
|
+
print(" " + rel(u))
|
|
107
|
+
print("FOUNDATION:")
|
|
108
|
+
for u in units:
|
|
109
|
+
if u not in feature_owned:
|
|
110
|
+
print(" " + rel(u))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if __name__ == "__main__":
|
|
114
|
+
main()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# detect-base.sh <workspace-root>
|
|
4
|
+
#
|
|
5
|
+
# Precondition gate for mobilems-project-init. Confirms the target is a scaffold-nx-workspace BASE
|
|
6
|
+
# (generic Nx + Angular-SSR shell) that has NOT yet had the MobilEMS delta applied. Portable to the
|
|
7
|
+
# macOS system bash (3.2) — no bash-4 features.
|
|
8
|
+
#
|
|
9
|
+
# Exit 0 → base detected, OK to apply the delta.
|
|
10
|
+
# Exit 3 → no base shell found (tell the user to run /smart:scaffold-nx-workspace first).
|
|
11
|
+
# Exit 4 → MobilEMS delta already present (init looks already applied).
|
|
12
|
+
set -eu
|
|
13
|
+
|
|
14
|
+
ROOT="${1:?usage: detect-base.sh <workspace-root>}"
|
|
15
|
+
cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
|
|
16
|
+
|
|
17
|
+
fail_no_base() {
|
|
18
|
+
echo "NOT A BASE: $1" >&2
|
|
19
|
+
echo "Run /smart:scaffold-nx-workspace first to create the generic Nx + Angular-SSR shell." >&2
|
|
20
|
+
exit 3
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# --- base shell signals ---
|
|
24
|
+
[ -f apps/web/src/server.ts ] || fail_no_base "apps/web/src/server.ts missing"
|
|
25
|
+
[ -f apps/web/src/app/app.config.ts ] || fail_no_base "apps/web/src/app/app.config.ts missing"
|
|
26
|
+
[ -f apps/web/src/app/app.routes.ts ] || fail_no_base "apps/web/src/app/app.routes.ts missing"
|
|
27
|
+
[ -f libs/shared/angular/src/index.ts ] || fail_no_base "libs/shared/angular/src/index.ts missing"
|
|
28
|
+
[ -f tsconfig.base.json ] || fail_no_base "tsconfig.base.json missing"
|
|
29
|
+
|
|
30
|
+
# base app.routes.ts has no feature loadChildren yet
|
|
31
|
+
if grep -qE "loadChildren" apps/web/src/app/app.routes.ts; then
|
|
32
|
+
echo "WARNING: app.routes.ts already has loadChildren — base may already be extended." >&2
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# --- already-applied signals (any one → likely already MobilEMS) ---
|
|
36
|
+
applied=0
|
|
37
|
+
[ -f tailwind.config.js ] && grep -q "smart-" tailwind.config.js 2>/dev/null && applied=1
|
|
38
|
+
grep -q "@smartsoft001-mobilems/angular" package.json 2>/dev/null && applied=1
|
|
39
|
+
[ -d libs/museum-objects ] && applied=1
|
|
40
|
+
if [ "$applied" = 1 ]; then
|
|
41
|
+
echo "ALREADY APPLIED: MobilEMS signals found (tailwind smart- prefix / mobilems dep / libs/museum-*)." >&2
|
|
42
|
+
echo "If you meant to re-run, revert the delta first." >&2
|
|
43
|
+
exit 4
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# --- report the detected prefix (from the single tsconfig path) ---
|
|
47
|
+
PREFIX="$(grep -oE '@[a-z0-9-]+/angular' tsconfig.base.json | head -1 | sed -E 's#@([a-z0-9-]+)/angular#\1#')"
|
|
48
|
+
echo "BASE OK. Detected prefix: ${PREFIX:-<unknown — inspect tsconfig.base.json paths>}"
|
|
49
|
+
exit 0
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# verify-init.sh <workspace-root> <PREFIX>
|
|
4
|
+
#
|
|
5
|
+
# Post-condition check for mobilems-project-init. Asserts the MobilEMS delta landed AND the hard
|
|
6
|
+
# foundation is self-contained (no feature modules / no feature routes / shared lib imports no
|
|
7
|
+
# feature package).
|
|
8
|
+
# Portable to macOS system bash (3.2). Exit 0 = all pass; exit 1 = one or more checks failed.
|
|
9
|
+
set -eu
|
|
10
|
+
|
|
11
|
+
ROOT="${1:?usage: verify-init.sh <workspace-root> <PREFIX>}"
|
|
12
|
+
PREFIX="${2:?usage: verify-init.sh <workspace-root> <PREFIX>}"
|
|
13
|
+
cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
|
|
14
|
+
|
|
15
|
+
fail=0
|
|
16
|
+
pass() { echo " PASS: $1"; }
|
|
17
|
+
bad() { echo " FAIL: $1" >&2; fail=1; }
|
|
18
|
+
|
|
19
|
+
echo "== Delta applied =="
|
|
20
|
+
[ -f tailwind.config.js ] && grep -q "prefix: 'smart-'" tailwind.config.js && pass "tailwind smart- prefix" || bad "tailwind.config.js with smart- prefix"
|
|
21
|
+
grep -q "@smartsoft001-mobilems/angular" package.json && pass "mobilems framework dep" || bad "@smartsoft001-mobilems/angular in package.json"
|
|
22
|
+
grep -q "@ngrx/store" package.json && pass "ngrx dep" || bad "@ngrx/store in package.json"
|
|
23
|
+
grep -q "SharedModule.forRoot" apps/web/src/app/app.config.ts && pass "SharedModule.forRoot in app.config" || bad "SharedModule.forRoot in app.config.ts"
|
|
24
|
+
grep -q "SEARCH_CONFIG_TOKEN" apps/web/src/app/app.config.ts && pass "SEARCH_CONFIG_TOKEN" || bad "SEARCH_CONFIG_TOKEN in app.config.ts"
|
|
25
|
+
grep -q "multimediaUrl" apps/web/src/server.ts && pass "multimediaUrl in server.ts" || bad "multimediaUrl in server.ts"
|
|
26
|
+
grep -q "/api/translations" apps/web/src/server.ts && pass "/api/translations endpoint" || bad "/api/translations in server.ts"
|
|
27
|
+
grep -q "./lib/components" libs/shared/angular/src/index.ts && pass "shared-lib components barrel populated" || bad "components barrel in shared-lib index.ts"
|
|
28
|
+
[ -f .claude/settings.json ] && grep -q "flow@mobilems" .claude/settings.json && pass "flow@mobilems enabled" || bad "flow@mobilems in .claude/settings.json"
|
|
29
|
+
|
|
30
|
+
echo "== Foundation scope (no feature modules yet) =="
|
|
31
|
+
if ls -d libs/museum-* >/dev/null 2>&1; then bad "libs/museum-* present (feature modules are built by the module skills)"; else pass "no libs/museum-*"; fi
|
|
32
|
+
# feature routes reference a museum-* lib; loadChildren + the import often span lines, so match museum- anywhere
|
|
33
|
+
if grep -qE "museum-" apps/web/src/app/app.routes.ts; then bad "feature route (museum-*) in app.routes.ts"; else pass "no feature routes"; fi
|
|
34
|
+
|
|
35
|
+
echo "== Foundation shared library is self-contained =="
|
|
36
|
+
COMP=libs/shared/angular/src/lib/components
|
|
37
|
+
# the widget container registers only foundation widgets (feature gallery widgets are added by module skills)
|
|
38
|
+
WID="$COMP/widget/widget.component.ts"
|
|
39
|
+
if [ -f "$WID" ]; then
|
|
40
|
+
if grep -qE "WidgetGalleryObjectComponent|WidgetGalleryArticleComponent" "$WID"; then
|
|
41
|
+
bad "widget container references a feature gallery widget — build it with foundation widgets only"
|
|
42
|
+
else
|
|
43
|
+
pass "widget container has foundation widgets only"
|
|
44
|
+
fi
|
|
45
|
+
else
|
|
46
|
+
bad "widget container missing"
|
|
47
|
+
fi
|
|
48
|
+
# objects.model holds only the foundation model types (the object-specific ISpecificObject is feature code)
|
|
49
|
+
OBJMODEL=libs/shared/angular/src/lib/models/objects.model.ts
|
|
50
|
+
if [ -f "$OBJMODEL" ]; then
|
|
51
|
+
grep -qE "from '[^']*objects-domain'" "$OBJMODEL" && bad "objects.model imports MsObject — foundation holds only the generic types" || pass "objects.model holds foundation types only"
|
|
52
|
+
grep -qE "AdvancedFilterType|KeyValue" "$OBJMODEL" && pass "foundation model types present" || bad "foundation model types missing from objects.model.ts"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
echo "== Build-safety invariant: shared lib imports no feature package =="
|
|
56
|
+
LEAK="$(grep -rlnE "from '@[^']*/(objects|articles|public-collections)-(domain|shell-angular|shell-dtos)'" libs/shared/angular/src 2>/dev/null || true)"
|
|
57
|
+
if [ -n "$LEAK" ]; then
|
|
58
|
+
bad "shared lib still imports a feature package — foundation will not build without it:"
|
|
59
|
+
printf ' %s\n' $LEAK >&2
|
|
60
|
+
else
|
|
61
|
+
pass "shared lib imports no feature package"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
echo "== Prefix threaded =="
|
|
65
|
+
if grep -rq "@msr/" libs/shared/angular/src apps/web/src 2>/dev/null && [ "$PREFIX" != "msr" ]; then
|
|
66
|
+
bad "stray @msr/ imports (prefix not fully threaded to @$PREFIX/)"
|
|
67
|
+
else
|
|
68
|
+
pass "no stray reference-prefix imports"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
echo
|
|
72
|
+
if [ "$fail" = 0 ]; then echo "VERIFY: all checks passed."; else echo "VERIFY: FAILED — fix the items above and re-run." >&2; fi
|
|
73
|
+
exit "$fail"
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobilems-thematic-publications
|
|
3
|
+
description: Add the museum THEMATIC PATHS / PUBLICATIONS feature module (ścieżki tematyczne) to a MobilEMS app initialized with mobilems-project-init. Use whenever the user wants to add / scaffold / wire the thematic paths / thematic publications module, the "ścieżki tematyczne" pages (list + paged publication reader with widgets), or asks to "dodaj moduł ścieżek tematycznych / publikacji tematycznych". Creates libs/museum-thematic-paths (domain + shell/angular), registers the /sciezki-tematyczne route, and adds the Articles npm packages it reuses. 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 thematic paths / publications module
|
|
9
|
+
|
|
10
|
+
Add the **thematic paths / publications** (ścieżki tematyczne) feature module on top of a MobilEMS
|
|
11
|
+
foundation produced by `mobilems-project-init`. This module's entire UI lives inside its own
|
|
12
|
+
`libs/museum-thematic-paths` library, so this skill builds that library and registers a single
|
|
13
|
+
top-level route.
|
|
14
|
+
|
|
15
|
+
> **Naming heads-up.** This skill is named _thematic-publications_ (the museum-domain term users say),
|
|
16
|
+
> but the artifact it generates is **thematic-paths**: folder `libs/museum-thematic-paths`, class
|
|
17
|
+
> `MuseumThematicPathsModule`, route `sciezki-tematyczne`, entity `'thematicPaths'`. Always emit the
|
|
18
|
+
> _thematic-paths_ names — "publications" is only the spoken alias.
|
|
19
|
+
|
|
20
|
+
The module is a list/detail feature where each entry is a multi-page publication: a `ListComponent`
|
|
21
|
+
of thematic paths plus an `ItemComponent` that renders a paged reader (intro, menu, page, widgets —
|
|
22
|
+
page-header, text, image, video, audio, image-gallery) backed by `ArticlesSharedModule.forFeature`
|
|
23
|
+
over the `MuseumThematicPath` entity. It REUSES the Articles shared module (like news) but with its
|
|
24
|
+
OWN domain entity, its OWN reducer (`getReducer`), and **no `baseQuery`**.
|
|
25
|
+
|
|
26
|
+
## Precondition
|
|
27
|
+
|
|
28
|
+
Run `scripts/detect-init.sh <workspace-root>`. It confirms the MobilEMS foundation is present
|
|
29
|
+
(`SharedModule.forRoot` in `app.config.ts`, a populated shared-lib barrel). If not, tell the user to
|
|
30
|
+
run `/mobilems:project-init` first. Hold `<PREFIX>` (from `tsconfig.base.json`; reference uses
|
|
31
|
+
`@msr`) and the reference repo path (same one init used).
|
|
32
|
+
|
|
33
|
+
## Steps
|
|
34
|
+
|
|
35
|
+
1. **npm deps** — add `@smartsoft001-mobilems/articles-domain`,
|
|
36
|
+
`@smartsoft001-mobilems/articles-shell-angular`, `@smartsoft001-mobilems/articles-shell-dtos`
|
|
37
|
+
(this module reuses the Articles shared module — `ArticlesSharedModule` + `ArticlesService`).
|
|
38
|
+
Match the installed mobilems line; resolve versions at run time; do not `npm install` unless
|
|
39
|
+
asked. Adding is idempotent — if `mobilems-articles` already installed these, nothing changes.
|
|
40
|
+
2. **Library** — create `libs/museum-thematic-paths/{domain,shell/angular}` per
|
|
41
|
+
`references/lib-contents.md`: copy the domain entity/interfaces/enums and the shell
|
|
42
|
+
(`MuseumThematicPathsModule`, routes, `+state/*`, `components/*`, `pages/{list,item}`, `services`,
|
|
43
|
+
`directives`), thread `<PREFIX>`. Add the two `tsconfig.base.json` paths and the
|
|
44
|
+
`museum-thematic-paths` commit scope.
|
|
45
|
+
3. **Module + routes** — see `references/module-and-routes.md`: `MuseumThematicPathsModule` wraps
|
|
46
|
+
`ArticlesSharedModule.forFeature({ routing: false, config: { reducerFactory: getReducer, type: MuseumThematicPath, apiUrl, entity: 'thematicPaths' } })`
|
|
47
|
+
(note: **no baseQuery**) with the `Masonry` SSR factory and provides `ThematicPathsFacade` +
|
|
48
|
+
`SERVICES`. Add the lazy `sciezki-tematyczne` route to the `appRoutes` array in
|
|
49
|
+
`apps/web/src/app/app.routes.ts` as a single top-level route.
|
|
50
|
+
4. **Verify** — run `scripts/verify-module.sh <workspace-root> <PREFIX>`: asserts the lib + entity
|
|
51
|
+
exist, the tsconfig path is added, `ArticlesSharedModule.forFeature` is wired with
|
|
52
|
+
`entity: 'thematicPaths'` + `MuseumThematicPath` + `reducerFactory`, `ThematicPathsFacade` is
|
|
53
|
+
provided, the `+state` files are present, the `sciezki-tematyczne` route is registered as a single
|
|
54
|
+
top-level route, and the three Articles deps are in `package.json`. Fix and re-run.
|
|
55
|
+
|
|
56
|
+
## Notes
|
|
57
|
+
|
|
58
|
+
- This skill ONLY touches the thematic-paths module + its route. It never adds other feature modules,
|
|
59
|
+
never re-runs the foundation, and never edits `libs/shared/angular`.
|
|
60
|
+
- Bundled `references/` + `scripts/` ship automatically. Do not hand-edit `plugin.json`.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# libs/museum-thematic-paths — structure to create
|
|
2
|
+
|
|
3
|
+
Copy from the reference repo's `libs/museum-thematic-paths` and thread `<PREFIX>`. The lib has two
|
|
4
|
+
projects: a `domain` (entity/interfaces/enums) and a `shell/angular` (the Angular module + NgRx
|
|
5
|
+
`+state` + UI).
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
libs/museum-thematic-paths/
|
|
9
|
+
├── domain/ # project: museum-thematic-paths-domain
|
|
10
|
+
│ ├── package.json # "name": "museum-thematic-paths-domain"
|
|
11
|
+
│ └── src/
|
|
12
|
+
│ ├── index.ts # export * from './lib/entities'; './lib/enums'; './lib/interfaces';
|
|
13
|
+
│ ├── features.ts # export const DOMAIN_SERVICES = [];
|
|
14
|
+
│ └── lib/
|
|
15
|
+
│ ├── entities/ # MuseumThematicPath (+ index)
|
|
16
|
+
│ ├── enums/ # WidgetType enum (+ index)
|
|
17
|
+
│ └── interfaces.ts # IThematicPath, IPage, IMenu, IImageFile, ICopyright, IDictionaryEntity, …
|
|
18
|
+
└── shell/angular/ # project: museum-thematic-paths-shell-angular
|
|
19
|
+
└── src/
|
|
20
|
+
├── index.ts # export * from './lib/pages'; export * from './lib/thematic-paths.module';
|
|
21
|
+
└── lib/
|
|
22
|
+
├── thematic-paths.module.ts # MuseumThematicPathsModule (references/module-and-routes.md)
|
|
23
|
+
├── thematic-paths.routes.ts
|
|
24
|
+
├── +state/ # thematic-paths.facade.ts (ThematicPathsFacade), thematic-paths.reducer.ts (getReducer), thematic-paths.selectors.ts
|
|
25
|
+
├── components/ # intro, main, menu, page, show-widgets, list-item, filters,
|
|
26
|
+
│ # widgets/{page-header,text,image,video,audio,image-gallery/*} (+ index)
|
|
27
|
+
├── directives/ # scroll-intersection.directive.ts (+ .spec)
|
|
28
|
+
├── pages/ # list (ListComponent), item (ItemComponent) + index
|
|
29
|
+
└── services/ # thematic-paths.service.ts + index (SERVICES)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
> There is **no `src/__mocks__/` dir** in this lib (objects had one; thematic-paths does not). Copy
|
|
33
|
+
> only what the reference has.
|
|
34
|
+
|
|
35
|
+
## Domain entity (verbatim — thread nothing; pure types)
|
|
36
|
+
|
|
37
|
+
Unlike objects' `MuseumObject extends MsObject`, this entity `implements` the local interfaces — it
|
|
38
|
+
does NOT extend a feature base class:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { IEntity } from '@smartsoft001/domain-core';
|
|
42
|
+
import { Field, Model } from '@smartsoft001/models';
|
|
43
|
+
|
|
44
|
+
import {
|
|
45
|
+
ICopyright,
|
|
46
|
+
IDictionaryEntity,
|
|
47
|
+
IImageFile,
|
|
48
|
+
IMenu,
|
|
49
|
+
IThematicPath,
|
|
50
|
+
} from '../interfaces';
|
|
51
|
+
|
|
52
|
+
@Model({})
|
|
53
|
+
export class MuseumThematicPath implements IEntity<any>, IThematicPath {
|
|
54
|
+
id!: any;
|
|
55
|
+
|
|
56
|
+
@Field() title!: string;
|
|
57
|
+
@Field() textColor!: string;
|
|
58
|
+
@Field() subTitle!: string;
|
|
59
|
+
@Field() shortDescription!: string;
|
|
60
|
+
@Field() author!: string;
|
|
61
|
+
@Field() backgroundColor!: string;
|
|
62
|
+
@Field() backgroundColorEnabled!: boolean;
|
|
63
|
+
@Field() backgroundImage!: IImageFile | null;
|
|
64
|
+
@Field() copyright!: ICopyright;
|
|
65
|
+
@Field() cycles!: IDictionaryEntity[];
|
|
66
|
+
@Field() image?: IImageFile;
|
|
67
|
+
@Field() keywords!: IDictionaryEntity[];
|
|
68
|
+
@Field() landingPageEnabled!: boolean;
|
|
69
|
+
@Field() menuBackgroundColor!: string;
|
|
70
|
+
@Field() menuBackgroundImage!: string;
|
|
71
|
+
@Field() menuType!: 'vertical' | 'horizontal';
|
|
72
|
+
@Field() publicationDate!: string;
|
|
73
|
+
@Field() sections!: IMenu[];
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Copy `domain/src/lib/interfaces.ts` verbatim (defines `IThematicPath`, `IPage`, `IMenu`, `IImageFile`,
|
|
78
|
+
`ICopyright`, `IDictionaryEntity`, and the page/widget shapes the reducer + components consume) and
|
|
79
|
+
`domain/src/lib/enums/index.ts` (`WidgetType`).
|
|
80
|
+
|
|
81
|
+
## Shell `+state` (NgRx — copy verbatim, thread `<PREFIX>`)
|
|
82
|
+
|
|
83
|
+
- `thematic-paths.reducer.ts` exports `getReducer()` — wraps `@smartsoft001/crud-shell-angular`'s
|
|
84
|
+
`getReducer('thematicPaths')` and adds thematic-specific cases (page loading, page desc, menu
|
|
85
|
+
display, widget id, etc.). This is the function passed as `reducerFactory` in the module config.
|
|
86
|
+
- `thematic-paths.facade.ts` exports `ThematicPathsFacade extends CrudFacade<MuseumThematicPath>`
|
|
87
|
+
with the paged-reader actions (`loadPage`, `loadPageDesc`, `setPage`, `setWidget`,
|
|
88
|
+
`setMenuDisplay`, `openPageDesc`) and signal accessors.
|
|
89
|
+
- `thematic-paths.selectors.ts` — the `getThematic*` selectors the facade reads.
|
|
90
|
+
|
|
91
|
+
## Services — `services/index.ts` exports a `SERVICES` array (copy verbatim)
|
|
92
|
+
|
|
93
|
+
The service extends `CrudBaseService` and is bound to BOTH `CrudService` and `ArticlesService` (the
|
|
94
|
+
reused Articles shared module resolves `ArticlesService`):
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { CrudService } from '@smartsoft001/crud-shell-angular';
|
|
98
|
+
import { ArticlesService } from '@smartsoft001-mobilems/articles-shell-angular';
|
|
99
|
+
|
|
100
|
+
import { ThematicPathsService } from './thematic-paths.service';
|
|
101
|
+
|
|
102
|
+
export * from './thematic-paths.service';
|
|
103
|
+
|
|
104
|
+
export const SERVICES = [
|
|
105
|
+
ThematicPathsService,
|
|
106
|
+
{ provide: CrudService, useClass: ThematicPathsService },
|
|
107
|
+
{ provide: ArticlesService, useClass: ThematicPathsService },
|
|
108
|
+
];
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`ThematicPathsService extends CrudBaseService<MuseumThematicPath>` (from
|
|
112
|
+
`@smartsoft001-mobilems/angular`) and adds `getPage`/`getPageDesc` for the paged reader.
|
|
113
|
+
|
|
114
|
+
## Wiring
|
|
115
|
+
|
|
116
|
+
- **tsconfig.base.json paths** (add both):
|
|
117
|
+
```json
|
|
118
|
+
"@<PREFIX>/museum-thematic-paths/domain": ["libs/museum-thematic-paths/domain/src/index.ts"],
|
|
119
|
+
"@<PREFIX>/museum-thematic-paths/shell/angular": ["libs/museum-thematic-paths/shell/angular/src/index.ts"]
|
|
120
|
+
```
|
|
121
|
+
- **project.json / build config** — copy each project's config (names `museum-thematic-paths-domain`,
|
|
122
|
+
`museum-thematic-paths-shell-angular`) and normalize every path field the reference baked to its
|
|
123
|
+
origin location — `sourceRoot`, `dest`, `outputPath`, `coverageDirectory`, `jestConfig`,
|
|
124
|
+
`lintFilePatterns`, and the jest `displayName` — to `libs/museum-thematic-paths/...`. Some reference modules carry stale
|
|
125
|
+
values (e.g. a `sourceRoot` missing the `shell/angular` segment, or a `coverageDirectory` under
|
|
126
|
+
`packages/...`) while others are already correct — verify each against a known-good sibling and fix
|
|
127
|
+
only the stale ones. A `domain` with no `project.json` (Nx-inferred) is fine — just set its
|
|
128
|
+
`package.json` `name`.
|
|
129
|
+
- **commit scope** — `commitlint.config.js` reads `libs/` dir names, so `museum-thematic-paths`
|
|
130
|
+
becomes a valid scope automatically; no edit needed.
|
|
131
|
+
|
|
132
|
+
This module reuses the Articles shared module, so it needs the three `@smartsoft001-mobilems/articles-*`
|
|
133
|
+
npm packages (see SKILL.md step 1). It does NOT need `online-3d-viewer`; `leaflet`/`openseadragon`/
|
|
134
|
+
`swiper` are foundation deps used by the gallery widgets if present.
|
package/plugins/mobilems/skills/mobilems-thematic-publications/references/module-and-routes.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# MuseumThematicPathsModule + route registration
|
|
2
|
+
|
|
3
|
+
## `libs/museum-thematic-paths/shell/angular/src/lib/thematic-paths.module.ts`
|
|
4
|
+
|
|
5
|
+
Thread `<PREFIX>` (the `environment` + domain imports). This module REUSES `ArticlesSharedModule`
|
|
6
|
+
(the same shared module the news/articles modules use) but configures it over its OWN
|
|
7
|
+
`MuseumThematicPath` entity with its OWN `getReducer` and **no `baseQuery`**. The `Masonry` factory
|
|
8
|
+
returns the real library in the browser and a no-op mock during SSR (identical to objects).
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { NgModule } from '@angular/core';
|
|
12
|
+
import { FormsModule } from '@angular/forms';
|
|
13
|
+
import { RouterModule } from '@angular/router';
|
|
14
|
+
import { SharedModule as SmartSharedModule } from '@smartsoft001/angular';
|
|
15
|
+
import { ArticlesSharedModule } from '@smartsoft001-mobilems/articles-shell-angular';
|
|
16
|
+
import { Masonry } from '@thisissoon/angular-masonry';
|
|
17
|
+
|
|
18
|
+
import { environment } from '@<PREFIX>/angular';
|
|
19
|
+
import { MuseumThematicPath } from '@<PREFIX>/museum-thematic-paths/domain';
|
|
20
|
+
|
|
21
|
+
import { ThematicPathsFacade } from './+state/thematic-paths.facade';
|
|
22
|
+
import { getReducer } from './+state/thematic-paths.reducer';
|
|
23
|
+
import { SERVICES } from './services';
|
|
24
|
+
import { routes } from './thematic-paths.routes';
|
|
25
|
+
|
|
26
|
+
@NgModule({
|
|
27
|
+
providers: [
|
|
28
|
+
ThematicPathsFacade,
|
|
29
|
+
...SERVICES,
|
|
30
|
+
{
|
|
31
|
+
provide: Masonry,
|
|
32
|
+
useFactory: () => {
|
|
33
|
+
if (typeof window !== 'undefined' && (window as any)['Masonry']) {
|
|
34
|
+
return (window as any)['Masonry'];
|
|
35
|
+
}
|
|
36
|
+
// Return a mock for SSR
|
|
37
|
+
return class {
|
|
38
|
+
constructor() {
|
|
39
|
+
// no-op
|
|
40
|
+
}
|
|
41
|
+
layout() {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
reloadItems() {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
destroy() {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
imports: [
|
|
55
|
+
FormsModule,
|
|
56
|
+
SmartSharedModule,
|
|
57
|
+
ArticlesSharedModule.forFeature({
|
|
58
|
+
routing: false,
|
|
59
|
+
config: {
|
|
60
|
+
reducerFactory: getReducer,
|
|
61
|
+
type: MuseumThematicPath,
|
|
62
|
+
apiUrl: environment.apiUrl,
|
|
63
|
+
entity: 'thematicPaths',
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
RouterModule.forChild(routes),
|
|
67
|
+
],
|
|
68
|
+
})
|
|
69
|
+
export class MuseumThematicPathsModule {}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
> Contrast with `mobilems-objects` (`ObjectsSharedModule.forFeature` over `MsObject`, no
|
|
73
|
+
> `reducerFactory`): here the module reuses `ArticlesSharedModule`, supplies `reducerFactory: getReducer`,
|
|
74
|
+
> and there is deliberately **no `baseQuery`** in the config.
|
|
75
|
+
|
|
76
|
+
## `thematic-paths.routes.ts`
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { Route } from '@angular/router';
|
|
80
|
+
|
|
81
|
+
import { ItemComponent, ListComponent } from './pages';
|
|
82
|
+
|
|
83
|
+
export const routes: Route[] = [
|
|
84
|
+
{ path: ':id/:slug', component: ItemComponent },
|
|
85
|
+
{ path: ':id', component: ItemComponent },
|
|
86
|
+
{ path: '', component: ListComponent },
|
|
87
|
+
];
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Register in `apps/web/src/app/app.routes.ts`
|
|
91
|
+
|
|
92
|
+
This module registers a single **top-level** route. Add the `sciezki-tematyczne` route to the
|
|
93
|
+
`appRoutes` array (idempotently — if a `sciezki-tematyczne` route already exists, skip). It is a
|
|
94
|
+
content publication browsed from the top level, so it is NOT added under the `wyszukaj/:text` search
|
|
95
|
+
route — thematic-paths does not appear in the search results.
|
|
96
|
+
|
|
97
|
+
Top-level — add to `appRoutes`:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
{
|
|
101
|
+
path: 'sciezki-tematyczne',
|
|
102
|
+
loadChildren: () =>
|
|
103
|
+
import('@<PREFIX>/museum-thematic-paths/shell/angular').then(
|
|
104
|
+
(m) => m.MuseumThematicPathsModule,
|
|
105
|
+
),
|
|
106
|
+
},
|
|
107
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# detect-init.sh <workspace-root>
|
|
4
|
+
#
|
|
5
|
+
# Precondition gate for mobilems-objects (and the other module skills follow the same shape):
|
|
6
|
+
# confirm the MobilEMS foundation from mobilems-project-init is present. Portable to macOS bash 3.2.
|
|
7
|
+
#
|
|
8
|
+
# Exit 0 → foundation present, OK to add the module.
|
|
9
|
+
# Exit 3 → foundation missing (tell the user to run /mobilems:project-init first).
|
|
10
|
+
set -eu
|
|
11
|
+
|
|
12
|
+
ROOT="${1:?usage: detect-init.sh <workspace-root>}"
|
|
13
|
+
cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
|
|
14
|
+
|
|
15
|
+
miss() {
|
|
16
|
+
echo "FOUNDATION MISSING: $1" >&2
|
|
17
|
+
echo "Run /mobilems:project-init first to lay down the MobilEMS foundation." >&2
|
|
18
|
+
exit 3
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
[ -f apps/web/src/app/app.config.ts ] || miss "app.config.ts missing"
|
|
22
|
+
grep -q "SharedModule.forRoot" apps/web/src/app/app.config.ts || miss "SharedModule.forRoot not in app.config.ts (foundation not applied)"
|
|
23
|
+
grep -q "./lib/components" libs/shared/angular/src/index.ts 2>/dev/null || miss "shared-lib components barrel not populated"
|
|
24
|
+
[ -f apps/web/src/app/app.routes.ts ] || miss "app.routes.ts missing"
|
|
25
|
+
|
|
26
|
+
PREFIX="$(grep -oE '@[a-z0-9-]+/angular' tsconfig.base.json | head -1 | sed -E 's#@([a-z0-9-]+)/angular#\1#')"
|
|
27
|
+
echo "FOUNDATION OK. Detected prefix: ${PREFIX:-<unknown>}"
|
|
28
|
+
[ -d libs/museum-objects ] && echo "NOTE: libs/museum-objects already exists — build steps must be idempotent." >&2
|
|
29
|
+
exit 0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# verify-module.sh <workspace-root> <PREFIX>
|
|
4
|
+
#
|
|
5
|
+
# Post-condition check for mobilems-thematic-publications: library created, ArticlesSharedModule
|
|
6
|
+
# wired over MuseumThematicPath with its own reducer, facade + +state present, the
|
|
7
|
+
# sciezki-tematyczne route registered as a single top-level route, and the Articles deps installed.
|
|
8
|
+
# macOS bash 3.2 safe.
|
|
9
|
+
set -eu
|
|
10
|
+
|
|
11
|
+
ROOT="${1:?usage: verify-module.sh <workspace-root> <PREFIX>}"
|
|
12
|
+
PREFIX="${2:?usage: verify-module.sh <workspace-root> <PREFIX>}"
|
|
13
|
+
cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
|
|
14
|
+
|
|
15
|
+
fail=0
|
|
16
|
+
pass() { echo " PASS: $1"; }
|
|
17
|
+
bad() { echo " FAIL: $1" >&2; fail=1; }
|
|
18
|
+
|
|
19
|
+
MOD=libs/museum-thematic-paths/shell/angular/src/lib/thematic-paths.module.ts
|
|
20
|
+
|
|
21
|
+
echo "== Library =="
|
|
22
|
+
[ -f "$MOD" ] && pass "MuseumThematicPathsModule present" || bad "thematic-paths.module.ts missing"
|
|
23
|
+
[ -f libs/museum-thematic-paths/domain/src/lib/entities/museum-thematic-path.entity.ts ] && pass "MuseumThematicPath entity present" || bad "domain entity missing"
|
|
24
|
+
grep -q "class MuseumThematicPath" libs/museum-thematic-paths/domain/src/lib/entities/museum-thematic-path.entity.ts 2>/dev/null && pass "MuseumThematicPath class declared" || bad "MuseumThematicPath class not declared"
|
|
25
|
+
grep -q "museum-thematic-paths/shell/angular" tsconfig.base.json && pass "tsconfig shell path added" || bad "tsconfig shell path missing"
|
|
26
|
+
grep -q "museum-thematic-paths/domain" tsconfig.base.json && pass "tsconfig domain path added" || bad "tsconfig domain path missing"
|
|
27
|
+
|
|
28
|
+
echo "== Module wiring =="
|
|
29
|
+
grep -q "ArticlesSharedModule.forFeature" "$MOD" 2>/dev/null && pass "ArticlesSharedModule.forFeature wired" || bad "ArticlesSharedModule.forFeature missing"
|
|
30
|
+
grep -q "entity: 'thematicPaths'" "$MOD" 2>/dev/null && pass "entity 'thematicPaths' configured" || bad "entity 'thematicPaths' missing"
|
|
31
|
+
grep -q "type: MuseumThematicPath" "$MOD" 2>/dev/null && pass "type MuseumThematicPath configured" || bad "type MuseumThematicPath missing"
|
|
32
|
+
grep -q "reducerFactory: getReducer" "$MOD" 2>/dev/null && pass "reducerFactory: getReducer configured" || bad "reducerFactory: getReducer missing"
|
|
33
|
+
grep -q "ThematicPathsFacade" "$MOD" 2>/dev/null && pass "ThematicPathsFacade provided" || bad "ThematicPathsFacade not provided"
|
|
34
|
+
|
|
35
|
+
echo "== +state =="
|
|
36
|
+
STATE=libs/museum-thematic-paths/shell/angular/src/lib/+state
|
|
37
|
+
[ -f "$STATE/thematic-paths.facade.ts" ] && pass "facade present" || bad "thematic-paths.facade.ts missing"
|
|
38
|
+
[ -f "$STATE/thematic-paths.reducer.ts" ] && pass "reducer present" || bad "thematic-paths.reducer.ts missing"
|
|
39
|
+
grep -q "export function getReducer" "$STATE/thematic-paths.reducer.ts" 2>/dev/null && pass "getReducer exported" || bad "getReducer not exported in reducer"
|
|
40
|
+
|
|
41
|
+
echo "== Route registration =="
|
|
42
|
+
ROUTES=apps/web/src/app/app.routes.ts
|
|
43
|
+
grep -q "museum-thematic-paths/shell/angular" "$ROUTES" && pass "thematic-paths route registered" || bad "thematic-paths route not in app.routes.ts"
|
|
44
|
+
# single top-level route — expect exactly 1 occurrence
|
|
45
|
+
n=$(grep -c "museum-thematic-paths/shell/angular" "$ROUTES" || true)
|
|
46
|
+
[ "${n:-0}" -eq 1 ] && pass "registered as a single top-level route ($n)" || bad "expected exactly 1 route registration, found $n"
|
|
47
|
+
grep -q "sciezki-tematyczne" "$ROUTES" && pass "sciezki-tematyczne path present" || bad "sciezki-tematyczne path missing"
|
|
48
|
+
|
|
49
|
+
echo "== Deps =="
|
|
50
|
+
grep -q "@smartsoft001-mobilems/articles-domain" package.json && pass "articles-domain dep" || bad "articles-domain dep missing"
|
|
51
|
+
grep -q "@smartsoft001-mobilems/articles-shell-angular" package.json && pass "articles-shell-angular dep" || bad "articles-shell-angular dep missing"
|
|
52
|
+
grep -q "@smartsoft001-mobilems/articles-shell-dtos" package.json && pass "articles-shell-dtos dep" || bad "articles-shell-dtos dep missing"
|
|
53
|
+
|
|
54
|
+
echo
|
|
55
|
+
if [ "$fail" = 0 ]; then echo "VERIFY: all checks passed."; else echo "VERIFY: FAILED — fix the items above and re-run." >&2; fi
|
|
56
|
+
exit "$fail"
|