@managemint-solutions/sdk 0.4.0 → 0.5.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/README.md +29 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.js +3 -0
- package/dist/client.js.map +1 -1
- package/dist/clients/dto.d.ts +30 -0
- package/dist/clients/dto.js +181 -0
- package/dist/clients/dto.js.map +1 -0
- package/dist/clients/index.d.ts +20 -0
- package/dist/clients/index.js +269 -0
- package/dist/clients/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/validators.d.ts +2 -0
- package/dist/validators.js +8 -0
- package/dist/validators.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,8 @@ npm install @managemint-solutions/sdk @supabase/supabase-js
|
|
|
13
13
|
are peer dependencies — the request DTOs (`AddStatusDto`, `UpdateStatusDto`, `StatusIdDto`,
|
|
14
14
|
`GetStatusesDto`, `AddAdditionalDetailsDto`, `UpdateAdditionalDetailsDto`,
|
|
15
15
|
`AdditionalDetailsIdDto`, `GetAdditionalDetailsDto`, `AddNoteDto`, `NoteIdDto`,
|
|
16
|
-
`GetNotesDto`, `SupportingFileIdDto`, `GetSupportingFilesDto`
|
|
16
|
+
`GetNotesDto`, `SupportingFileIdDto`, `GetSupportingFilesDto`, `GetClientsDto`, `ClientIdDto`,
|
|
17
|
+
`CreateClientDto`, `UpdateClientDto`) ship with their class-validator
|
|
17
18
|
decorators so consumers validate against
|
|
18
19
|
the same rules the SDK's input types describe. `@nestjs/common` (^11) is an optional peer
|
|
19
20
|
dependency, needed only for the `@managemint-solutions/sdk/nest` subpath.
|
|
@@ -96,6 +97,33 @@ await supabase.supportingFiles.remove(files[0].mms_id); // deletes the row and t
|
|
|
96
97
|
Uploads run in batches of 5 and upsert, so re-uploading a file refreshes the object without
|
|
97
98
|
adding a second row; `upload` returns the entity's full file list.
|
|
98
99
|
|
|
100
|
+
```ts
|
|
101
|
+
// Clients are paginated; the query DTO's page/page_size default to 1/10.
|
|
102
|
+
const page = await supabase.clients.list({ page: 1, page_size: 10, archive: false });
|
|
103
|
+
// → { results, page, per_page, count, total_pages, has_next_page, has_previous_page }
|
|
104
|
+
// `search` matches name/email, `created_after`/`created_before` bound created_at, and
|
|
105
|
+
// `status_id_in` filters by status.
|
|
106
|
+
|
|
107
|
+
const client = await supabase.clients.create({
|
|
108
|
+
name: 'Acme',
|
|
109
|
+
email: 'hello@acme.test',
|
|
110
|
+
phone: '0123456789',
|
|
111
|
+
status_id: statusId,
|
|
112
|
+
contract_client: true,
|
|
113
|
+
contracted_hours: 40,
|
|
114
|
+
});
|
|
115
|
+
await supabase.clients.getById(client.mms_id);
|
|
116
|
+
await supabase.clients.update(client.mms_id, { ...client, name: 'Acme Ltd' });
|
|
117
|
+
await supabase.clients.archive(client.mms_id); // archived + archived_at/by
|
|
118
|
+
await supabase.clients.unarchive(client.mms_id); // archived = false + unarchived_at/by
|
|
119
|
+
await supabase.clients.remove(client.mms_id); // soft delete — deleted + deleted_at/by
|
|
120
|
+
await supabase.clients.restore(client.mms_id); // deleted = false + restored_at/by
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`getById` on a soft-deleted client returns the audit trail with the details blanked (name,
|
|
124
|
+
email and phone empty, no status, `contract_client` false, `contracted_hours` 0). Every write
|
|
125
|
+
except `remove` re-reads and returns the full record afterwards.
|
|
126
|
+
|
|
99
127
|
The client decodes `{ mms_id, organization_id }` from the JWT itself and scopes every query
|
|
100
128
|
by `organization_id`. `supabase.supabase` is the raw typed `@supabase/supabase-js` client
|
|
101
129
|
(`TypedSupabaseClient`) — the escape hatch for queries not yet covered by a resource.
|
package/dist/client.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type SupabaseClient as SupabaseJsClient } from '@supabase/supabase-js';
|
|
|
2
2
|
import type { Database } from './database.types';
|
|
3
3
|
import { type AuthContext } from './auth';
|
|
4
4
|
import { AdditionalDetailsResource } from './additional-details';
|
|
5
|
+
import { ClientsResource } from './clients';
|
|
5
6
|
import { NotesResource } from './notes';
|
|
6
7
|
import { StatusesResource } from './statuses';
|
|
7
8
|
import { SupportingFilesResource } from './supporting-files';
|
|
@@ -18,6 +19,7 @@ export declare class SupabaseClient {
|
|
|
18
19
|
readonly additionalDetails: AdditionalDetailsResource;
|
|
19
20
|
readonly notes: NotesResource;
|
|
20
21
|
readonly supportingFiles: SupportingFilesResource;
|
|
22
|
+
readonly clients: ClientsResource;
|
|
21
23
|
constructor(config: SupabaseClientConfig);
|
|
22
24
|
}
|
|
23
25
|
export declare const createSupabaseClient: (config: SupabaseClientConfig) => SupabaseClient;
|
package/dist/client.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.createSupabaseClient = exports.SupabaseClient = void 0;
|
|
|
4
4
|
const supabase_js_1 = require("@supabase/supabase-js");
|
|
5
5
|
const auth_1 = require("./auth");
|
|
6
6
|
const additional_details_1 = require("./additional-details");
|
|
7
|
+
const clients_1 = require("./clients");
|
|
7
8
|
const notes_1 = require("./notes");
|
|
8
9
|
const statuses_1 = require("./statuses");
|
|
9
10
|
const supporting_files_1 = require("./supporting-files");
|
|
@@ -14,6 +15,7 @@ class SupabaseClient {
|
|
|
14
15
|
additionalDetails;
|
|
15
16
|
notes;
|
|
16
17
|
supportingFiles;
|
|
18
|
+
clients;
|
|
17
19
|
constructor(config) {
|
|
18
20
|
this.auth = (0, auth_1.decodeAuthContext)(config.accessToken);
|
|
19
21
|
this.supabase = (0, supabase_js_1.createClient)(config.url, config.key, {
|
|
@@ -24,6 +26,7 @@ class SupabaseClient {
|
|
|
24
26
|
this.additionalDetails = new additional_details_1.AdditionalDetailsResource(this.supabase, this.auth);
|
|
25
27
|
this.notes = new notes_1.NotesResource(this.supabase, this.auth);
|
|
26
28
|
this.supportingFiles = new supporting_files_1.SupportingFilesResource(this.supabase, this.auth);
|
|
29
|
+
this.clients = new clients_1.ClientsResource(this.supabase, this.auth);
|
|
27
30
|
}
|
|
28
31
|
}
|
|
29
32
|
exports.SupabaseClient = SupabaseClient;
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,uDAA8F;AAE9F,iCAA6D;AAC7D,6DAAiE;AACjE,mCAAwC;AACxC,yCAA8C;AAC9C,yDAA6D;AAU7D,MAAa,cAAc;IAChB,QAAQ,CAAsB,CAAC,4CAA4C;IAC3E,IAAI,CAAc;IAClB,QAAQ,CAAmB;IAC3B,iBAAiB,CAA4B;IAC7C,KAAK,CAAgB;IACrB,eAAe,CAA0B;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,uDAA8F;AAE9F,iCAA6D;AAC7D,6DAAiE;AACjE,uCAA4C;AAC5C,mCAAwC;AACxC,yCAA8C;AAC9C,yDAA6D;AAU7D,MAAa,cAAc;IAChB,QAAQ,CAAsB,CAAC,4CAA4C;IAC3E,IAAI,CAAc;IAClB,QAAQ,CAAmB;IAC3B,iBAAiB,CAA4B;IAC7C,KAAK,CAAgB;IACrB,eAAe,CAA0B;IACzC,OAAO,CAAkB;IAElC,YAAY,MAA4B;QACtC,IAAI,CAAC,IAAI,GAAG,IAAA,wBAAiB,EAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,IAAA,0BAAY,EAAW,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE;YAC7D,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE;YACtE,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE;SACzD,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,2BAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,iBAAiB,GAAG,IAAI,8CAAyB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjF,IAAI,CAAC,KAAK,GAAG,IAAI,qBAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,eAAe,GAAG,IAAI,0CAAuB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,IAAI,CAAC,OAAO,GAAG,IAAI,yBAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;CACF;AArBD,wCAqBC;AAEM,MAAM,oBAAoB,GAAG,CAAC,MAA4B,EAAkB,EAAE,CACnF,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AADhB,QAAA,oBAAoB,wBACJ"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { UUID } from 'crypto';
|
|
2
|
+
import type { ClientIdDto as ClientIdDtoType, CreateClientDto as CreateClientDtoType, GetClientsDto as GetClientsDtoType, UpdateClientDto as UpdateClientDtoType } from '@managemint-solutions/entities/clients/dto';
|
|
3
|
+
export declare class GetClientsDto implements Omit<GetClientsDtoType, 'status_id_in'> {
|
|
4
|
+
readonly search?: string | null;
|
|
5
|
+
readonly page: number;
|
|
6
|
+
readonly page_size: number;
|
|
7
|
+
readonly created_after?: string | null;
|
|
8
|
+
readonly created_before?: string | null;
|
|
9
|
+
readonly status_id_in?: string[] | null;
|
|
10
|
+
readonly archive: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare class ClientIdDto implements ClientIdDtoType {
|
|
13
|
+
readonly clientId: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class CreateClientDto implements CreateClientDtoType {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly email: string | null;
|
|
18
|
+
readonly phone: string | null;
|
|
19
|
+
readonly status_id: UUID | null;
|
|
20
|
+
readonly contract_client: boolean;
|
|
21
|
+
readonly contracted_hours: number | null;
|
|
22
|
+
}
|
|
23
|
+
export declare class UpdateClientDto implements UpdateClientDtoType {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly email: string | null;
|
|
26
|
+
readonly phone: string | null;
|
|
27
|
+
readonly status_id: UUID | null;
|
|
28
|
+
readonly contract_client: boolean;
|
|
29
|
+
readonly contracted_hours: number | null;
|
|
30
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.UpdateClientDto = exports.CreateClientDto = exports.ClientIdDto = exports.GetClientsDto = void 0;
|
|
13
|
+
const class_validator_1 = require("class-validator");
|
|
14
|
+
const class_transformer_1 = require("class-transformer");
|
|
15
|
+
const validators_1 = require("../validators");
|
|
16
|
+
// class-validator versions of the shared DTO types from @managemint-solutions/entities, so the
|
|
17
|
+
// wire contract cannot drift. `status_id` is typed as the entities' `UUID | null` for the same
|
|
18
|
+
// reason; class-validator only sees the runtime string.
|
|
19
|
+
// `status_id_in` is omitted from the implemented type on purpose: the entities type carries the
|
|
20
|
+
// CSV wire value (`string | null`), while this class carries the `@Transform`-parsed
|
|
21
|
+
// `string[] | null` the query builder feeds to `.in('status_id', ...)`.
|
|
22
|
+
class GetClientsDto {
|
|
23
|
+
search;
|
|
24
|
+
page = 1;
|
|
25
|
+
page_size = 10;
|
|
26
|
+
created_after;
|
|
27
|
+
created_before;
|
|
28
|
+
status_id_in;
|
|
29
|
+
archive = false;
|
|
30
|
+
}
|
|
31
|
+
exports.GetClientsDto = GetClientsDto;
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, validators_1.IsNullable)(),
|
|
35
|
+
(0, class_validator_1.IsString)({ message: 'Search query must be a string' }),
|
|
36
|
+
(0, class_validator_1.MinLength)(1, { message: 'Search query cannot be empty' }),
|
|
37
|
+
(0, class_validator_1.MaxLength)(255, { message: 'Search query cannot exceed 255 characters' }),
|
|
38
|
+
__metadata("design:type", Object)
|
|
39
|
+
], GetClientsDto.prototype, "search", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, class_validator_1.IsOptional)(),
|
|
42
|
+
(0, class_transformer_1.Transform)(({ value }) => value ? Number(value) : 1, { toClassOnly: true }),
|
|
43
|
+
(0, class_validator_1.IsNumber)({}, { message: 'Page must be a number' }),
|
|
44
|
+
(0, class_validator_1.Min)(1, { message: 'Page must be at least 1' }),
|
|
45
|
+
__metadata("design:type", Number)
|
|
46
|
+
], GetClientsDto.prototype, "page", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, class_validator_1.IsOptional)(),
|
|
49
|
+
(0, class_transformer_1.Transform)(({ value }) => value ? Number(value) : 10, { toClassOnly: true }),
|
|
50
|
+
(0, class_validator_1.IsNumber)({}, { message: 'Page size must be a number' }),
|
|
51
|
+
(0, class_validator_1.Min)(1, { message: 'Page size must be at least 1' }),
|
|
52
|
+
(0, class_validator_1.Max)(100, { message: 'Page size cannot exceed 100' }),
|
|
53
|
+
__metadata("design:type", Number)
|
|
54
|
+
], GetClientsDto.prototype, "page_size", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, class_validator_1.IsOptional)(),
|
|
57
|
+
(0, validators_1.IsNullable)(),
|
|
58
|
+
(0, class_validator_1.IsDateString)({}, { message: 'Start date must be a valid ISO 8601 date string' }),
|
|
59
|
+
__metadata("design:type", Object)
|
|
60
|
+
], GetClientsDto.prototype, "created_after", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, class_validator_1.IsOptional)(),
|
|
63
|
+
(0, validators_1.IsNullable)(),
|
|
64
|
+
(0, class_validator_1.IsDateString)({}, { message: 'End date must be a valid ISO 8601 date string' }),
|
|
65
|
+
__metadata("design:type", Object)
|
|
66
|
+
], GetClientsDto.prototype, "created_before", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, class_validator_1.IsOptional)(),
|
|
69
|
+
(0, validators_1.IsNullable)(),
|
|
70
|
+
(0, class_transformer_1.Transform)(({ value }) => value ? value.split(',').map((id) => id.trim()) : null, { toClassOnly: true }),
|
|
71
|
+
(0, class_validator_1.IsUUID)('4', { each: true, message: 'Each status ID must be a valid UUID v4' }),
|
|
72
|
+
__metadata("design:type", Object)
|
|
73
|
+
], GetClientsDto.prototype, "status_id_in", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
(0, class_validator_1.IsOptional)(),
|
|
76
|
+
(0, validators_1.IsNullable)(),
|
|
77
|
+
(0, class_transformer_1.Transform)(({ value }) => value ? value === 'true' : false, { toClassOnly: true }),
|
|
78
|
+
(0, class_validator_1.IsBoolean)({ message: 'Include archived must be a boolean' }),
|
|
79
|
+
__metadata("design:type", Boolean)
|
|
80
|
+
], GetClientsDto.prototype, "archive", void 0);
|
|
81
|
+
class ClientIdDto {
|
|
82
|
+
clientId;
|
|
83
|
+
}
|
|
84
|
+
exports.ClientIdDto = ClientIdDto;
|
|
85
|
+
__decorate([
|
|
86
|
+
(0, class_validator_1.IsUUID)('4', { message: 'Invalid client ID format' }),
|
|
87
|
+
__metadata("design:type", String)
|
|
88
|
+
], ClientIdDto.prototype, "clientId", void 0);
|
|
89
|
+
class CreateClientDto {
|
|
90
|
+
name;
|
|
91
|
+
email;
|
|
92
|
+
phone;
|
|
93
|
+
status_id;
|
|
94
|
+
contract_client;
|
|
95
|
+
contracted_hours;
|
|
96
|
+
}
|
|
97
|
+
exports.CreateClientDto = CreateClientDto;
|
|
98
|
+
__decorate([
|
|
99
|
+
(0, class_validator_1.IsString)({ message: 'Invalid name' }),
|
|
100
|
+
(0, class_validator_1.MinLength)(1, { message: 'Name cannot be empty' }),
|
|
101
|
+
(0, class_validator_1.MaxLength)(100, { message: 'Name cannot exceed 100 characters' }),
|
|
102
|
+
__metadata("design:type", String)
|
|
103
|
+
], CreateClientDto.prototype, "name", void 0);
|
|
104
|
+
__decorate([
|
|
105
|
+
(0, validators_1.IsNullable)(),
|
|
106
|
+
(0, class_transformer_1.Transform)(({ value }) => value !== undefined ? value : null, { toClassOnly: true }),
|
|
107
|
+
(0, class_validator_1.ValidateIf)((o) => o.email !== ''),
|
|
108
|
+
(0, class_validator_1.IsEmail)({}, { message: 'Invalid email address' }),
|
|
109
|
+
__metadata("design:type", Object)
|
|
110
|
+
], CreateClientDto.prototype, "email", void 0);
|
|
111
|
+
__decorate([
|
|
112
|
+
(0, validators_1.IsNullable)(),
|
|
113
|
+
(0, class_transformer_1.Transform)(({ value }) => value !== undefined ? value : null, { toClassOnly: true }),
|
|
114
|
+
(0, class_validator_1.ValidateIf)((o) => o.phone !== ''),
|
|
115
|
+
(0, class_validator_1.IsString)({ message: 'Invalid phone number' }),
|
|
116
|
+
(0, class_validator_1.MinLength)(1, { message: 'Phone number cannot be empty' }),
|
|
117
|
+
__metadata("design:type", Object)
|
|
118
|
+
], CreateClientDto.prototype, "phone", void 0);
|
|
119
|
+
__decorate([
|
|
120
|
+
(0, validators_1.IsNullable)(),
|
|
121
|
+
(0, class_validator_1.IsUUID)('4', { message: 'Invalid status ID format' }),
|
|
122
|
+
__metadata("design:type", Object)
|
|
123
|
+
], CreateClientDto.prototype, "status_id", void 0);
|
|
124
|
+
__decorate([
|
|
125
|
+
(0, class_validator_1.IsBoolean)({ message: 'Contract client must be a boolean' }),
|
|
126
|
+
__metadata("design:type", Boolean)
|
|
127
|
+
], CreateClientDto.prototype, "contract_client", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
(0, validators_1.IsNullable)(),
|
|
130
|
+
(0, class_transformer_1.Transform)(({ value }) => value !== undefined ? Number(value) : null, { toClassOnly: true }),
|
|
131
|
+
(0, class_validator_1.IsNumber)({}, { message: 'Contracted hours must be a number' }),
|
|
132
|
+
(0, class_validator_1.Min)(0, { message: 'Contracted hours must be at least 0' }),
|
|
133
|
+
__metadata("design:type", Object)
|
|
134
|
+
], CreateClientDto.prototype, "contracted_hours", void 0);
|
|
135
|
+
class UpdateClientDto {
|
|
136
|
+
name;
|
|
137
|
+
email;
|
|
138
|
+
phone;
|
|
139
|
+
status_id;
|
|
140
|
+
contract_client;
|
|
141
|
+
contracted_hours;
|
|
142
|
+
}
|
|
143
|
+
exports.UpdateClientDto = UpdateClientDto;
|
|
144
|
+
__decorate([
|
|
145
|
+
(0, class_validator_1.IsString)({ message: 'Invalid name' }),
|
|
146
|
+
(0, class_validator_1.MinLength)(1, { message: 'Name cannot be empty' }),
|
|
147
|
+
(0, class_validator_1.MaxLength)(100, { message: 'Name cannot exceed 100 characters' }),
|
|
148
|
+
__metadata("design:type", String)
|
|
149
|
+
], UpdateClientDto.prototype, "name", void 0);
|
|
150
|
+
__decorate([
|
|
151
|
+
(0, validators_1.IsNullable)(),
|
|
152
|
+
(0, class_transformer_1.Transform)(({ value }) => value !== undefined ? value : null, { toClassOnly: true }),
|
|
153
|
+
(0, class_validator_1.ValidateIf)((o) => o.email !== ''),
|
|
154
|
+
(0, class_validator_1.IsEmail)({}, { message: 'Invalid email address' }),
|
|
155
|
+
__metadata("design:type", Object)
|
|
156
|
+
], UpdateClientDto.prototype, "email", void 0);
|
|
157
|
+
__decorate([
|
|
158
|
+
(0, validators_1.IsNullable)(),
|
|
159
|
+
(0, class_transformer_1.Transform)(({ value }) => value !== undefined ? value : null, { toClassOnly: true }),
|
|
160
|
+
(0, class_validator_1.ValidateIf)((o) => o.phone !== ''),
|
|
161
|
+
(0, class_validator_1.IsString)({ message: 'Invalid phone number' }),
|
|
162
|
+
(0, class_validator_1.MinLength)(1, { message: 'Phone number cannot be empty' }),
|
|
163
|
+
__metadata("design:type", Object)
|
|
164
|
+
], UpdateClientDto.prototype, "phone", void 0);
|
|
165
|
+
__decorate([
|
|
166
|
+
(0, validators_1.IsNullable)(),
|
|
167
|
+
(0, class_validator_1.IsUUID)('4', { message: 'Invalid status ID format' }),
|
|
168
|
+
__metadata("design:type", Object)
|
|
169
|
+
], UpdateClientDto.prototype, "status_id", void 0);
|
|
170
|
+
__decorate([
|
|
171
|
+
(0, class_validator_1.IsBoolean)({ message: 'Contract client must be a boolean' }),
|
|
172
|
+
__metadata("design:type", Boolean)
|
|
173
|
+
], UpdateClientDto.prototype, "contract_client", void 0);
|
|
174
|
+
__decorate([
|
|
175
|
+
(0, validators_1.IsNullable)(),
|
|
176
|
+
(0, class_transformer_1.Transform)(({ value }) => value !== undefined ? Number(value) : null, { toClassOnly: true }),
|
|
177
|
+
(0, class_validator_1.IsNumber)({}, { message: 'Contracted hours must be a number' }),
|
|
178
|
+
(0, class_validator_1.Min)(0, { message: 'Contracted hours must be at least 0' }),
|
|
179
|
+
__metadata("design:type", Object)
|
|
180
|
+
], UpdateClientDto.prototype, "contracted_hours", void 0);
|
|
181
|
+
//# sourceMappingURL=dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/clients/dto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ClientEntity, ClientSummary } from '@managemint-solutions/entities/clients';
|
|
2
|
+
import type { MmsList } from '@managemint-solutions/entities/common';
|
|
3
|
+
import type { AuthContext } from '../auth';
|
|
4
|
+
import type { TypedSupabaseClient } from '../client';
|
|
5
|
+
import type { CreateClientDto, GetClientsDto, UpdateClientDto } from './dto';
|
|
6
|
+
export * from './dto';
|
|
7
|
+
export declare class ClientsResource {
|
|
8
|
+
private readonly supabase;
|
|
9
|
+
private readonly auth;
|
|
10
|
+
constructor(supabase: TypedSupabaseClient, auth: AuthContext);
|
|
11
|
+
list(query: GetClientsDto): Promise<MmsList<ClientSummary>>;
|
|
12
|
+
getById(clientId: string): Promise<ClientEntity>;
|
|
13
|
+
create(input: CreateClientDto): Promise<ClientEntity>;
|
|
14
|
+
update(clientId: string, input: UpdateClientDto): Promise<ClientEntity>;
|
|
15
|
+
archive(clientId: string): Promise<ClientEntity>;
|
|
16
|
+
unarchive(clientId: string): Promise<ClientEntity>;
|
|
17
|
+
restore(clientId: string): Promise<ClientEntity>;
|
|
18
|
+
/** Soft delete — the row stays, flagged `deleted`, and `restore()` brings it back. */
|
|
19
|
+
remove(clientId: string): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.ClientsResource = void 0;
|
|
18
|
+
const errors_1 = require("../errors");
|
|
19
|
+
__exportStar(require("./dto"), exports);
|
|
20
|
+
// The queries are typed by the generated Database schema (so the select strings and the
|
|
21
|
+
// insert/update payloads are checked); the public contract is the shared ClientSummary /
|
|
22
|
+
// ClientEntity from @managemint-solutions/entities. The two shapes legitimately differ, hence
|
|
23
|
+
// `as unknown as`: the embedded user_profiles/statuses rows are all-nullable view rows where the
|
|
24
|
+
// entities declare UserIdentity/StatusEntity, and the timestamp columns are ISO strings where the
|
|
25
|
+
// entities declare Date.
|
|
26
|
+
const CLIENT_LIST_SELECT = `
|
|
27
|
+
mms_id,
|
|
28
|
+
created_at,
|
|
29
|
+
name,
|
|
30
|
+
email,
|
|
31
|
+
status:statuses!status_id (
|
|
32
|
+
mms_id,
|
|
33
|
+
colour,
|
|
34
|
+
label
|
|
35
|
+
),
|
|
36
|
+
created_by:user_profiles!created_by (*)
|
|
37
|
+
`;
|
|
38
|
+
const CLIENT_DETAIL_SELECT = `
|
|
39
|
+
mms_id,
|
|
40
|
+
created_at,
|
|
41
|
+
name,
|
|
42
|
+
email,
|
|
43
|
+
phone,
|
|
44
|
+
status:statuses!status_id (
|
|
45
|
+
mms_id,
|
|
46
|
+
label,
|
|
47
|
+
colour
|
|
48
|
+
),
|
|
49
|
+
contract_client,
|
|
50
|
+
contracted_hours,
|
|
51
|
+
updated_at,
|
|
52
|
+
last_updated_by:user_profiles!last_updated_by (
|
|
53
|
+
mms_id,
|
|
54
|
+
name,
|
|
55
|
+
surname,
|
|
56
|
+
email,
|
|
57
|
+
profile_image
|
|
58
|
+
),
|
|
59
|
+
created_by:user_profiles!created_by (
|
|
60
|
+
mms_id,
|
|
61
|
+
name,
|
|
62
|
+
surname,
|
|
63
|
+
email,
|
|
64
|
+
profile_image
|
|
65
|
+
),
|
|
66
|
+
archived,
|
|
67
|
+
archived_at,
|
|
68
|
+
archived_by:user_profiles!archived_by (
|
|
69
|
+
mms_id,
|
|
70
|
+
name,
|
|
71
|
+
surname,
|
|
72
|
+
email,
|
|
73
|
+
profile_image
|
|
74
|
+
),
|
|
75
|
+
unarchived_at,
|
|
76
|
+
unarchived_by:user_profiles!unarchived_by (
|
|
77
|
+
mms_id,
|
|
78
|
+
name,
|
|
79
|
+
surname,
|
|
80
|
+
email,
|
|
81
|
+
profile_image
|
|
82
|
+
),
|
|
83
|
+
deleted,
|
|
84
|
+
deleted_at,
|
|
85
|
+
deleted_by:user_profiles!deleted_by (
|
|
86
|
+
mms_id,
|
|
87
|
+
name,
|
|
88
|
+
surname,
|
|
89
|
+
email,
|
|
90
|
+
profile_image
|
|
91
|
+
),
|
|
92
|
+
restored_at,
|
|
93
|
+
restored_by:user_profiles!restored_by (
|
|
94
|
+
mms_id,
|
|
95
|
+
name,
|
|
96
|
+
surname,
|
|
97
|
+
email,
|
|
98
|
+
profile_image
|
|
99
|
+
)
|
|
100
|
+
`;
|
|
101
|
+
class ClientsResource {
|
|
102
|
+
supabase;
|
|
103
|
+
auth;
|
|
104
|
+
constructor(supabase, auth) {
|
|
105
|
+
this.supabase = supabase;
|
|
106
|
+
this.auth = auth;
|
|
107
|
+
}
|
|
108
|
+
async list(query) {
|
|
109
|
+
const page = query.page;
|
|
110
|
+
const pageSize = query.page_size;
|
|
111
|
+
const offset = (page - 1) * pageSize;
|
|
112
|
+
const trimmedSearch = query.search?.trim();
|
|
113
|
+
// `order`/`range` return `this`, so the builder stays a filter builder and the conditional
|
|
114
|
+
// filters below can be reassigned onto it without a cast.
|
|
115
|
+
let clientsQuery = this.supabase
|
|
116
|
+
.from('clients')
|
|
117
|
+
.select(CLIENT_LIST_SELECT, { count: 'estimated' })
|
|
118
|
+
.eq('organization_id', this.auth.organization_id)
|
|
119
|
+
.eq('archived', query.archive)
|
|
120
|
+
.eq('deleted', false)
|
|
121
|
+
.order('created_at', { ascending: false })
|
|
122
|
+
.range(offset, offset + pageSize - 1);
|
|
123
|
+
if (trimmedSearch) {
|
|
124
|
+
const escapedSearch = trimmedSearch.replace(/,/g, '\\,');
|
|
125
|
+
clientsQuery = clientsQuery.or(`name.ilike.%${escapedSearch}%,email.ilike.%${escapedSearch}%`);
|
|
126
|
+
}
|
|
127
|
+
if (query.created_after) {
|
|
128
|
+
clientsQuery = clientsQuery.gte('created_at', query.created_after);
|
|
129
|
+
}
|
|
130
|
+
if (query.created_before) {
|
|
131
|
+
clientsQuery = clientsQuery.lte('created_at', query.created_before);
|
|
132
|
+
}
|
|
133
|
+
if (query.status_id_in && query.status_id_in.length > 0) {
|
|
134
|
+
clientsQuery = clientsQuery.in('status_id', query.status_id_in);
|
|
135
|
+
}
|
|
136
|
+
const { data, error, count } = await clientsQuery;
|
|
137
|
+
if (error)
|
|
138
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
139
|
+
const totalEstimated = count ?? 0;
|
|
140
|
+
const totalPages = totalEstimated > 0 ? Math.ceil(totalEstimated / pageSize) : 0;
|
|
141
|
+
return {
|
|
142
|
+
results: (data ?? []),
|
|
143
|
+
page,
|
|
144
|
+
per_page: pageSize,
|
|
145
|
+
count: totalEstimated,
|
|
146
|
+
total_pages: totalPages,
|
|
147
|
+
has_next_page: page < totalPages,
|
|
148
|
+
has_previous_page: page > 1,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async getById(clientId) {
|
|
152
|
+
const { data, error } = await this.supabase
|
|
153
|
+
.from('clients')
|
|
154
|
+
.select(CLIENT_DETAIL_SELECT)
|
|
155
|
+
.eq('organization_id', this.auth.organization_id)
|
|
156
|
+
.eq('mms_id', clientId)
|
|
157
|
+
.single();
|
|
158
|
+
if (error)
|
|
159
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
160
|
+
// A soft-deleted client keeps its audit trail but gives up its details.
|
|
161
|
+
if (data.deleted) {
|
|
162
|
+
return {
|
|
163
|
+
...data,
|
|
164
|
+
name: '',
|
|
165
|
+
email: '',
|
|
166
|
+
phone: '',
|
|
167
|
+
status: null,
|
|
168
|
+
contract_client: false,
|
|
169
|
+
contracted_hours: 0,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return data;
|
|
173
|
+
}
|
|
174
|
+
async create(input) {
|
|
175
|
+
const { data, error } = await this.supabase
|
|
176
|
+
.from('clients')
|
|
177
|
+
.insert({
|
|
178
|
+
...input,
|
|
179
|
+
organization_id: this.auth.organization_id,
|
|
180
|
+
created_by: this.auth.mms_id,
|
|
181
|
+
created_at: new Date().toISOString(),
|
|
182
|
+
})
|
|
183
|
+
.select('mms_id')
|
|
184
|
+
.single();
|
|
185
|
+
if (error)
|
|
186
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
187
|
+
return this.getById(data.mms_id);
|
|
188
|
+
}
|
|
189
|
+
async update(clientId, input) {
|
|
190
|
+
const { data, error } = await this.supabase
|
|
191
|
+
.from('clients')
|
|
192
|
+
.update({
|
|
193
|
+
...input,
|
|
194
|
+
last_updated_by: this.auth.mms_id,
|
|
195
|
+
updated_at: new Date().toISOString(),
|
|
196
|
+
})
|
|
197
|
+
.eq('organization_id', this.auth.organization_id)
|
|
198
|
+
.eq('mms_id', clientId)
|
|
199
|
+
.select('mms_id')
|
|
200
|
+
.single();
|
|
201
|
+
if (error)
|
|
202
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
203
|
+
return this.getById(data.mms_id);
|
|
204
|
+
}
|
|
205
|
+
async archive(clientId) {
|
|
206
|
+
const { data, error } = await this.supabase
|
|
207
|
+
.from('clients')
|
|
208
|
+
.update({
|
|
209
|
+
archived: true,
|
|
210
|
+
archived_at: new Date().toISOString(),
|
|
211
|
+
archived_by: this.auth.mms_id,
|
|
212
|
+
})
|
|
213
|
+
.eq('organization_id', this.auth.organization_id)
|
|
214
|
+
.eq('mms_id', clientId)
|
|
215
|
+
.select('mms_id')
|
|
216
|
+
.single();
|
|
217
|
+
if (error)
|
|
218
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
219
|
+
return this.getById(data.mms_id);
|
|
220
|
+
}
|
|
221
|
+
async unarchive(clientId) {
|
|
222
|
+
const { data, error } = await this.supabase
|
|
223
|
+
.from('clients')
|
|
224
|
+
.update({
|
|
225
|
+
archived: false,
|
|
226
|
+
unarchived_at: new Date().toISOString(),
|
|
227
|
+
unarchived_by: this.auth.mms_id,
|
|
228
|
+
})
|
|
229
|
+
.eq('organization_id', this.auth.organization_id)
|
|
230
|
+
.eq('mms_id', clientId)
|
|
231
|
+
.select('mms_id')
|
|
232
|
+
.single();
|
|
233
|
+
if (error)
|
|
234
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
235
|
+
return this.getById(data.mms_id);
|
|
236
|
+
}
|
|
237
|
+
async restore(clientId) {
|
|
238
|
+
const { data, error } = await this.supabase
|
|
239
|
+
.from('clients')
|
|
240
|
+
.update({
|
|
241
|
+
deleted: false,
|
|
242
|
+
restored_at: new Date().toISOString(),
|
|
243
|
+
restored_by: this.auth.mms_id,
|
|
244
|
+
})
|
|
245
|
+
.eq('organization_id', this.auth.organization_id)
|
|
246
|
+
.eq('mms_id', clientId)
|
|
247
|
+
.select('mms_id')
|
|
248
|
+
.single();
|
|
249
|
+
if (error)
|
|
250
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
251
|
+
return this.getById(data.mms_id);
|
|
252
|
+
}
|
|
253
|
+
/** Soft delete — the row stays, flagged `deleted`, and `restore()` brings it back. */
|
|
254
|
+
async remove(clientId) {
|
|
255
|
+
const { error } = await this.supabase
|
|
256
|
+
.from('clients')
|
|
257
|
+
.update({
|
|
258
|
+
deleted: true,
|
|
259
|
+
deleted_at: new Date().toISOString(),
|
|
260
|
+
deleted_by: this.auth.mms_id,
|
|
261
|
+
})
|
|
262
|
+
.eq('organization_id', this.auth.organization_id)
|
|
263
|
+
.eq('mms_id', clientId);
|
|
264
|
+
if (error)
|
|
265
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
exports.ClientsResource = ClientsResource;
|
|
269
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/clients/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from './client';
|
|
2
2
|
export * from './auth';
|
|
3
3
|
export * from './errors';
|
|
4
|
+
export * from './validators';
|
|
4
5
|
export * from './statuses';
|
|
5
6
|
export * from './additional-details';
|
|
6
7
|
export * from './notes';
|
|
7
8
|
export * from './supporting-files';
|
|
9
|
+
export * from './clients';
|
|
8
10
|
export type { Database, Tables, TablesInsert, TablesUpdate, Json } from './database.types';
|
package/dist/index.js
CHANGED
|
@@ -17,8 +17,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./client"), exports);
|
|
18
18
|
__exportStar(require("./auth"), exports);
|
|
19
19
|
__exportStar(require("./errors"), exports);
|
|
20
|
+
__exportStar(require("./validators"), exports);
|
|
20
21
|
__exportStar(require("./statuses"), exports);
|
|
21
22
|
__exportStar(require("./additional-details"), exports);
|
|
22
23
|
__exportStar(require("./notes"), exports);
|
|
23
24
|
__exportStar(require("./supporting-files"), exports);
|
|
25
|
+
__exportStar(require("./clients"), exports);
|
|
24
26
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,yCAAuB;AACvB,2CAAyB;AACzB,6CAA2B;AAC3B,uDAAqC;AACrC,0CAAwB;AACxB,qDAAmC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,yCAAuB;AACvB,2CAAyB;AACzB,+CAA6B;AAC7B,6CAA2B;AAC3B,uDAAqC;AACrC,0CAAwB;AACxB,qDAAmC;AACnC,4CAA0B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IsNullable = IsNullable;
|
|
4
|
+
const class_validator_1 = require("class-validator");
|
|
5
|
+
function IsNullable(validationOptions) {
|
|
6
|
+
return (0, class_validator_1.ValidateIf)((_object, value) => value !== null, validationOptions);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":";;AAEA,gCAEC;AAJD,qDAAgE;AAEhE,SAAgB,UAAU,CAAC,iBAAqC;IAC9D,OAAO,IAAA,4BAAU,EAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,EAAE,iBAAiB,CAAC,CAAC;AAC3E,CAAC"}
|
package/package.json
CHANGED