@lssm/example.saas-boilerplate 0.0.0-canary-20251215234153 → 0.0.0-canary-20251216023757
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/.turbo/turbo-build.log +32 -24
- package/CHANGELOG.md +8 -8
- package/dist/billing/billing.contracts.js +1 -0
- package/dist/billing/billing.enum.js +1 -0
- package/dist/billing/billing.event.js +1 -0
- package/dist/billing/billing.handler.js +1 -0
- package/dist/billing/billing.schema.js +1 -0
- package/dist/billing/index.js +1 -0
- package/dist/dashboard/index.js +1 -0
- package/dist/handlers/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/presentations/index.js +1 -1
- package/dist/project/index.js +1 -0
- package/dist/project/project.contracts.js +1 -0
- package/dist/project/project.enum.js +1 -0
- package/dist/project/project.event.js +1 -0
- package/dist/project/project.handler.js +1 -0
- package/dist/project/project.presentation.js +1 -0
- package/dist/project/project.schema.js +1 -0
- package/dist/settings/index.js +1 -0
- package/dist/settings/settings.entity.js +1 -0
- package/dist/settings/settings.enum.js +1 -0
- package/package.json +45 -29
- package/src/billing/billing.contracts.ts +116 -0
- package/src/{entities/billing.ts → billing/billing.entity.ts} +2 -1
- package/src/billing/billing.enum.ts +24 -0
- package/src/billing/billing.event.ts +94 -0
- package/src/{handlers/billing.handlers.ts → billing/billing.handler.ts} +7 -8
- package/src/{presentations/billing.ts → billing/billing.presentation.ts} +1 -3
- package/src/{contracts/billing.ts → billing/billing.schema.ts} +29 -131
- package/src/billing/index.ts +65 -0
- package/src/{presentations/dashboard.ts → dashboard/dashboard.presentation.ts} +1 -3
- package/src/dashboard/index.ts +9 -0
- package/src/handlers/index.ts +12 -26
- package/src/index.ts +43 -6
- package/src/presentations/index.ts +24 -30
- package/src/project/index.ts +67 -0
- package/src/project/project.contracts.ts +185 -0
- package/src/{entities/project.ts → project/project.entity.ts} +2 -1
- package/src/project/project.enum.ts +23 -0
- package/src/project/project.event.ts +109 -0
- package/src/{handlers/project.handlers.ts → project/project.handler.ts} +8 -9
- package/src/{presentations/project-list.ts → project/project.presentation.ts} +2 -4
- package/src/project/project.schema.ts +145 -0
- package/src/settings/index.ts +10 -0
- package/src/{entities/settings.ts → settings/settings.entity.ts} +3 -11
- package/src/settings/settings.enum.ts +12 -0
- package/src/{handlers → shared}/mock-data.ts +2 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/contracts/billing.js +0 -1
- package/dist/contracts/index.js +0 -1
- package/dist/contracts/project.js +0 -1
- package/dist/entities/index.js +0 -1
- package/dist/entities/settings.js +0 -1
- package/dist/events.js +0 -1
- package/dist/handlers/billing.handlers.js +0 -1
- package/dist/handlers/project.handlers.js +0 -1
- package/dist/presentations/project-list.js +0 -1
- package/src/contracts/index.ts +0 -36
- package/src/contracts/project.ts +0 -314
- package/src/entities/index.ts +0 -62
- package/src/events.ts +0 -177
- /package/dist/{entities/billing.js → billing/billing.entity.js} +0 -0
- /package/dist/{presentations/billing.js → billing/billing.presentation.js} +0 -0
- /package/dist/{presentations/dashboard.js → dashboard/dashboard.presentation.js} +0 -0
- /package/dist/{entities/project.js → project/project.entity.js} +0 -0
- /package/dist/{handlers → shared}/mock-data.js +0 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { defineCommand, defineQuery } from '@lssm/lib.contracts/spec';
|
|
2
|
+
import {
|
|
3
|
+
ProjectModel,
|
|
4
|
+
CreateProjectInputModel,
|
|
5
|
+
UpdateProjectInputModel,
|
|
6
|
+
GetProjectInputModel,
|
|
7
|
+
DeleteProjectInputModel,
|
|
8
|
+
DeleteProjectOutputModel,
|
|
9
|
+
ProjectDeletedPayloadModel,
|
|
10
|
+
ListProjectsInputModel,
|
|
11
|
+
ListProjectsOutputModel,
|
|
12
|
+
} from './project.schema';
|
|
13
|
+
|
|
14
|
+
const OWNERS = ['example.saas-boilerplate'] as const;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a new project.
|
|
18
|
+
*/
|
|
19
|
+
export const CreateProjectContract = defineCommand({
|
|
20
|
+
meta: {
|
|
21
|
+
name: 'saas.project.create',
|
|
22
|
+
version: 1,
|
|
23
|
+
stability: 'stable',
|
|
24
|
+
owners: [...OWNERS],
|
|
25
|
+
tags: ['saas', 'project', 'create'],
|
|
26
|
+
description: 'Create a new project in the organization.',
|
|
27
|
+
goal: 'Allow users to create projects for organizing work.',
|
|
28
|
+
context: 'Called from project creation UI or API.',
|
|
29
|
+
},
|
|
30
|
+
io: {
|
|
31
|
+
input: CreateProjectInputModel,
|
|
32
|
+
output: ProjectModel,
|
|
33
|
+
errors: {
|
|
34
|
+
SLUG_EXISTS: {
|
|
35
|
+
description: 'A project with this slug already exists',
|
|
36
|
+
http: 409,
|
|
37
|
+
gqlCode: 'SLUG_EXISTS',
|
|
38
|
+
when: 'Slug is already taken in the organization',
|
|
39
|
+
},
|
|
40
|
+
LIMIT_REACHED: {
|
|
41
|
+
description: 'Project limit reached for this plan',
|
|
42
|
+
http: 403,
|
|
43
|
+
gqlCode: 'LIMIT_REACHED',
|
|
44
|
+
when: 'Organization has reached project limit',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
policy: {
|
|
49
|
+
auth: 'user',
|
|
50
|
+
},
|
|
51
|
+
sideEffects: {
|
|
52
|
+
emits: [
|
|
53
|
+
{
|
|
54
|
+
name: 'project.created',
|
|
55
|
+
version: 1,
|
|
56
|
+
when: 'Project is created',
|
|
57
|
+
payload: ProjectModel,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
audit: ['project.created'],
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get project by ID.
|
|
66
|
+
*/
|
|
67
|
+
export const GetProjectContract = defineQuery({
|
|
68
|
+
meta: {
|
|
69
|
+
name: 'saas.project.get',
|
|
70
|
+
version: 1,
|
|
71
|
+
stability: 'stable',
|
|
72
|
+
owners: [...OWNERS],
|
|
73
|
+
tags: ['saas', 'project', 'get'],
|
|
74
|
+
description: 'Get a project by ID.',
|
|
75
|
+
goal: 'Retrieve project details.',
|
|
76
|
+
context: 'Project detail page, API calls.',
|
|
77
|
+
},
|
|
78
|
+
io: {
|
|
79
|
+
input: GetProjectInputModel,
|
|
80
|
+
output: ProjectModel,
|
|
81
|
+
errors: {
|
|
82
|
+
NOT_FOUND: {
|
|
83
|
+
description: 'Project not found',
|
|
84
|
+
http: 404,
|
|
85
|
+
gqlCode: 'NOT_FOUND',
|
|
86
|
+
when: 'Project ID is invalid or user lacks access',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
policy: {
|
|
91
|
+
auth: 'user',
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Update a project.
|
|
97
|
+
*/
|
|
98
|
+
export const UpdateProjectContract = defineCommand({
|
|
99
|
+
meta: {
|
|
100
|
+
name: 'saas.project.update',
|
|
101
|
+
version: 1,
|
|
102
|
+
stability: 'stable',
|
|
103
|
+
owners: [...OWNERS],
|
|
104
|
+
tags: ['saas', 'project', 'update'],
|
|
105
|
+
description: 'Update project details.',
|
|
106
|
+
goal: 'Allow project owners/editors to modify project.',
|
|
107
|
+
context: 'Project settings page.',
|
|
108
|
+
},
|
|
109
|
+
io: {
|
|
110
|
+
input: UpdateProjectInputModel,
|
|
111
|
+
output: ProjectModel,
|
|
112
|
+
},
|
|
113
|
+
policy: {
|
|
114
|
+
auth: 'user',
|
|
115
|
+
},
|
|
116
|
+
sideEffects: {
|
|
117
|
+
emits: [
|
|
118
|
+
{
|
|
119
|
+
name: 'project.updated',
|
|
120
|
+
version: 1,
|
|
121
|
+
when: 'Project is updated',
|
|
122
|
+
payload: ProjectModel,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
audit: ['project.updated'],
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Delete a project.
|
|
131
|
+
*/
|
|
132
|
+
export const DeleteProjectContract = defineCommand({
|
|
133
|
+
meta: {
|
|
134
|
+
name: 'saas.project.delete',
|
|
135
|
+
version: 1,
|
|
136
|
+
stability: 'stable',
|
|
137
|
+
owners: [...OWNERS],
|
|
138
|
+
tags: ['saas', 'project', 'delete'],
|
|
139
|
+
description: 'Delete a project (soft delete).',
|
|
140
|
+
goal: 'Allow project owners to remove projects.',
|
|
141
|
+
context: 'Project settings page.',
|
|
142
|
+
},
|
|
143
|
+
io: {
|
|
144
|
+
input: DeleteProjectInputModel,
|
|
145
|
+
output: DeleteProjectOutputModel,
|
|
146
|
+
},
|
|
147
|
+
policy: {
|
|
148
|
+
auth: 'user',
|
|
149
|
+
},
|
|
150
|
+
sideEffects: {
|
|
151
|
+
emits: [
|
|
152
|
+
{
|
|
153
|
+
name: 'project.deleted',
|
|
154
|
+
version: 1,
|
|
155
|
+
when: 'Project is deleted',
|
|
156
|
+
payload: ProjectDeletedPayloadModel,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
audit: ['project.deleted'],
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* List organization projects.
|
|
165
|
+
*/
|
|
166
|
+
export const ListProjectsContract = defineQuery({
|
|
167
|
+
meta: {
|
|
168
|
+
name: 'saas.project.list',
|
|
169
|
+
version: 1,
|
|
170
|
+
stability: 'stable',
|
|
171
|
+
owners: [...OWNERS],
|
|
172
|
+
tags: ['saas', 'project', 'list'],
|
|
173
|
+
description: 'List projects in the organization.',
|
|
174
|
+
goal: 'Show all projects user has access to.',
|
|
175
|
+
context: 'Project list page, dashboard.',
|
|
176
|
+
},
|
|
177
|
+
io: {
|
|
178
|
+
input: ListProjectsInputModel,
|
|
179
|
+
output: ListProjectsOutputModel,
|
|
180
|
+
},
|
|
181
|
+
policy: {
|
|
182
|
+
auth: 'user',
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineEntity, defineEntityEnum, field, index } from '@lssm/lib.schema';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Project status enum.
|
|
4
|
+
* Project status enum for entities.
|
|
5
5
|
*/
|
|
6
6
|
export const ProjectStatusEnum = defineEntityEnum({
|
|
7
7
|
name: 'ProjectStatus',
|
|
@@ -86,3 +86,4 @@ export const ProjectMemberEntity = defineEntity({
|
|
|
86
86
|
},
|
|
87
87
|
indexes: [index.unique(['projectId', 'userId'])],
|
|
88
88
|
});
|
|
89
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineEnum } from '@lssm/lib.schema';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Project status enum for contract schemas.
|
|
5
|
+
* Note: Entity enum is defined separately in project.entity.ts
|
|
6
|
+
*/
|
|
7
|
+
export const ProjectStatusSchemaEnum = defineEnum('ProjectStatus', [
|
|
8
|
+
'DRAFT',
|
|
9
|
+
'ACTIVE',
|
|
10
|
+
'ARCHIVED',
|
|
11
|
+
'DELETED',
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Project status filter enum (includes 'all' option).
|
|
16
|
+
*/
|
|
17
|
+
export const ProjectStatusFilterEnum = defineEnum('ProjectStatusFilter', [
|
|
18
|
+
'DRAFT',
|
|
19
|
+
'ACTIVE',
|
|
20
|
+
'ARCHIVED',
|
|
21
|
+
'all',
|
|
22
|
+
]);
|
|
23
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { ScalarTypeEnum, defineSchemaModel } from '@lssm/lib.schema';
|
|
2
|
+
import { defineEvent } from '@lssm/lib.contracts';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Payload when a project is created.
|
|
6
|
+
*/
|
|
7
|
+
const ProjectCreatedPayload = defineSchemaModel({
|
|
8
|
+
name: 'ProjectCreatedPayload',
|
|
9
|
+
description: 'Payload when a project is created',
|
|
10
|
+
fields: {
|
|
11
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
12
|
+
name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
13
|
+
organizationId: {
|
|
14
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
15
|
+
isOptional: false,
|
|
16
|
+
},
|
|
17
|
+
createdBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
18
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Payload when a project is updated.
|
|
24
|
+
*/
|
|
25
|
+
const ProjectUpdatedPayload = defineSchemaModel({
|
|
26
|
+
name: 'ProjectUpdatedPayload',
|
|
27
|
+
description: 'Payload when a project is updated',
|
|
28
|
+
fields: {
|
|
29
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
30
|
+
updatedFields: {
|
|
31
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
32
|
+
isArray: true,
|
|
33
|
+
isOptional: false,
|
|
34
|
+
},
|
|
35
|
+
updatedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
36
|
+
updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Payload when a project is deleted.
|
|
42
|
+
*/
|
|
43
|
+
const ProjectDeletedPayload = defineSchemaModel({
|
|
44
|
+
name: 'ProjectDeletedPayload',
|
|
45
|
+
description: 'Payload when a project is deleted',
|
|
46
|
+
fields: {
|
|
47
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
48
|
+
organizationId: {
|
|
49
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
50
|
+
isOptional: false,
|
|
51
|
+
},
|
|
52
|
+
deletedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
53
|
+
deletedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Payload when a project is archived.
|
|
59
|
+
*/
|
|
60
|
+
const ProjectArchivedPayload = defineSchemaModel({
|
|
61
|
+
name: 'ProjectArchivedPayload',
|
|
62
|
+
description: 'Payload when a project is archived',
|
|
63
|
+
fields: {
|
|
64
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
65
|
+
archivedBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
66
|
+
archivedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Event: A new project has been created.
|
|
72
|
+
*/
|
|
73
|
+
export const ProjectCreatedEvent = defineEvent({
|
|
74
|
+
name: 'project.created',
|
|
75
|
+
version: 1,
|
|
76
|
+
description: 'A new project has been created.',
|
|
77
|
+
payload: ProjectCreatedPayload,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Event: A project has been updated.
|
|
82
|
+
*/
|
|
83
|
+
export const ProjectUpdatedEvent = defineEvent({
|
|
84
|
+
name: 'project.updated',
|
|
85
|
+
version: 1,
|
|
86
|
+
description: 'A project has been updated.',
|
|
87
|
+
payload: ProjectUpdatedPayload,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Event: A project has been deleted.
|
|
92
|
+
*/
|
|
93
|
+
export const ProjectDeletedEvent = defineEvent({
|
|
94
|
+
name: 'project.deleted',
|
|
95
|
+
version: 1,
|
|
96
|
+
description: 'A project has been deleted.',
|
|
97
|
+
payload: ProjectDeletedPayload,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Event: A project has been archived.
|
|
102
|
+
*/
|
|
103
|
+
export const ProjectArchivedEvent = defineEvent({
|
|
104
|
+
name: 'project.archived',
|
|
105
|
+
version: 1,
|
|
106
|
+
description: 'A project has been archived.',
|
|
107
|
+
payload: ProjectArchivedPayload,
|
|
108
|
+
});
|
|
109
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Mock handlers for Project contracts
|
|
2
|
+
* Mock handlers for Project contracts.
|
|
3
3
|
*/
|
|
4
|
-
import { MOCK_PROJECTS } from '
|
|
4
|
+
import { MOCK_PROJECTS } from '../shared/mock-data';
|
|
5
5
|
|
|
6
6
|
// Types inferred from contract schemas
|
|
7
7
|
export interface Project {
|
|
@@ -49,7 +49,7 @@ export interface ListProjectsOutput {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
* Mock handler for ListProjectsContract
|
|
52
|
+
* Mock handler for ListProjectsContract.
|
|
53
53
|
*/
|
|
54
54
|
export async function mockListProjectsHandler(
|
|
55
55
|
input: ListProjectsInput
|
|
@@ -72,7 +72,6 @@ export async function mockListProjectsHandler(
|
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
// Sort by updatedAt descending
|
|
76
75
|
filtered.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
77
76
|
|
|
78
77
|
const total = filtered.length;
|
|
@@ -85,7 +84,7 @@ export async function mockListProjectsHandler(
|
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
/**
|
|
88
|
-
* Mock handler for GetProjectContract
|
|
87
|
+
* Mock handler for GetProjectContract.
|
|
89
88
|
*/
|
|
90
89
|
export async function mockGetProjectHandler(input: {
|
|
91
90
|
projectId: string;
|
|
@@ -100,13 +99,12 @@ export async function mockGetProjectHandler(input: {
|
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
/**
|
|
103
|
-
* Mock handler for CreateProjectContract
|
|
102
|
+
* Mock handler for CreateProjectContract.
|
|
104
103
|
*/
|
|
105
104
|
export async function mockCreateProjectHandler(
|
|
106
105
|
input: CreateProjectInput,
|
|
107
106
|
context: { organizationId: string; userId: string }
|
|
108
107
|
): Promise<Project> {
|
|
109
|
-
// Simulate slug collision check
|
|
110
108
|
if (input.slug) {
|
|
111
109
|
const exists = MOCK_PROJECTS.some((p) => p.slug === input.slug);
|
|
112
110
|
if (exists) {
|
|
@@ -131,7 +129,7 @@ export async function mockCreateProjectHandler(
|
|
|
131
129
|
}
|
|
132
130
|
|
|
133
131
|
/**
|
|
134
|
-
* Mock handler for UpdateProjectContract
|
|
132
|
+
* Mock handler for UpdateProjectContract.
|
|
135
133
|
*/
|
|
136
134
|
export async function mockUpdateProjectHandler(
|
|
137
135
|
input: UpdateProjectInput
|
|
@@ -155,7 +153,7 @@ export async function mockUpdateProjectHandler(
|
|
|
155
153
|
}
|
|
156
154
|
|
|
157
155
|
/**
|
|
158
|
-
* Mock handler for DeleteProjectContract
|
|
156
|
+
* Mock handler for DeleteProjectContract.
|
|
159
157
|
*/
|
|
160
158
|
export async function mockDeleteProjectHandler(input: {
|
|
161
159
|
projectId: string;
|
|
@@ -168,3 +166,4 @@ export async function mockDeleteProjectHandler(input: {
|
|
|
168
166
|
|
|
169
167
|
return { success: true };
|
|
170
168
|
}
|
|
169
|
+
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project List Presentation Descriptor
|
|
3
|
-
*/
|
|
4
1
|
import type { PresentationDescriptorV2 } from '@lssm/lib.contracts';
|
|
5
|
-
import { ProjectModel } from '
|
|
2
|
+
import { ProjectModel } from './project.schema';
|
|
6
3
|
|
|
7
4
|
/**
|
|
8
5
|
* Presentation for displaying a list of projects.
|
|
@@ -51,3 +48,4 @@ export const ProjectDetailPresentation: PresentationDescriptorV2 = {
|
|
|
51
48
|
flags: ['saas.projects.enabled'],
|
|
52
49
|
},
|
|
53
50
|
};
|
|
51
|
+
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { defineSchemaModel, ScalarTypeEnum } from '@lssm/lib.schema';
|
|
2
|
+
import { ProjectStatusSchemaEnum, ProjectStatusFilterEnum } from './project.enum';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A project within an organization.
|
|
6
|
+
*/
|
|
7
|
+
export const ProjectModel = defineSchemaModel({
|
|
8
|
+
name: 'Project',
|
|
9
|
+
description: 'A project within an organization',
|
|
10
|
+
fields: {
|
|
11
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
12
|
+
name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
13
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
14
|
+
slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
15
|
+
organizationId: {
|
|
16
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
17
|
+
isOptional: false,
|
|
18
|
+
},
|
|
19
|
+
createdBy: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
20
|
+
status: { type: ProjectStatusSchemaEnum, isOptional: false },
|
|
21
|
+
isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
22
|
+
tags: {
|
|
23
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
24
|
+
isArray: true,
|
|
25
|
+
isOptional: false,
|
|
26
|
+
},
|
|
27
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
28
|
+
updatedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Input for creating a project.
|
|
34
|
+
*/
|
|
35
|
+
export const CreateProjectInputModel = defineSchemaModel({
|
|
36
|
+
name: 'CreateProjectInput',
|
|
37
|
+
description: 'Input for creating a project',
|
|
38
|
+
fields: {
|
|
39
|
+
name: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
|
|
40
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
41
|
+
slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
42
|
+
isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: true },
|
|
43
|
+
tags: {
|
|
44
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
45
|
+
isArray: true,
|
|
46
|
+
isOptional: true,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Input for updating a project.
|
|
53
|
+
*/
|
|
54
|
+
export const UpdateProjectInputModel = defineSchemaModel({
|
|
55
|
+
name: 'UpdateProjectInput',
|
|
56
|
+
description: 'Input for updating a project',
|
|
57
|
+
fields: {
|
|
58
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
59
|
+
name: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
60
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
61
|
+
slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
62
|
+
isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: true },
|
|
63
|
+
tags: {
|
|
64
|
+
type: ScalarTypeEnum.String_unsecure(),
|
|
65
|
+
isArray: true,
|
|
66
|
+
isOptional: true,
|
|
67
|
+
},
|
|
68
|
+
status: { type: ProjectStatusSchemaEnum, isOptional: true },
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Input for getting a project.
|
|
74
|
+
*/
|
|
75
|
+
export const GetProjectInputModel = defineSchemaModel({
|
|
76
|
+
name: 'GetProjectInput',
|
|
77
|
+
fields: {
|
|
78
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Input for deleting a project.
|
|
84
|
+
*/
|
|
85
|
+
export const DeleteProjectInputModel = defineSchemaModel({
|
|
86
|
+
name: 'DeleteProjectInput',
|
|
87
|
+
fields: {
|
|
88
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Output for delete operation.
|
|
94
|
+
*/
|
|
95
|
+
export const DeleteProjectOutputModel = defineSchemaModel({
|
|
96
|
+
name: 'DeleteProjectOutput',
|
|
97
|
+
fields: {
|
|
98
|
+
success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Payload for project deleted event.
|
|
104
|
+
*/
|
|
105
|
+
export const ProjectDeletedPayloadModel = defineSchemaModel({
|
|
106
|
+
name: 'ProjectDeletedPayload',
|
|
107
|
+
fields: {
|
|
108
|
+
projectId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Input for listing projects.
|
|
114
|
+
*/
|
|
115
|
+
export const ListProjectsInputModel = defineSchemaModel({
|
|
116
|
+
name: 'ListProjectsInput',
|
|
117
|
+
description: 'Input for listing projects',
|
|
118
|
+
fields: {
|
|
119
|
+
status: { type: ProjectStatusFilterEnum, isOptional: true },
|
|
120
|
+
search: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
121
|
+
limit: {
|
|
122
|
+
type: ScalarTypeEnum.Int_unsecure(),
|
|
123
|
+
isOptional: true,
|
|
124
|
+
defaultValue: 20,
|
|
125
|
+
},
|
|
126
|
+
offset: {
|
|
127
|
+
type: ScalarTypeEnum.Int_unsecure(),
|
|
128
|
+
isOptional: true,
|
|
129
|
+
defaultValue: 0,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Output for listing projects.
|
|
136
|
+
*/
|
|
137
|
+
export const ListProjectsOutputModel = defineSchemaModel({
|
|
138
|
+
name: 'ListProjectsOutput',
|
|
139
|
+
description: 'Output for listing projects',
|
|
140
|
+
fields: {
|
|
141
|
+
projects: { type: ProjectModel, isArray: true, isOptional: false },
|
|
142
|
+
total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import { defineEntity,
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Settings scope enum.
|
|
5
|
-
*/
|
|
6
|
-
export const SettingsScopeEnum = defineEntityEnum({
|
|
7
|
-
name: 'SettingsScope',
|
|
8
|
-
values: ['APP', 'ORG', 'USER', 'PROJECT'] as const,
|
|
9
|
-
schema: 'saas_app',
|
|
10
|
-
description: 'Scope of a setting.',
|
|
11
|
-
});
|
|
1
|
+
import { defineEntity, field, index } from '@lssm/lib.schema';
|
|
2
|
+
import { SettingsScopeEnum } from './settings.enum';
|
|
12
3
|
|
|
13
4
|
/**
|
|
14
5
|
* Settings entity - key-value configuration store.
|
|
@@ -96,3 +87,4 @@ export const FeatureFlagEntity = defineEntity({
|
|
|
96
87
|
updatedAt: field.updatedAt(),
|
|
97
88
|
},
|
|
98
89
|
});
|
|
90
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineEntityEnum } from '@lssm/lib.schema';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Settings scope enum.
|
|
5
|
+
*/
|
|
6
|
+
export const SettingsScopeEnum = defineEntityEnum({
|
|
7
|
+
name: 'SettingsScope',
|
|
8
|
+
values: ['APP', 'ORG', 'USER', 'PROJECT'] as const,
|
|
9
|
+
schema: 'saas_app',
|
|
10
|
+
description: 'Scope of a setting.',
|
|
11
|
+
});
|
|
12
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Shared mock data for saas-boilerplate handlers.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
// ============ Project Mock Data ============
|
|
@@ -108,3 +108,4 @@ export const MOCK_USAGE_SUMMARY = {
|
|
|
108
108
|
{ date: '2024-04-05', apiCalls: 3800, storageGb: 12.5 },
|
|
109
109
|
],
|
|
110
110
|
};
|
|
111
|
+
|