@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
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# libs/museum-<name> — structure to create
|
|
2
|
+
|
|
3
|
+
Copy from an existing article module in the reference MobilEMS app and substitute the module's
|
|
4
|
+
`<name>` / `<entity>`, threading `<PREFIX>`. The library has two projects: a
|
|
5
|
+
thin `domain` (one entity extending the npm `Article`) and a `shell/angular` (the Angular module +
|
|
6
|
+
list/item pages + service). Article modules use the npm `Article` entity directly through
|
|
7
|
+
`ArticlesSharedModule.forFeature`; the local domain entity is a near-empty subclass.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
libs/museum-<name>/
|
|
11
|
+
├── domain/ # project: museum-<name>-domain
|
|
12
|
+
│ └── src/
|
|
13
|
+
│ ├── index.ts # export * from './lib/entities';
|
|
14
|
+
│ └── lib/
|
|
15
|
+
│ ├── entities/ # Museum<Name> extends Article (+ index)
|
|
16
|
+
│ ├── enums/ # .gitkeep
|
|
17
|
+
│ ├── specifications/ # .gitkeep
|
|
18
|
+
│ └── value-objects/ # .gitkeep
|
|
19
|
+
└── shell/angular/ # project: museum-<name>-shell-angular
|
|
20
|
+
└── src/
|
|
21
|
+
├── index.ts # public barrel (pages + module [+ service])
|
|
22
|
+
└── lib/
|
|
23
|
+
├── <name>.module.ts # Museum<Name>Module (references/module-and-routes.md)
|
|
24
|
+
├── <name>.routes.ts
|
|
25
|
+
├── index.ts # SERVICES const + barrel (see below)
|
|
26
|
+
├── +state/ # ONLY if the module keeps feature state: <name>.reducer.ts
|
|
27
|
+
├── pages/ # list (ListComponent), item (ItemComponent) + index (PAGES)
|
|
28
|
+
└── services/ # optional module service (e.g. a visit logger)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Domain entity (thin subclass of the npm `Article`)
|
|
32
|
+
|
|
33
|
+
`domain/src/lib/entities/museum-<name>.entity.ts`:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { Model } from '@smartsoft001/models';
|
|
37
|
+
import { Article } from '@smartsoft001-mobilems/articles-domain';
|
|
38
|
+
|
|
39
|
+
@Model({})
|
|
40
|
+
export class Museum<Name> extends Article {}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Then `entities/index.ts` re-exports it and `domain/src/index.ts` does `export * from './lib/entities';`.
|
|
44
|
+
(If the module needs extra fields, add them to this subclass.)
|
|
45
|
+
|
|
46
|
+
## shell `lib/index.ts` — `SERVICES` + barrel
|
|
47
|
+
|
|
48
|
+
Define a `SERVICES` const here binding `ArticlesService` as the `CrudService`; a module that keeps
|
|
49
|
+
feature state spreads it into its providers:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { CrudService } from '@smartsoft001/crud-shell-angular';
|
|
53
|
+
import { ArticlesService } from '@smartsoft001-mobilems/articles-shell-angular';
|
|
54
|
+
|
|
55
|
+
export * from './pages/index';
|
|
56
|
+
export * from './<name>.module';
|
|
57
|
+
|
|
58
|
+
export const SERVICES = [
|
|
59
|
+
ArticlesService,
|
|
60
|
+
{ provide: CrudService, useClass: ArticlesService },
|
|
61
|
+
];
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## shell `src/index.ts` (public barrel)
|
|
65
|
+
|
|
66
|
+
`export * from './lib/pages';` + `export * from './lib/<name>.module';` (plus the module's own service
|
|
67
|
+
if it ships one — see below).
|
|
68
|
+
|
|
69
|
+
## `pages/index.ts`
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { ItemComponent } from './item/item.component';
|
|
73
|
+
import { ListComponent } from './list/list.component';
|
|
74
|
+
|
|
75
|
+
export * from './item/item.component';
|
|
76
|
+
export * from './list/list.component';
|
|
77
|
+
|
|
78
|
+
export const PAGES = [ListComponent, ItemComponent];
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Copy the `list/` and `item/` `.component.ts` + `.html` from a reference article module, threading
|
|
82
|
+
`<PREFIX>`.
|
|
83
|
+
|
|
84
|
+
## Optional: `+state/<name>.reducer.ts` (feature-local ngrx state)
|
|
85
|
+
|
|
86
|
+
Build this only if the module keeps its own ngrx state (Step 1 "feature state? = yes"). It wraps the
|
|
87
|
+
smart CRUD reducer keyed by the module's `<entity>`:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { Action } from '@ngrx/store';
|
|
91
|
+
import {
|
|
92
|
+
State as SmartState,
|
|
93
|
+
initialState as smartInitialState,
|
|
94
|
+
getReducer as smartGetReducer,
|
|
95
|
+
} from '@smartsoft001/crud-shell-angular';
|
|
96
|
+
import { Article } from '@smartsoft001-mobilems/articles-domain';
|
|
97
|
+
|
|
98
|
+
export type State = SmartState<Article>;
|
|
99
|
+
|
|
100
|
+
export const initialState = { ...smartInitialState };
|
|
101
|
+
|
|
102
|
+
const reducer = (state = initialState, action: any) => {
|
|
103
|
+
switch (action.type) {
|
|
104
|
+
default:
|
|
105
|
+
return smartGetReducer('<entity>')(state, action);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export function getReducer() {
|
|
110
|
+
return (state: any, action: Action) => reducer(state, action);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The module then passes `reducerFactory: getReducer` to `forFeature` (see
|
|
115
|
+
`references/module-and-routes.md`). A module without feature state omits `+state/` entirely.
|
|
116
|
+
|
|
117
|
+
## Optional: a module service
|
|
118
|
+
|
|
119
|
+
A module may ship a small injectable (for example, a visit logger). Copy it from the reference module
|
|
120
|
+
if it has one, threading `<PREFIX>`, and export it from `src/index.ts`:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { HttpClient } from '@angular/common/http';
|
|
124
|
+
import { inject, Injectable } from '@angular/core';
|
|
125
|
+
import { firstValueFrom } from 'rxjs';
|
|
126
|
+
|
|
127
|
+
import { environment } from '@<PREFIX>/angular';
|
|
128
|
+
|
|
129
|
+
@Injectable({ providedIn: 'root' })
|
|
130
|
+
export class Museum<Name>Service {
|
|
131
|
+
private http = inject(HttpClient);
|
|
132
|
+
|
|
133
|
+
logVisit(id: string | number): Promise<void> {
|
|
134
|
+
const url = environment.apiUrl + 'api/article/' + id + '/visit';
|
|
135
|
+
return firstValueFrom(this.http.post<void>(url, {}));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> **Watch for cross-module service imports.** In the reference, some article modules' pages inject
|
|
141
|
+
> _another_ article module's service (e.g. a `news` page importing `MuseumArticlesService` from
|
|
142
|
+
> `@<ref-prefix>/museum-articles/shell/angular`). A generic article module must be self-contained — when
|
|
143
|
+
> a copied page injects a sibling module's service, give this module its **own** `Museum<Name>Service`
|
|
144
|
+
> (the template above) and rewire the page's import to it, rather than depending on a module that may
|
|
145
|
+
> not exist in the target.
|
|
146
|
+
|
|
147
|
+
## Wiring
|
|
148
|
+
|
|
149
|
+
- **tsconfig.base.json paths** (add both):
|
|
150
|
+
```json
|
|
151
|
+
"@<PREFIX>/museum-<name>/domain": ["libs/museum-<name>/domain/src/index.ts"],
|
|
152
|
+
"@<PREFIX>/museum-<name>/shell/angular": ["libs/museum-<name>/shell/angular/src/index.ts"]
|
|
153
|
+
```
|
|
154
|
+
- **project.json / build config** — copy each project's build config and normalize every path field
|
|
155
|
+
the reference baked to its origin location — `sourceRoot`, `dest`, `outputPath`, `coverageDirectory`,
|
|
156
|
+
`jestConfig`, `lintFilePatterns`, and the jest `displayName` — to `libs/museum-<name>/...`. Some reference modules carry
|
|
157
|
+
stale values (e.g. a `sourceRoot` missing the `shell/angular` segment, or a `coverageDirectory`
|
|
158
|
+
under `packages/...`) while others are already correct — verify each against a known-good sibling and
|
|
159
|
+
fix only the stale ones. Set each `package.json` `name` to match (`museum-<name>-domain` /
|
|
160
|
+
`museum-<name>-shell-angular`) — a copied `package.json` may carry a stale name. A `domain` with no
|
|
161
|
+
`project.json` (Nx-inferred) is fine.
|
|
162
|
+
- **commit scope** — `commitlint.config.js` reads `libs/` dir names, so `museum-<name>` becomes a valid
|
|
163
|
+
scope automatically; no edit needed.
|
|
164
|
+
- **jest** — keep the reference `jest.config.ts` / `tsconfig.spec.json` so the shell unit-tests run.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# `Museum<Name>Module` + route registration
|
|
2
|
+
|
|
3
|
+
An article module wraps `ArticlesSharedModule.forFeature` over the npm `Article` entity and filters
|
|
4
|
+
its API requests with a `template` value. Thread `<PREFIX>` (the `environment` import) and the chosen
|
|
5
|
+
`<name>` / `<entity>` / `<template>`. The `Masonry` factory returns the real library in the browser
|
|
6
|
+
and a no-op mock during SSR. Copy the file structure from an existing article module in the reference
|
|
7
|
+
MobilEMS app and substitute the parameters.
|
|
8
|
+
|
|
9
|
+
## `libs/museum-<name>/shell/angular/src/lib/<name>.module.ts`
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { NgModule } from '@angular/core';
|
|
13
|
+
import { FormsModule } from '@angular/forms';
|
|
14
|
+
import { RouterModule } from '@angular/router';
|
|
15
|
+
import { SharedModule as SmartSharedModule } from '@smartsoft001/angular';
|
|
16
|
+
import { Article } from '@smartsoft001-mobilems/articles-domain';
|
|
17
|
+
import { ArticlesSharedModule } from '@smartsoft001-mobilems/articles-shell-angular';
|
|
18
|
+
import { Masonry } from '@thisissoon/angular-masonry';
|
|
19
|
+
|
|
20
|
+
import { environment } from '@<PREFIX>/angular';
|
|
21
|
+
|
|
22
|
+
import { routes } from './<name>.routes';
|
|
23
|
+
|
|
24
|
+
@NgModule({
|
|
25
|
+
providers: [
|
|
26
|
+
{
|
|
27
|
+
provide: Masonry,
|
|
28
|
+
useFactory: () => {
|
|
29
|
+
if (typeof window !== 'undefined' && (window as any)['Masonry']) {
|
|
30
|
+
return (window as any)['Masonry'];
|
|
31
|
+
}
|
|
32
|
+
// Return a mock for SSR
|
|
33
|
+
return class {
|
|
34
|
+
constructor() {
|
|
35
|
+
// no-op
|
|
36
|
+
}
|
|
37
|
+
layout() { return; }
|
|
38
|
+
reloadItems() { return; }
|
|
39
|
+
destroy() { return; }
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
imports: [
|
|
45
|
+
FormsModule,
|
|
46
|
+
SmartSharedModule,
|
|
47
|
+
ArticlesSharedModule.forFeature({
|
|
48
|
+
routing: false,
|
|
49
|
+
config: {
|
|
50
|
+
type: Article,
|
|
51
|
+
apiUrl: environment.apiUrl,
|
|
52
|
+
entity: '<entity>',
|
|
53
|
+
baseQuery: [
|
|
54
|
+
{ value: '<template>', key: 'template', type: '=', hidden: true },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
RouterModule.forChild(routes),
|
|
59
|
+
],
|
|
60
|
+
})
|
|
61
|
+
export class Museum<Name>Module {}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The **`baseQuery`** is what scopes the module to its content: `key` is always `'template'`, `type` is
|
|
65
|
+
`'='`, `hidden` is `true`, and `value` is the module's `<template>` (the API then returns only records
|
|
66
|
+
matching that template). Change only the `value` between modules.
|
|
67
|
+
|
|
68
|
+
### Optional: feature-local ngrx state
|
|
69
|
+
|
|
70
|
+
If the module keeps its own ngrx state, build `+state/<name>.reducer.ts` (see
|
|
71
|
+
`references/lib-contents.md`) exporting a `getReducer`, then in the module:
|
|
72
|
+
|
|
73
|
+
- pass `reducerFactory: getReducer` inside the `forFeature` `config`,
|
|
74
|
+
- define a `SERVICES` const in `lib/index.ts` that binds `ArticlesService` as the `CrudService`, and
|
|
75
|
+
spread it into the `providers` (alongside the `Masonry` provider).
|
|
76
|
+
|
|
77
|
+
(In the reference, the stateful article module also omits `SmartSharedModule` from its `imports` and
|
|
78
|
+
imports `ConfigsModule` from `@<PREFIX>/angular` — mirror whichever the reference module you copy
|
|
79
|
+
uses.) A module with no feature state omits `+state/` and the `reducerFactory` entirely.
|
|
80
|
+
|
|
81
|
+
## `<name>.routes.ts`
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { Route } from '@angular/router';
|
|
85
|
+
|
|
86
|
+
import { ItemComponent, ListComponent } from './pages';
|
|
87
|
+
|
|
88
|
+
export const routes: Route[] = [
|
|
89
|
+
{ path: ':id/:slug', component: ItemComponent },
|
|
90
|
+
{ path: ':id', component: ItemComponent },
|
|
91
|
+
{ path: '', component: ListComponent },
|
|
92
|
+
];
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Register in `apps/web/src/app/app.routes.ts`
|
|
96
|
+
|
|
97
|
+
Add the module's `<route>` to the `appRoutes` array (idempotently — if a `<route>` route already
|
|
98
|
+
exists, skip). Add it as a top-level route, and — if the module's results belong in site search — as a
|
|
99
|
+
child of the `wyszukaj/:text` route so `/wyszukaj/:text/<route>` works.
|
|
100
|
+
|
|
101
|
+
Top-level — add to `appRoutes`:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
{
|
|
105
|
+
path: '<route>',
|
|
106
|
+
loadChildren: () =>
|
|
107
|
+
import('@<PREFIX>/museum-<name>/shell/angular').then(
|
|
108
|
+
(m) => m.Museum<Name>Module,
|
|
109
|
+
),
|
|
110
|
+
},
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Search child — add to the `children` of the `wyszukaj/:text` route, before the
|
|
114
|
+
`{ path: '', redirectTo: ... }` default:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
{
|
|
118
|
+
path: '<route>',
|
|
119
|
+
loadChildren: () =>
|
|
120
|
+
import('@<PREFIX>/museum-<name>/shell/angular').then(
|
|
121
|
+
(m) => m.Museum<Name>Module,
|
|
122
|
+
),
|
|
123
|
+
},
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## The `/article-preview` page (build once)
|
|
127
|
+
|
|
128
|
+
The app's content-preview page (`apps/web/src/app/article-preview/`) renders an `Article` for CMS
|
|
129
|
+
preview mode, so it imports `@smartsoft001-mobilems/articles-domain` and belongs to the articles
|
|
130
|
+
feature — the foundation deliberately leaves it out. Build it the first time an article module is
|
|
131
|
+
added, and skip it if it already exists (idempotent across article-module runs):
|
|
132
|
+
|
|
133
|
+
1. Copy `apps/web/src/app/article-preview/` (`.component.ts` + `.html`) from the reference app, thread
|
|
134
|
+
`<PREFIX>`.
|
|
135
|
+
2. Add its route to `appRoutes` in `apps/web/src/app/app.routes.ts` (a plain top-level route, before
|
|
136
|
+
the `**` catch-all):
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
{
|
|
140
|
+
path: 'article-preview',
|
|
141
|
+
loadComponent: () =>
|
|
142
|
+
import('./article-preview/article-preview.component').then(
|
|
143
|
+
(m) => m.ArticlePreviewComponent,
|
|
144
|
+
),
|
|
145
|
+
},
|
|
146
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Article module shared components
|
|
2
|
+
|
|
3
|
+
An article module renders its records as cards in the grid view and rows in the list view, so it
|
|
4
|
+
contributes a pair of shared components to `libs/shared/angular` named after the module. Build them by
|
|
5
|
+
copying the card components of an existing article module in the reference MobilEMS app and adapting
|
|
6
|
+
them to the module's `<name>` and `<PREFIX>`. Every step is idempotent — if the target already exists,
|
|
7
|
+
leave it.
|
|
8
|
+
|
|
9
|
+
All paths below are under `libs/shared/angular/src/lib`.
|
|
10
|
+
|
|
11
|
+
## Article card components — build + export
|
|
12
|
+
|
|
13
|
+
Build these two component directories and export them from `components/index.ts`:
|
|
14
|
+
|
|
15
|
+
| Component | Renders |
|
|
16
|
+
| ----------------------------- | -------------------------------- |
|
|
17
|
+
| `components/<name>-grid-item` | an article card in the grid view |
|
|
18
|
+
| `components/<name>-list-item` | an article row in the list view |
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
// components/index.ts — these exports belong to the <name> module:
|
|
22
|
+
export * from './<name>-grid-item';
|
|
23
|
+
export * from './<name>-list-item';
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
These render an `Article` (via the foundation's generic `IArticle` model), so they depend on
|
|
27
|
+
`@smartsoft001-mobilems/articles-domain` — which this skill installs. There is no module-specific
|
|
28
|
+
model type to add (contrast `mobilems-objects`, which adds `ISpecificObject` to `objects.model.ts`).
|
|
29
|
+
|
|
30
|
+
## Optional: article gallery widget
|
|
31
|
+
|
|
32
|
+
If the project renders **article-gallery content blocks** (a page widget that embeds a gallery of
|
|
33
|
+
articles), build the article gallery widget once and register it in the widget content-type map. This
|
|
34
|
+
is shared by all article modules — build it the first time an article module needs it, and skip if a
|
|
35
|
+
previous article module already added it.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
// components/widget/index.ts:
|
|
39
|
+
export * from './gallery-article/widget-gallery-article.component';
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Register it in the widget content-type map in `components/widget/widget.component.ts`:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { WidgetGalleryArticleComponent } from './gallery-article/widget-gallery-article.component';
|
|
46
|
+
// …in the ArticleWidgetType → component map:
|
|
47
|
+
[ArticleWidgetType.GALLERY_ARTICLE]: WidgetGalleryArticleComponent,
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The widget container renders sub-widgets via `NgComponentOutlet`, so the gallery widget goes in the
|
|
51
|
+
type-map only — it does **not** go in the container's `imports` array.
|
|
52
|
+
|
|
53
|
+
## Verify
|
|
54
|
+
|
|
55
|
+
`scripts/verify-module.sh <workspace> <PREFIX> <name>` checks the module's `<name>-grid-item` and
|
|
56
|
+
`<name>-list-item` exist and are exported from the components barrel.
|
|
@@ -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.
|
|
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,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# verify-module.sh <workspace-root> <PREFIX> <name> [template]
|
|
4
|
+
#
|
|
5
|
+
# Post-condition check for one article module named <name>: library created, ArticlesSharedModule
|
|
6
|
+
# .forFeature wired (with the template value if given), route registered, and the module's article
|
|
7
|
+
# card shared components built + exported.
|
|
8
|
+
set -eu
|
|
9
|
+
|
|
10
|
+
ROOT="${1:?usage: verify-module.sh <workspace-root> <PREFIX> <name> [template]}"
|
|
11
|
+
PREFIX="${2:?usage: verify-module.sh <workspace-root> <PREFIX> <name> [template]}"
|
|
12
|
+
NAME="${3:?usage: verify-module.sh <workspace-root> <PREFIX> <name> [template]}"
|
|
13
|
+
TEMPLATE="${4:-}"
|
|
14
|
+
cd "$ROOT" 2>/dev/null || { echo "ERROR: no such dir: $ROOT" >&2; exit 2; }
|
|
15
|
+
|
|
16
|
+
LIBF="museum-$NAME"
|
|
17
|
+
fail=0
|
|
18
|
+
pass() { echo " PASS: $1"; }
|
|
19
|
+
bad() { echo " FAIL: $1" >&2; fail=1; }
|
|
20
|
+
info() { echo " INFO: $1"; }
|
|
21
|
+
|
|
22
|
+
echo "== Verifying article module: name=$NAME lib=$LIBF =="
|
|
23
|
+
|
|
24
|
+
echo "== Library =="
|
|
25
|
+
MOD="$(ls libs/$LIBF/shell/angular/src/lib/*.module.ts 2>/dev/null | head -1)"
|
|
26
|
+
[ -n "$MOD" ] && pass "module file present ($MOD)" || bad "no *.module.ts in libs/$LIBF/shell/angular/src/lib"
|
|
27
|
+
[ -f "libs/$LIBF/domain/src/lib/entities/index.ts" ] && pass "domain entity present" || bad "domain entity missing"
|
|
28
|
+
grep -q "$LIBF/shell/angular" tsconfig.base.json && pass "tsconfig shell path added" || bad "tsconfig.base.json shell path missing"
|
|
29
|
+
grep -q "$LIBF/domain" tsconfig.base.json && pass "tsconfig domain path added" || bad "tsconfig.base.json domain path missing"
|
|
30
|
+
|
|
31
|
+
echo "== forFeature wiring =="
|
|
32
|
+
if [ -n "$MOD" ]; then
|
|
33
|
+
grep -q "ArticlesSharedModule.forFeature" "$MOD" && pass "ArticlesSharedModule.forFeature wired" || bad "ArticlesSharedModule.forFeature missing"
|
|
34
|
+
grep -q "key: 'template'" "$MOD" && pass "baseQuery filters on key 'template'" || bad "baseQuery key 'template' missing"
|
|
35
|
+
if [ -n "$TEMPLATE" ]; then
|
|
36
|
+
grep -q "$TEMPLATE" "$MOD" && pass "template value '$TEMPLATE' present" || bad "template value '$TEMPLATE' missing"
|
|
37
|
+
fi
|
|
38
|
+
grep -q "reducerFactory" "$MOD" && info "module keeps feature state (reducerFactory present)" || info "module has no feature state"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
echo "== Route registration =="
|
|
42
|
+
ROUTES=apps/web/src/app/app.routes.ts
|
|
43
|
+
n=$(grep -c "$LIBF/shell/angular" "$ROUTES" 2>/dev/null || true)
|
|
44
|
+
[ "${n:-0}" -ge 1 ] && pass "route registered ($n occurrence(s) — top-level$([ "${n:-0}" -ge 2 ] && echo ' + search child'))" || bad "route not in app.routes.ts"
|
|
45
|
+
|
|
46
|
+
echo "== Article card shared components =="
|
|
47
|
+
COMP=libs/shared/angular/src/lib/components
|
|
48
|
+
for d in "$NAME-grid-item" "$NAME-list-item"; do
|
|
49
|
+
[ -d "$COMP/$d" ] && pass "built $d" || bad "missing $COMP/$d"
|
|
50
|
+
done
|
|
51
|
+
grep -q "$NAME-grid-item" "$COMP/index.ts" && pass "$NAME-grid-item exported" || bad "$NAME-grid-item export missing"
|
|
52
|
+
grep -q "$NAME-list-item" "$COMP/index.ts" && pass "$NAME-list-item exported" || bad "$NAME-list-item export missing"
|
|
53
|
+
|
|
54
|
+
echo "== Deps =="
|
|
55
|
+
for p in articles-domain articles-shell-angular articles-shell-dtos; do
|
|
56
|
+
grep -q "@smartsoft001-mobilems/$p" package.json && pass "$p dep" || bad "$p dep missing"
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
echo
|
|
60
|
+
if [ "$fail" = 0 ]; then echo "VERIFY: all checks passed."; else echo "VERIFY: FAILED — fix the items above and re-run." >&2; fi
|
|
61
|
+
exit "$fail"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobilems-docs-reader
|
|
3
|
+
description: Answer questions about the MuzaCMS / MobileMS indexer API by reading a freshly-fetched OpenAPI spec. Use whenever the user asks about endpoints, request/response shapes, status codes, auth, or behavior of the indexer API (host develop-indexer-api.mobilems.pl). Read-only — never fabricates endpoints.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Glob
|
|
8
|
+
- Grep
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You answer questions about the **MuzaCMS / MobileMS indexer API** strictly from the OpenAPI (Swagger 2.0) specification. You never invent endpoints, schemas, or status codes — if it is not in the spec, you say so plainly.
|
|
12
|
+
|
|
13
|
+
The spec is **not bundled**. It is fetched from the live MuzaCMS instance by a refresh script that lives next to this skill, using credentials supplied via environment variables. The script caches the fetched spec per Claude Code session (with an 8-hour TTL safety net), so it may skip the actual network call and reuse a cached copy on follow-up invocations within the same session.
|
|
14
|
+
|
|
15
|
+
## Step 1 — Run the refresh script (mandatory)
|
|
16
|
+
|
|
17
|
+
On every invocation, run the refresh script via Bash. The script itself decides whether to actually fetch — it owns the cache. Your job is only to run it and react to the result. A successful run may be either:
|
|
18
|
+
|
|
19
|
+
- A real fetch (`Refreshing MuzaCMS API spec from ... → GET /admin/login → POST /admin/login → GET /docs/api → ✓ Refreshed N bytes ...`), or
|
|
20
|
+
- A cache hit (`✓ spec cached for this Claude Code session (refreshed N min ago at ...), skipping fetch`).
|
|
21
|
+
|
|
22
|
+
Both are exit-code-0 successes. Treat them identically and proceed to Step 2. **Do not** attempt to bypass the cache, delete the cache file, or force a refetch — the cache is intentional and the script's decision is authoritative.
|
|
23
|
+
|
|
24
|
+
### Invocation
|
|
25
|
+
|
|
26
|
+
The refresh script is shipped under `plugins/mobilems/scripts/`. Invoke it through `bash` so the executable bit is irrelevant:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
bash ./node_modules/@smartsoft001-mobilems/claude-plugins/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh --quiet
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Outcomes:
|
|
33
|
+
|
|
34
|
+
- **Success (exit 0)** → jump to Step 2.
|
|
35
|
+
- **Script-level error** (missing env vars, missing tooling, auth rejected, HTTP error, parse failure, etc.) → jump to the matching Fail mode below.
|
|
36
|
+
- **Permission denied by Claude Code** → jump to "Fail mode — permission denied".
|
|
37
|
+
|
|
38
|
+
The script reads two environment variables — `MOBILEMS_LOGIN` and `MOBILEMS_PASSWORD` — performs the Symfony CSRF + session login against `https://develop-indexer.mobilems.pl`, fetches `/docs/api`, and writes the spec to `shared-assets/mobilems-api.json` inside the installed package. It also auto-loads `.env` from the current working directory; no shell sourcing is needed.
|
|
39
|
+
|
|
40
|
+
### Fail mode — permission denied by Claude Code
|
|
41
|
+
|
|
42
|
+
If the Bash call is rejected by Claude Code's permission system, stop and tell the user verbatim:
|
|
43
|
+
|
|
44
|
+
> The MuzaCMS spec could not be refreshed because Claude Code denied permission to run the refresh script. To allow it, add this entry to your project's `.claude/settings.json` (committed) or `.claude/settings.local.json` (per-dev, gitignored) under `permissions.allow`, then ask again:
|
|
45
|
+
>
|
|
46
|
+
> - `"Bash(bash ./node_modules/@smartsoft001-mobilems/claude-plugins/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh:*)"`
|
|
47
|
+
|
|
48
|
+
Do not attempt to answer the user's question from training knowledge. Do not invent alternative invocation patterns to try to bypass the denial.
|
|
49
|
+
|
|
50
|
+
### Fail mode — missing env vars
|
|
51
|
+
|
|
52
|
+
If the script exits non-zero with a message starting `✗ Brak wymaganych zmiennych środowiskowych` (or English equivalent listing `MOBILEMS_LOGIN` / `MOBILEMS_PASSWORD`), **stop immediately**. Relay the script's message verbatim to the user.
|
|
53
|
+
|
|
54
|
+
Do not attempt to answer the user's question from training knowledge. Do not guess. Do not read any pre-existing `mobilems-api.json` that may be lying around in `node_modules/` — without a successful refresh you have no confirmation it is current.
|
|
55
|
+
|
|
56
|
+
### Fail mode — missing tooling
|
|
57
|
+
|
|
58
|
+
If the script exits with a message about missing `curl` or `jq`, relay it verbatim. The script tells the user exactly how to install the missing dependency (`brew install jq` / `apt install jq`).
|
|
59
|
+
|
|
60
|
+
### Fail mode — other script failures
|
|
61
|
+
|
|
62
|
+
If the script fails for any other reason (HTTP error, auth rejected, parse failure), report the exact error message from the script back to the user and stop. Do not answer the API question.
|
|
63
|
+
|
|
64
|
+
## Step 2 — Locate the freshly-written spec
|
|
65
|
+
|
|
66
|
+
Use `Glob` with this pattern:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
**/claude-plugins/**/shared-assets/mobilems-api.json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The hit lives under `node_modules/@smartsoft001-mobilems/claude-plugins/shared-assets/` after a successful refresh. Exclude `dist/` and `tmp/` from the Glob, but **do** allow `node_modules/`.
|
|
73
|
+
|
|
74
|
+
If the Glob returns nothing after the refresh script reported success, something is wrong with the install layout — tell the user and stop.
|
|
75
|
+
|
|
76
|
+
## Step 3 — Answer from the spec
|
|
77
|
+
|
|
78
|
+
The spec is **Swagger 2.0** with this wrapping shape:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
{ "spec": { "swagger": "2.0", "paths": {...}, "definitions": {...} } }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Always traverse into `.spec` first.
|
|
85
|
+
|
|
86
|
+
When the user asks about endpoints:
|
|
87
|
+
|
|
88
|
+
1. **Locate the path** in `spec.paths`. Look for the exact path the user mentioned, including any path parameters (`{id}`).
|
|
89
|
+
2. **Quote the HTTP method(s) and path verbatim.** Example: `GET /api/objects/{id}`.
|
|
90
|
+
3. For request bodies and responses, cite the `$ref` target by name and (briefly) summarize its shape from `spec.definitions`.
|
|
91
|
+
4. For status codes, list each documented response from `responses` with its `description`.
|
|
92
|
+
5. For auth, check both the operation-level `security` and the global `spec.securityDefinitions`.
|
|
93
|
+
|
|
94
|
+
If the user asks about a path that is **not in the spec**, say so explicitly:
|
|
95
|
+
|
|
96
|
+
> The spec does not document a `DELETE /api/articles/{id}` endpoint. The articles paths in the spec are: `[list actual paths]`. If you've seen this endpoint elsewhere, it may exist in the running service without being documented — verify with a live request.
|
|
97
|
+
|
|
98
|
+
## Known caveats — always surface when relevant
|
|
99
|
+
|
|
100
|
+
- **Response schemas occasionally diverge from runtime.** Documented response shapes have, in practice, not always matched what the live API actually returns. When the user is about to implement against a response schema, add a brief reminder to verify with a real request before relying on the documented shape.
|
|
101
|
+
- **Spec is regenerated server-side from PHP annotations.** Newly added endpoints in the live service may not appear until the next backend deployment, even with a fresh fetch.
|
|
102
|
+
- **Auth flow nuance:** the spec describes the indexer API itself; the `/admin/login` flow used by the refresh script is separate and not documented in the spec.
|
|
103
|
+
|
|
104
|
+
## Answering style
|
|
105
|
+
|
|
106
|
+
- Be terse. The user wants a specific fact, not a tutorial on Swagger.
|
|
107
|
+
- Always include exact path + method + relevant status codes when applicable.
|
|
108
|
+
- When quoting definitions, use the schema name (e.g., `Object`, `Unauthorised`) as it appears in `spec.definitions`.
|
|
109
|
+
- If multiple endpoints match a vague question, list them — don't pick one arbitrarily.
|
|
110
|
+
|
|
111
|
+
## When NOT to use this skill
|
|
112
|
+
|
|
113
|
+
- Non-MobileMS APIs (any other host).
|
|
114
|
+
- Generic REST/OpenAPI guidance unrelated to the indexer.
|
|
115
|
+
- Schema design decisions ("should I add X field?") — this skill only describes what exists.
|
|
116
|
+
- Anything requiring a live network call to the API itself.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobilems-events
|
|
3
|
+
description: Add the museum EVENTS feature module (wydarzenia) to a MobilEMS app initialized with mobilems-project-init. Use whenever the user wants to add / scaffold / wire the events module, the "wydarzenia" pages (event list + event detail + booking/reservation flow with confirm + cancel), event booking, event reservation, an event calendar / available-dates picker, or asks to "dodaj moduł wydarzeń / rezerwacji wydarzeń". Creates libs/museum-events (shell/angular only — a standalone booking module), registers the /wydarzenia route, and confirms the foundation packages it reuses are present. 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 events module
|
|
9
|
+
|
|
10
|
+
Add the **events** (wydarzenia) feature module to a MobilEMS app whose foundation was built by
|
|
11
|
+
`mobilems-project-init`. Events is a self-contained booking / reservation system: a list of events,
|
|
12
|
+
an event detail page, and a reservation flow (booking form -> confirmation -> cancellation) driven by
|
|
13
|
+
its own `EventsReservationService` over the event / event-periods / event-reservations API. This
|
|
14
|
+
skill builds the `libs/museum-events` library and registers a single top-level `/wydarzenia` route.
|
|
15
|
+
|
|
16
|
+
Events has a leaner shape than the other feature modules: a pure `RouterModule.forChild` module with
|
|
17
|
+
**lazy `loadComponent` routes** and **no shared-module `forFeature`**, and it ships **only a
|
|
18
|
+
`shell/angular` project** (there is no `domain` library). All of its UI and data access live inside
|
|
19
|
+
its own `shell/angular`.
|
|
20
|
+
|
|
21
|
+
## Precondition
|
|
22
|
+
|
|
23
|
+
Run `scripts/detect-init.sh <workspace-root>`. It confirms the MobilEMS foundation is present
|
|
24
|
+
(`SharedModule.forRoot` in `app.config.ts`, a populated shared-lib barrel). If not, tell the user to
|
|
25
|
+
run `/mobilems:project-init` first. Hold `<PREFIX>` (from `tsconfig.base.json`; the reference
|
|
26
|
+
MobilEMS app uses `@msr`) and the reference repo path (same one init used).
|
|
27
|
+
|
|
28
|
+
## Steps
|
|
29
|
+
|
|
30
|
+
1. **npm deps (precondition check)** — events imports only foundation packages:
|
|
31
|
+
`@smartsoft001-mobilems/angular`, `@smartsoft001-mobilems/models`, `@smartsoft001/angular`,
|
|
32
|
+
`@thisissoon/angular-masonry`, and `@ngx-translate/core` — all already installed by
|
|
33
|
+
`mobilems-project-init`. So this step is a CHECK: confirm those lines are in `package.json`; there
|
|
34
|
+
is nothing new to add. As a safeguard, grep the copied lib for any third-party import not in that
|
|
35
|
+
foundation set and add only what is genuinely missing. Do not `npm install` unless asked.
|
|
36
|
+
2. **Library** — create `libs/museum-events/shell/angular` per `references/lib-contents.md`: copy the
|
|
37
|
+
shell (`MuseumEventsModule`, `events.routes.ts`, `pages/{list,item,booking,confirm,cancel}`,
|
|
38
|
+
`services/events-reservation.service.ts`, `models/events.models.ts`, `pipes/time-format.pipe.ts`,
|
|
39
|
+
and the `src/__mocks__/@smartsoft001-mobilems/{angular,models}.ts` jest mocks), thread `<PREFIX>`.
|
|
40
|
+
Add the single `tsconfig.base.json` path `@<PREFIX>/museum-events/shell/angular` and the
|
|
41
|
+
`museum-events` commit scope.
|
|
42
|
+
3. **Module + routes** — see `references/module-and-routes.md`: `MuseumEventsModule` is just
|
|
43
|
+
`@NgModule({ imports: [RouterModule.forChild(eventsRoutes)] })`; `eventsRoutes` uses lazy
|
|
44
|
+
`loadComponent` for every page and provides the `Masonry` SSR factory on the list route. Add the
|
|
45
|
+
lazy `wydarzenia` route to the `appRoutes` array in `apps/web/src/app/app.routes.ts` as a single
|
|
46
|
+
top-level route.
|
|
47
|
+
4. **Verify** — run `scripts/verify-module.sh <workspace-root> <PREFIX>`: asserts the
|
|
48
|
+
`libs/museum-events/shell/angular` lib exists with `MuseumEventsModule` (`RouterModule.forChild`)
|
|
49
|
+
and `events.routes.ts`, the `@<PREFIX>/museum-events/shell/angular` tsconfig path is added, the
|
|
50
|
+
five pages + `EventsReservationService` + `events.models.ts` + `TimeFormatPipe` are present, the
|
|
51
|
+
`wydarzenia` route is registered as a single top-level route, and the foundation deps it reuses are
|
|
52
|
+
in `package.json`. Fix and re-run.
|
|
53
|
+
|
|
54
|
+
## Notes
|
|
55
|
+
|
|
56
|
+
- Events is a standalone booking module: it owns its data access (`EventsReservationService` calling
|
|
57
|
+
the events API) and contributes **nothing** to `libs/shared/angular`. The shared lib stays
|
|
58
|
+
untouched.
|
|
59
|
+
- Events ships **only** a `shell/angular` project — there is no `domain` library and no shared-module
|
|
60
|
+
`forFeature`; its event/reservation types live in `shell/angular/src/lib/models/events.models.ts`.
|
|
61
|
+
- `/wydarzenia` is a top-level route only. Events is a booking destination, not a search result, so it
|
|
62
|
+
is NOT added under the `wyszukaj/:text` search children.
|
|
63
|
+
- This skill ONLY touches the events module + its route. It never adds other feature modules, never
|
|
64
|
+
re-runs the foundation, and never edits `libs/shared/angular`.
|
|
65
|
+
- Bundled `references/` + `scripts/` ship automatically. Do not hand-edit `plugin.json`.
|