@meridianjs/meridian 0.1.30 → 0.1.32
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/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# @meridianjs/meridian
|
|
2
|
+
|
|
3
|
+
The default MeridianJS plugin. Provides all core domain modules, API routes, workflows, event subscribers, and link definitions out of the box. Adding this single plugin to your config gives you a fully functional project management backend.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @meridianjs/meridian
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// meridian.config.ts
|
|
15
|
+
import { defineConfig } from "@meridianjs/framework"
|
|
16
|
+
|
|
17
|
+
export default defineConfig({
|
|
18
|
+
projectConfig: {
|
|
19
|
+
databaseUrl: process.env.DATABASE_URL!,
|
|
20
|
+
jwtSecret: process.env.JWT_SECRET!,
|
|
21
|
+
httpPort: 9000,
|
|
22
|
+
},
|
|
23
|
+
modules: [
|
|
24
|
+
{ resolve: "@meridianjs/event-bus-local" }, // swap for event-bus-redis in production
|
|
25
|
+
{ resolve: "@meridianjs/job-queue-local" }, // swap for job-queue-redis in production
|
|
26
|
+
],
|
|
27
|
+
plugins: [
|
|
28
|
+
{ resolve: "@meridianjs/meridian" },
|
|
29
|
+
],
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You do **not** need to list the 14 core domain modules individually — the plugin loads them all automatically.
|
|
34
|
+
|
|
35
|
+
## What's Included
|
|
36
|
+
|
|
37
|
+
### Core Domain Modules (auto-loaded)
|
|
38
|
+
|
|
39
|
+
| Module | Service Token | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `@meridianjs/user` | `userModuleService` | Users, teams, sessions |
|
|
42
|
+
| `@meridianjs/workspace` | `workspaceModuleService` | Multi-tenant workspaces |
|
|
43
|
+
| `@meridianjs/auth` | `authModuleService` | JWT register / login / OAuth |
|
|
44
|
+
| `@meridianjs/project` | `projectModuleService` | Projects, labels, milestones, statuses |
|
|
45
|
+
| `@meridianjs/issue` | `issueModuleService` | Issues, comments, attachments, time logs |
|
|
46
|
+
| `@meridianjs/sprint` | `sprintModuleService` | Sprints / cycles |
|
|
47
|
+
| `@meridianjs/activity` | `activityModuleService` | Audit log |
|
|
48
|
+
| `@meridianjs/notification` | `notificationModuleService` | In-app notifications |
|
|
49
|
+
| `@meridianjs/invitation` | `invitationModuleService` | Workspace invitation tokens |
|
|
50
|
+
| `@meridianjs/workspace-member` | `workspaceMemberModuleService` | Workspace membership + roles |
|
|
51
|
+
| `@meridianjs/team-member` | `teamMemberModuleService` | Team membership |
|
|
52
|
+
| `@meridianjs/project-member` | `projectMemberModuleService` | Project-level access control |
|
|
53
|
+
| `@meridianjs/app-role` | `appRoleModuleService` | Custom RBAC roles with permission arrays |
|
|
54
|
+
| `@meridianjs/org-calendar` | `orgCalendarModuleService` | Working days, holidays, Gantt support |
|
|
55
|
+
|
|
56
|
+
### API Routes
|
|
57
|
+
|
|
58
|
+
All routes are mounted automatically. Selected highlights:
|
|
59
|
+
|
|
60
|
+
| Method | Path | Description |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `POST` | `/auth/register` | Create account, return JWT |
|
|
63
|
+
| `POST` | `/auth/login` | Authenticate, return JWT |
|
|
64
|
+
| `GET/POST` | `/admin/workspaces` | List / create workspaces |
|
|
65
|
+
| `GET/POST` | `/admin/projects` | List / create projects |
|
|
66
|
+
| `GET/POST` | `/admin/projects/:id/issues` | List / create issues |
|
|
67
|
+
| `GET/POST` | `/admin/projects/:id/sprints` | Manage sprints |
|
|
68
|
+
| `POST` | `/admin/projects/:id/issues/:issueId/comments` | Add comment |
|
|
69
|
+
| `GET/POST` | `/admin/workspaces/:id/members` | Workspace membership |
|
|
70
|
+
| `GET/POST` | `/admin/workspaces/:id/teams` | Team management |
|
|
71
|
+
| `GET/POST` | `/admin/workspaces/:id/invitations` | Invite users |
|
|
72
|
+
| `GET/POST` | `/admin/roles` | Custom RBAC role management |
|
|
73
|
+
|
|
74
|
+
### Workflows
|
|
75
|
+
|
|
76
|
+
All mutation routes run through saga workflows with automatic compensation:
|
|
77
|
+
|
|
78
|
+
- `createProjectWorkflow` — creates project + seeds default statuses
|
|
79
|
+
- `createIssueWorkflow` — creates issue + records activity + emits event
|
|
80
|
+
- `updateIssueStatusWorkflow` — updates status + emits `issue.status_changed`
|
|
81
|
+
- `assignIssueWorkflow` — assigns user + emits `issue.assigned`
|
|
82
|
+
- `completeSprintWorkflow` — completes sprint + moves incomplete issues to backlog
|
|
83
|
+
|
|
84
|
+
### Domain Events
|
|
85
|
+
|
|
86
|
+
| Event | Emitted by |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `project.created` | `createProjectWorkflow` |
|
|
89
|
+
| `issue.created` | `createIssueWorkflow` |
|
|
90
|
+
| `issue.status_changed` | `updateIssueStatusWorkflow` |
|
|
91
|
+
| `issue.assigned` | `assignIssueWorkflow` |
|
|
92
|
+
| `sprint.completed` | `completeSprintWorkflow` |
|
|
93
|
+
| `comment.created` | Comment creation route |
|
|
94
|
+
|
|
95
|
+
## Extending
|
|
96
|
+
|
|
97
|
+
Disable specific subscribers if you want to handle events yourself:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
{ resolve: "@meridianjs/meridian", disableSubscribers: ["issue.created"] }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Add your own routes, subscribers, and jobs alongside the plugin by placing files in your project's `src/api/`, `src/subscribers/`, and `src/jobs/` directories.
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Response } from "express";
|
|
2
2
|
/**
|
|
3
|
-
* GET /auth/google/link
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* GET /auth/google/link?token=<jwt>
|
|
4
|
+
* Initiates the Google OAuth link flow (connecting Google to an existing account).
|
|
5
|
+
* The JWT is accepted via query param so this can be a full-page navigation —
|
|
6
|
+
* which is required to ensure the nonce cookie is stored correctly (cross-origin
|
|
7
|
+
* XHR responses silently discard Set-Cookie headers in all modern browsers).
|
|
7
8
|
*/
|
|
8
9
|
export declare const GET: (req: any, res: Response) => Promise<void>;
|
|
9
10
|
//# sourceMappingURL=route.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/auth/google/link/route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/api/auth/google/link/route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,GAAU,KAAK,GAAG,EAAE,KAAK,QAAQ,kBAmDhD,CAAA"}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import jwt from "jsonwebtoken";
|
|
3
3
|
/**
|
|
4
|
-
* GET /auth/google/link
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* GET /auth/google/link?token=<jwt>
|
|
5
|
+
* Initiates the Google OAuth link flow (connecting Google to an existing account).
|
|
6
|
+
* The JWT is accepted via query param so this can be a full-page navigation —
|
|
7
|
+
* which is required to ensure the nonce cookie is stored correctly (cross-origin
|
|
8
|
+
* XHR responses silently discard Set-Cookie headers in all modern browsers).
|
|
8
9
|
*/
|
|
9
10
|
export const GET = async (req, res) => {
|
|
10
|
-
//
|
|
11
|
+
// Accept token from query param (full-page navigation) or Authorization header (fallback)
|
|
11
12
|
const authHeader = req.headers.authorization;
|
|
12
|
-
const token =
|
|
13
|
+
const token = req.query.token ||
|
|
14
|
+
(authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null);
|
|
13
15
|
if (!token) {
|
|
14
|
-
res.status(401).json({ error: { message: "Authorization header required" } });
|
|
16
|
+
res.status(401).json({ error: { message: "token query parameter or Authorization header required" } });
|
|
15
17
|
return;
|
|
16
18
|
}
|
|
17
19
|
const config = req.scope.resolve("config");
|
|
@@ -48,6 +50,6 @@ export const GET = async (req, res) => {
|
|
|
48
50
|
secure: process.env.NODE_ENV === "production",
|
|
49
51
|
});
|
|
50
52
|
const url = googleOAuthService.getAuthUrl(state);
|
|
51
|
-
res.
|
|
53
|
+
res.redirect(302, url);
|
|
52
54
|
};
|
|
53
55
|
//# sourceMappingURL=route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/auth/google/link/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,GAAG,MAAM,cAAc,CAAA;AAG9B
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../../../../../src/api/auth/google/link/route.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED