@managemint-solutions/sdk 0.1.0 → 0.3.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 CHANGED
@@ -11,14 +11,17 @@ npm install @managemint-solutions/sdk @supabase/supabase-js
11
11
 
12
12
  `@supabase/supabase-js` (^2.103.0), `class-validator` (^0.15) and `class-transformer` (^0.5)
13
13
  are peer dependencies — the request DTOs (`AddStatusDto`, `UpdateStatusDto`, `StatusIdDto`,
14
- `GetStatusesDto`) ship with their class-validator decorators so consumers validate against
14
+ `GetStatusesDto`, `AddAdditionalDetailsDto`, `UpdateAdditionalDetailsDto`,
15
+ `AdditionalDetailsIdDto`, `GetAdditionalDetailsDto`, `AddNoteDto`, `NoteIdDto`,
16
+ `GetNotesDto`) ship with their class-validator
17
+ decorators so consumers validate against
15
18
  the same rules the SDK's input types describe. `@nestjs/common` (^11) is an optional peer
16
19
  dependency, needed only for the `@managemint-solutions/sdk/nest` subpath.
17
20
 
18
21
  ## Usage
19
22
 
20
23
  ```ts
21
- import { createSupabaseClient, isPostgrestError } from '@managemint-solutions/sdk';
24
+ import { createSupabaseClient } from '@managemint-solutions/sdk';
22
25
  import type { StatusEntity } from '@managemint-solutions/entities/status';
23
26
  import { StatusEntityTypes } from '@managemint-solutions/entities/status/enum';
24
27
 
@@ -39,6 +42,45 @@ await supabase.statuses.update(created.mms_id, { label: 'Doing', colour: '#2ecc7
39
42
  await supabase.statuses.remove(created.mms_id);
40
43
  ```
41
44
 
45
+ ```ts
46
+ import { AdditionalDetailsEntityTypes, AdditionalDetailsTypes } from '@managemint-solutions/entities/additional-details/enum';
47
+
48
+ // Additional details hang off another entity, so reads and writes take (entity, entityId).
49
+ const details = await supabase.additionalDetails.list(AdditionalDetailsEntityTypes.PROJECT, projectId);
50
+ const detail = await supabase.additionalDetails.create(
51
+ AdditionalDetailsEntityTypes.PROJECT,
52
+ projectId,
53
+ { key: 'Reference', value: 'INV-1001', type: AdditionalDetailsTypes.Text, copyable: true },
54
+ );
55
+ await supabase.additionalDetails.getById(detail.mms_id);
56
+ await supabase.additionalDetails.update(detail.mms_id, {
57
+ key: 'Reference',
58
+ value: 42,
59
+ type: AdditionalDetailsTypes.Number,
60
+ copyable: false,
61
+ });
62
+ await supabase.additionalDetails.remove(detail.mms_id);
63
+ ```
64
+
65
+ The `value` column is `text`; the SDK serializes on write and casts back on read according to the
66
+ row's `type` (`number` → `Number`, `boolean`, `date` → `Date`, `url` → `URL`).
67
+
68
+ ```ts
69
+ import { NotesEntityTypes } from '@managemint-solutions/entities/notes/enum';
70
+
71
+ // Notes hang off another entity too, so reads and writes take (entity, entityId).
72
+ const notes = await supabase.notes.list(NotesEntityTypes.PROJECT, projectId);
73
+ const note = await supabase.notes.create(NotesEntityTypes.PROJECT, projectId, {
74
+ content: 'Called the client to confirm the site visit.',
75
+ });
76
+ await supabase.notes.getById(note.mms_id);
77
+ await supabase.notes.togglePin(note.mms_id); // flips `pinned` and returns the refreshed note
78
+ await supabase.notes.remove(note.mms_id);
79
+ ```
80
+
81
+ Each note carries its author as an embedded `user` (from the `user_profiles` view), and `list`
82
+ returns newest first.
83
+
42
84
  The client decodes `{ mms_id, organization_id }` from the JWT itself and scopes every query
43
85
  by `organization_id`. `supabase.supabase` is the raw typed `@supabase/supabase-js` client
44
86
  (`TypedSupabaseClient`) — the escape hatch for queries not yet covered by a resource.
@@ -0,0 +1,27 @@
1
+ import { type ValidationOptions } from 'class-validator';
2
+ import type { AddAdditionalDetailsDto as AddAdditionalDetailsDtoType, AdditionalDetailsIdDto as AdditionalDetailsIdDtoType, GetAdditionalDetailsDto as GetAdditionalDetailsDtoType, UpdateAdditionalDetailsDto as UpdateAdditionalDetailsDtoType } from '@managemint-solutions/entities/additional-details/dto';
3
+ import { AdditionalDetailsEntityTypes, AdditionalDetailsTypes } from '@managemint-solutions/entities/additional-details/enum';
4
+ import type { TablesInsert } from '../database.types';
5
+ /** Validates `value` against the sibling `type` property (the discriminator). */
6
+ export declare function IsAdditionalDetailsValueByType(typeProperty: string, validationOptions?: ValidationOptions): (object: object, propertyName: string) => void;
7
+ type AdditionalDetailsInsertColumns = Required<Pick<TablesInsert<'additional_details'>, 'key' | 'copyable'>>;
8
+ export declare class AdditionalDetailsIdDto implements AdditionalDetailsIdDtoType {
9
+ readonly additionalDetailsId: string;
10
+ }
11
+ export declare class GetAdditionalDetailsDto implements GetAdditionalDetailsDtoType {
12
+ readonly entity: AdditionalDetailsEntityTypes;
13
+ readonly entityId: string;
14
+ }
15
+ export declare class AddAdditionalDetailsDto implements AddAdditionalDetailsDtoType, AdditionalDetailsInsertColumns {
16
+ readonly key: string;
17
+ readonly value: string | number | boolean | Date | URL;
18
+ readonly type: AdditionalDetailsTypes;
19
+ readonly copyable: boolean;
20
+ }
21
+ export declare class UpdateAdditionalDetailsDto implements UpdateAdditionalDetailsDtoType, AdditionalDetailsInsertColumns {
22
+ readonly key: string;
23
+ readonly value: string | number | boolean;
24
+ readonly type: AdditionalDetailsTypes;
25
+ readonly copyable: boolean;
26
+ }
27
+ export {};
@@ -0,0 +1,142 @@
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.UpdateAdditionalDetailsDto = exports.AddAdditionalDetailsDto = exports.GetAdditionalDetailsDto = exports.AdditionalDetailsIdDto = void 0;
13
+ exports.IsAdditionalDetailsValueByType = IsAdditionalDetailsValueByType;
14
+ const class_validator_1 = require("class-validator");
15
+ const enum_1 = require("@managemint-solutions/entities/additional-details/enum");
16
+ /** Validates `value` against the sibling `type` property (the discriminator). */
17
+ function IsAdditionalDetailsValueByType(typeProperty, validationOptions) {
18
+ return function (object, propertyName) {
19
+ (0, class_validator_1.registerDecorator)({
20
+ name: 'isAdditionalDetailsValueByType',
21
+ target: object.constructor,
22
+ propertyName,
23
+ constraints: [typeProperty],
24
+ options: validationOptions,
25
+ validator: {
26
+ validate(value, args) {
27
+ const [typeKey] = args.constraints;
28
+ const selectedType = args.object[typeKey];
29
+ // Let enum validation on `type` report invalid type values.
30
+ if (!selectedType || !Object.values(enum_1.AdditionalDetailsTypes).includes(selectedType)) {
31
+ return true;
32
+ }
33
+ if (value === null || value === undefined) {
34
+ return false;
35
+ }
36
+ switch (selectedType) {
37
+ case enum_1.AdditionalDetailsTypes.Text:
38
+ return typeof value === 'string' && value.trim().length > 0;
39
+ case enum_1.AdditionalDetailsTypes.Number:
40
+ return typeof value === 'number' && Number.isFinite(value);
41
+ case enum_1.AdditionalDetailsTypes.Boolean:
42
+ return typeof value === 'boolean';
43
+ case enum_1.AdditionalDetailsTypes.DATE:
44
+ return typeof value === 'string' && !Number.isNaN(Date.parse(value));
45
+ case enum_1.AdditionalDetailsTypes.URL:
46
+ if (typeof value !== 'string') {
47
+ return false;
48
+ }
49
+ try {
50
+ const parsedUrl = new URL(value);
51
+ return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ default:
57
+ return true;
58
+ }
59
+ },
60
+ defaultMessage(args) {
61
+ const [typeKey] = args.constraints;
62
+ const selectedType = args.object[typeKey];
63
+ return `Value does not match provided type: ${String(selectedType)}`;
64
+ },
65
+ },
66
+ });
67
+ };
68
+ }
69
+ class AdditionalDetailsIdDto {
70
+ additionalDetailsId;
71
+ }
72
+ exports.AdditionalDetailsIdDto = AdditionalDetailsIdDto;
73
+ __decorate([
74
+ (0, class_validator_1.IsUUID)('4', { message: 'Invalid additional details ID format' }),
75
+ __metadata("design:type", String)
76
+ ], AdditionalDetailsIdDto.prototype, "additionalDetailsId", void 0);
77
+ class GetAdditionalDetailsDto {
78
+ entity;
79
+ entityId;
80
+ }
81
+ exports.GetAdditionalDetailsDto = GetAdditionalDetailsDto;
82
+ __decorate([
83
+ (0, class_validator_1.IsEnum)(enum_1.AdditionalDetailsEntityTypes, { message: 'Invalid entity type' }),
84
+ __metadata("design:type", String)
85
+ ], GetAdditionalDetailsDto.prototype, "entity", void 0);
86
+ __decorate([
87
+ (0, class_validator_1.IsUUID)('4', { message: 'Invalid entity ID format' }),
88
+ __metadata("design:type", String)
89
+ ], GetAdditionalDetailsDto.prototype, "entityId", void 0);
90
+ class AddAdditionalDetailsDto {
91
+ key;
92
+ value;
93
+ type;
94
+ copyable;
95
+ }
96
+ exports.AddAdditionalDetailsDto = AddAdditionalDetailsDto;
97
+ __decorate([
98
+ (0, class_validator_1.IsString)({ message: 'Invalid key' }),
99
+ (0, class_validator_1.MinLength)(1, { message: 'Key cannot be empty' }),
100
+ (0, class_validator_1.MaxLength)(100, { message: 'Key cannot exceed 100 characters' }),
101
+ __metadata("design:type", String)
102
+ ], AddAdditionalDetailsDto.prototype, "key", void 0);
103
+ __decorate([
104
+ (0, class_validator_1.IsDefined)({ message: 'Value is required' }),
105
+ IsAdditionalDetailsValueByType('type', { message: 'Value does not match the provided type' }),
106
+ __metadata("design:type", Object)
107
+ ], AddAdditionalDetailsDto.prototype, "value", void 0);
108
+ __decorate([
109
+ (0, class_validator_1.IsEnum)(enum_1.AdditionalDetailsTypes, { message: 'Invalid additional details type' }),
110
+ __metadata("design:type", String)
111
+ ], AddAdditionalDetailsDto.prototype, "type", void 0);
112
+ __decorate([
113
+ (0, class_validator_1.IsBoolean)({ message: 'Invalid copyable value' }),
114
+ __metadata("design:type", Boolean)
115
+ ], AddAdditionalDetailsDto.prototype, "copyable", void 0);
116
+ class UpdateAdditionalDetailsDto {
117
+ key;
118
+ value;
119
+ type;
120
+ copyable;
121
+ }
122
+ exports.UpdateAdditionalDetailsDto = UpdateAdditionalDetailsDto;
123
+ __decorate([
124
+ (0, class_validator_1.IsString)({ message: 'Invalid key' }),
125
+ (0, class_validator_1.MinLength)(1, { message: 'Key cannot be empty' }),
126
+ (0, class_validator_1.MaxLength)(100, { message: 'Key cannot exceed 100 characters' }),
127
+ __metadata("design:type", String)
128
+ ], UpdateAdditionalDetailsDto.prototype, "key", void 0);
129
+ __decorate([
130
+ (0, class_validator_1.IsDefined)({ message: 'Value is required' }),
131
+ IsAdditionalDetailsValueByType('type', { message: 'Value does not match the provided type' }),
132
+ __metadata("design:type", Object)
133
+ ], UpdateAdditionalDetailsDto.prototype, "value", void 0);
134
+ __decorate([
135
+ (0, class_validator_1.IsEnum)(enum_1.AdditionalDetailsTypes, { message: 'Invalid additional details type' }),
136
+ __metadata("design:type", String)
137
+ ], UpdateAdditionalDetailsDto.prototype, "type", void 0);
138
+ __decorate([
139
+ (0, class_validator_1.IsBoolean)({ message: 'Invalid copyable value' }),
140
+ __metadata("design:type", Boolean)
141
+ ], UpdateAdditionalDetailsDto.prototype, "copyable", void 0);
142
+ //# sourceMappingURL=dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/additional-details/dto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { AdditionalDetailSummary, AdditionalDetailsEntity } from '@managemint-solutions/entities/additional-details';
2
+ import type { AddAdditionalDetailsDto, UpdateAdditionalDetailsDto } from '@managemint-solutions/entities/additional-details/dto';
3
+ import { AdditionalDetailsEntityTypes } from '@managemint-solutions/entities/additional-details/enum';
4
+ import type { AuthContext } from '../auth';
5
+ import type { TypedSupabaseClient } from '../client';
6
+ export * from './dto';
7
+ export * from './values';
8
+ export declare class AdditionalDetailsResource {
9
+ private readonly supabase;
10
+ private readonly auth;
11
+ constructor(supabase: TypedSupabaseClient, auth: AuthContext);
12
+ getById(additionalDetailsId: string): Promise<AdditionalDetailsEntity>;
13
+ list(entity: AdditionalDetailsEntityTypes, entityId: string): Promise<AdditionalDetailSummary[]>;
14
+ create(entity: AdditionalDetailsEntityTypes, entityId: string, input: AddAdditionalDetailsDto): Promise<AdditionalDetailsEntity>;
15
+ update(additionalDetailsId: string, input: UpdateAdditionalDetailsDto): Promise<AdditionalDetailsEntity>;
16
+ remove(additionalDetailsId: string): Promise<void>;
17
+ }
@@ -0,0 +1,113 @@
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.AdditionalDetailsResource = void 0;
18
+ const errors_1 = require("../errors");
19
+ const values_1 = require("./values");
20
+ __exportStar(require("./dto"), exports);
21
+ __exportStar(require("./values"), exports);
22
+ // The query is typed by the generated Database schema (so the select string and the
23
+ // insert/update payloads are checked); the public contract is the shared entities type.
24
+ // The two shapes legitimately differ, hence `as unknown as`: the embedded user_profiles rows
25
+ // are all-nullable view rows where the entity declares UserIdentity, the timestamps are ISO
26
+ // strings where the entity declares Date, and `value` is the `text` column where the entity
27
+ // declares the parsed string | number | boolean | Date | URL union that castValueByType produces.
28
+ const ADDITIONAL_DETAILS_SELECT = 'mms_id, created_at, created_by:user_profiles!created_by(*), updated_at, last_updated_by:user_profiles!last_updated_by(*), key, value, type, copyable';
29
+ const ADDITIONAL_DETAILS_SUMMARY_SELECT = 'mms_id, key, value, type, copyable';
30
+ const withCastValue = (detail) => ({
31
+ ...detail,
32
+ value: (0, values_1.castValueByType)(detail.type, detail.value),
33
+ });
34
+ class AdditionalDetailsResource {
35
+ supabase;
36
+ auth;
37
+ constructor(supabase, auth) {
38
+ this.supabase = supabase;
39
+ this.auth = auth;
40
+ }
41
+ async getById(additionalDetailsId) {
42
+ const { data, error } = await this.supabase
43
+ .from('additional_details')
44
+ .select(ADDITIONAL_DETAILS_SELECT)
45
+ .eq('organization_id', this.auth.organization_id)
46
+ .eq('mms_id', additionalDetailsId)
47
+ .single();
48
+ if (error)
49
+ throw (0, errors_1.mapPostgrestError)(error);
50
+ return withCastValue(data);
51
+ }
52
+ async list(entity, entityId) {
53
+ const { data, error } = await this.supabase
54
+ .from('additional_details')
55
+ .select(ADDITIONAL_DETAILS_SUMMARY_SELECT)
56
+ .eq('organization_id', this.auth.organization_id)
57
+ .eq('entity_type', entity)
58
+ .eq('entity_id', entityId)
59
+ .order('key', { ascending: false });
60
+ if (error)
61
+ throw (0, errors_1.mapPostgrestError)(error);
62
+ return data.map(withCastValue);
63
+ }
64
+ async create(entity, entityId, input) {
65
+ const { data, error } = await this.supabase
66
+ .from('additional_details')
67
+ .insert({
68
+ organization_id: this.auth.organization_id,
69
+ entity_type: entity,
70
+ entity_id: entityId,
71
+ key: input.key,
72
+ value: (0, values_1.serializeValue)(input.value),
73
+ type: input.type,
74
+ copyable: input.copyable,
75
+ created_by: this.auth.mms_id,
76
+ })
77
+ .select(ADDITIONAL_DETAILS_SELECT)
78
+ .single();
79
+ if (error)
80
+ throw (0, errors_1.mapPostgrestError)(error);
81
+ return withCastValue(data);
82
+ }
83
+ async update(additionalDetailsId, input) {
84
+ const { data, error } = await this.supabase
85
+ .from('additional_details')
86
+ .update({
87
+ key: input.key,
88
+ value: (0, values_1.serializeValue)(input.value),
89
+ type: input.type,
90
+ copyable: input.copyable,
91
+ updated_at: new Date().toISOString(),
92
+ last_updated_by: this.auth.mms_id,
93
+ })
94
+ .eq('mms_id', additionalDetailsId)
95
+ .eq('organization_id', this.auth.organization_id)
96
+ .select(ADDITIONAL_DETAILS_SELECT)
97
+ .single();
98
+ if (error)
99
+ throw (0, errors_1.mapPostgrestError)(error);
100
+ return withCastValue(data);
101
+ }
102
+ async remove(additionalDetailsId) {
103
+ const { error } = await this.supabase
104
+ .from('additional_details')
105
+ .delete()
106
+ .eq('mms_id', additionalDetailsId)
107
+ .eq('organization_id', this.auth.organization_id);
108
+ if (error)
109
+ throw (0, errors_1.mapPostgrestError)(error);
110
+ }
111
+ }
112
+ exports.AdditionalDetailsResource = AdditionalDetailsResource;
113
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/additional-details/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { AdditionalDetailsTypes } from '@managemint-solutions/entities/additional-details/enum';
2
+ /**
3
+ * The `value` column is `text`, so every stored value comes back as a string. This casts it
4
+ * back to the JS shape the row's `type` promises. Non-strings and null/undefined pass through.
5
+ */
6
+ export declare const castValueByType: (type: AdditionalDetailsTypes, value: unknown) => unknown;
7
+ /**
8
+ * What gets written to the `text` column. The generated Insert/Update requires `value: string`;
9
+ * `String()` reproduces the JSON → text coercion PostgREST used to do for number/boolean/string.
10
+ */
11
+ export declare const serializeValue: (value: string | number | boolean | Date | URL) => string;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serializeValue = exports.castValueByType = void 0;
4
+ const enum_1 = require("@managemint-solutions/entities/additional-details/enum");
5
+ /**
6
+ * The `value` column is `text`, so every stored value comes back as a string. This casts it
7
+ * back to the JS shape the row's `type` promises. Non-strings and null/undefined pass through.
8
+ */
9
+ const castValueByType = (type, value) => {
10
+ if (value === null || value === undefined) {
11
+ return value;
12
+ }
13
+ if (typeof value !== 'string') {
14
+ return value;
15
+ }
16
+ switch (type) {
17
+ case enum_1.AdditionalDetailsTypes.Number:
18
+ return Number(value);
19
+ case enum_1.AdditionalDetailsTypes.Boolean:
20
+ return value.toLowerCase() === 'true';
21
+ case enum_1.AdditionalDetailsTypes.DATE:
22
+ return new Date(value);
23
+ case enum_1.AdditionalDetailsTypes.URL:
24
+ return new URL(value);
25
+ case enum_1.AdditionalDetailsTypes.Text:
26
+ default:
27
+ return value;
28
+ }
29
+ };
30
+ exports.castValueByType = castValueByType;
31
+ /**
32
+ * What gets written to the `text` column. The generated Insert/Update requires `value: string`;
33
+ * `String()` reproduces the JSON → text coercion PostgREST used to do for number/boolean/string.
34
+ */
35
+ const serializeValue = (value) => value instanceof Date ? value.toISOString() : String(value);
36
+ exports.serializeValue = serializeValue;
37
+ //# sourceMappingURL=values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.js","sourceRoot":"","sources":["../../src/additional-details/values.ts"],"names":[],"mappings":";;;AAAA,iFAAgG;AAEhG;;;GAGG;AACI,MAAM,eAAe,GAAG,CAAC,IAA4B,EAAE,KAAc,EAAW,EAAE;IACvF,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,6BAAsB,CAAC,MAAM;YAChC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,KAAK,6BAAsB,CAAC,OAAO;YACjC,OAAO,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;QACxC,KAAK,6BAAsB,CAAC,IAAI;YAC9B,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,KAAK,6BAAsB,CAAC,GAAG;YAC7B,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QACxB,KAAK,6BAAsB,CAAC,IAAI,CAAC;QACjC;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC,CAAC;AAtBW,QAAA,eAAe,mBAsB1B;AAEF;;;GAGG;AACI,MAAM,cAAc,GAAG,CAAC,KAA6C,EAAU,EAAE,CACtF,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AADjD,QAAA,cAAc,kBACmC"}
package/dist/client.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  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
+ import { AdditionalDetailsResource } from './additional-details';
5
+ import { NotesResource } from './notes';
4
6
  import { StatusesResource } from './statuses';
5
7
  export type TypedSupabaseClient = SupabaseJsClient<Database>;
6
8
  export type SupabaseClientConfig = {
@@ -12,6 +14,8 @@ export declare class SupabaseClient {
12
14
  readonly supabase: TypedSupabaseClient;
13
15
  readonly auth: AuthContext;
14
16
  readonly statuses: StatusesResource;
17
+ readonly additionalDetails: AdditionalDetailsResource;
18
+ readonly notes: NotesResource;
15
19
  constructor(config: SupabaseClientConfig);
16
20
  }
17
21
  export declare const createSupabaseClient: (config: SupabaseClientConfig) => SupabaseClient;
package/dist/client.js CHANGED
@@ -3,11 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createSupabaseClient = exports.SupabaseClient = void 0;
4
4
  const supabase_js_1 = require("@supabase/supabase-js");
5
5
  const auth_1 = require("./auth");
6
+ const additional_details_1 = require("./additional-details");
7
+ const notes_1 = require("./notes");
6
8
  const statuses_1 = require("./statuses");
7
9
  class SupabaseClient {
8
10
  supabase; // escape hatch for not-yet-migrated queries
9
11
  auth;
10
12
  statuses;
13
+ additionalDetails;
14
+ notes;
11
15
  constructor(config) {
12
16
  this.auth = (0, auth_1.decodeAuthContext)(config.accessToken);
13
17
  this.supabase = (0, supabase_js_1.createClient)(config.url, config.key, {
@@ -15,6 +19,8 @@ class SupabaseClient {
15
19
  auth: { persistSession: false, autoRefreshToken: false },
16
20
  });
17
21
  this.statuses = new statuses_1.StatusesResource(this.supabase, this.auth);
22
+ this.additionalDetails = new additional_details_1.AdditionalDetailsResource(this.supabase, this.auth);
23
+ this.notes = new notes_1.NotesResource(this.supabase, this.auth);
18
24
  }
19
25
  }
20
26
  exports.SupabaseClient = SupabaseClient;
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,uDAA8F;AAE9F,iCAA6D;AAC7D,yCAA8C;AAU9C,MAAa,cAAc;IAChB,QAAQ,CAAsB,CAAC,4CAA4C;IAC3E,IAAI,CAAc;IAClB,QAAQ,CAAmB;IAEpC,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;IACjE,CAAC;CACF;AAbD,wCAaC;AAEM,MAAM,oBAAoB,GAAG,CAAC,MAA4B,EAAkB,EAAE,CACnF,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AADhB,QAAA,oBAAoB,wBACJ"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAAA,uDAA8F;AAE9F,iCAA6D;AAC7D,6DAAiE;AACjE,mCAAwC;AACxC,yCAA8C;AAU9C,MAAa,cAAc;IAChB,QAAQ,CAAsB,CAAC,4CAA4C;IAC3E,IAAI,CAAc;IAClB,QAAQ,CAAmB;IAC3B,iBAAiB,CAA4B;IAC7C,KAAK,CAAgB;IAE9B,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;IAC3D,CAAC;CACF;AAjBD,wCAiBC;AAEM,MAAM,oBAAoB,GAAG,CAAC,MAA4B,EAAkB,EAAE,CACnF,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AADhB,QAAA,oBAAoB,wBACJ"}
package/dist/index.d.ts CHANGED
@@ -2,4 +2,6 @@ export * from './client';
2
2
  export * from './auth';
3
3
  export * from './errors';
4
4
  export * from './statuses';
5
+ export * from './additional-details';
6
+ export * from './notes';
5
7
  export type { Database, Tables, TablesInsert, TablesUpdate, Json } from './database.types';
package/dist/index.js CHANGED
@@ -18,4 +18,6 @@ __exportStar(require("./client"), exports);
18
18
  __exportStar(require("./auth"), exports);
19
19
  __exportStar(require("./errors"), exports);
20
20
  __exportStar(require("./statuses"), exports);
21
+ __exportStar(require("./additional-details"), exports);
22
+ __exportStar(require("./notes"), exports);
21
23
  //# 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"}
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"}
@@ -0,0 +1,15 @@
1
+ import type { AddNoteDto as AddNoteDtoType, GetNotesDto as GetNotesDtoType, NoteIdDto as NoteIdDtoType } from '@managemint-solutions/entities/notes/dto';
2
+ import { NotesEntityTypes } from '@managemint-solutions/entities/notes/enum';
3
+ import type { TablesInsert } from '../database.types';
4
+ type NotesInsertColumns = Required<Pick<TablesInsert<'notes'>, 'content'>>;
5
+ export declare class NoteIdDto implements NoteIdDtoType {
6
+ readonly noteId: string;
7
+ }
8
+ export declare class GetNotesDto implements GetNotesDtoType {
9
+ readonly entity: NotesEntityTypes;
10
+ readonly entityId: string;
11
+ }
12
+ export declare class AddNoteDto implements AddNoteDtoType, NotesInsertColumns {
13
+ readonly content: string;
14
+ }
15
+ export {};
@@ -0,0 +1,46 @@
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.AddNoteDto = exports.GetNotesDto = exports.NoteIdDto = void 0;
13
+ const class_validator_1 = require("class-validator");
14
+ const enum_1 = require("@managemint-solutions/entities/notes/enum");
15
+ class NoteIdDto {
16
+ noteId;
17
+ }
18
+ exports.NoteIdDto = NoteIdDto;
19
+ __decorate([
20
+ (0, class_validator_1.IsUUID)('4', { message: 'Invalid note ID format' }),
21
+ __metadata("design:type", String)
22
+ ], NoteIdDto.prototype, "noteId", void 0);
23
+ class GetNotesDto {
24
+ entity;
25
+ entityId;
26
+ }
27
+ exports.GetNotesDto = GetNotesDto;
28
+ __decorate([
29
+ (0, class_validator_1.IsEnum)(enum_1.NotesEntityTypes, { message: 'Invalid entity type' }),
30
+ __metadata("design:type", String)
31
+ ], GetNotesDto.prototype, "entity", void 0);
32
+ __decorate([
33
+ (0, class_validator_1.IsUUID)('4', { message: 'Invalid entity ID format' }),
34
+ __metadata("design:type", String)
35
+ ], GetNotesDto.prototype, "entityId", void 0);
36
+ class AddNoteDto {
37
+ content;
38
+ }
39
+ exports.AddNoteDto = AddNoteDto;
40
+ __decorate([
41
+ (0, class_validator_1.IsString)({ message: 'Invalid content' }),
42
+ (0, class_validator_1.MinLength)(1, { message: 'Content cannot be empty' }),
43
+ (0, class_validator_1.MaxLength)(255, { message: 'Content cannot exceed 255 characters' }),
44
+ __metadata("design:type", String)
45
+ ], AddNoteDto.prototype, "content", void 0);
46
+ //# sourceMappingURL=dto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/notes/dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAiF;AAMjF,oEAA6E;AAQ7E,MAAa,SAAS;IAEX,MAAM,CAAU;CAC1B;AAHD,8BAGC;AADU;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;;yCAC1B;AAG3B,MAAa,WAAW;IAEb,MAAM,CAAoB;IAG1B,QAAQ,CAAU;CAC5B;AAND,kCAMC;AAJU;IADR,IAAA,wBAAM,EAAC,uBAAgB,EAAE,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;;2CAC1B;AAG1B;IADR,IAAA,wBAAM,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;;6CAC1B;AAG7B,MAAa,UAAU;IAIZ,OAAO,CAAU;CAC3B;AALD,gCAKC;AADU;IAHR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;IACxC,IAAA,2BAAS,EAAC,CAAC,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;IACpD,IAAA,2BAAS,EAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC;;2CAC1C"}
@@ -0,0 +1,16 @@
1
+ import type { NoteEntity } from '@managemint-solutions/entities/notes';
2
+ import type { AddNoteDto } from '@managemint-solutions/entities/notes/dto';
3
+ import { NotesEntityTypes } from '@managemint-solutions/entities/notes/enum';
4
+ import type { AuthContext } from '../auth';
5
+ import type { TypedSupabaseClient } from '../client';
6
+ export * from './dto';
7
+ export declare class NotesResource {
8
+ private readonly supabase;
9
+ private readonly auth;
10
+ constructor(supabase: TypedSupabaseClient, auth: AuthContext);
11
+ getById(noteId: string): Promise<NoteEntity>;
12
+ list(entity: NotesEntityTypes, entityId: string): Promise<NoteEntity[]>;
13
+ create(entity: NotesEntityTypes, entityId: string, input: AddNoteDto): Promise<NoteEntity>;
14
+ togglePin(noteId: string): Promise<NoteEntity>;
15
+ remove(noteId: string): Promise<void>;
16
+ }
@@ -0,0 +1,98 @@
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.NotesResource = void 0;
18
+ const errors_1 = require("../errors");
19
+ __exportStar(require("./dto"), exports);
20
+ // The query is typed by the generated Database schema (so the select string and the insert/update
21
+ // payloads are checked); the public contract is the shared NoteEntity from
22
+ // @managemint-solutions/entities. The two shapes legitimately differ, hence `as unknown as`: the
23
+ // embedded user_profiles row is an all-nullable view row where the entity declares UserIdentity,
24
+ // and created_at is an ISO string where the entity declares Date.
25
+ const NOTE_SELECT = 'mms_id, created_at, content, pinned, user:user_profiles!user_id(*)';
26
+ class NotesResource {
27
+ supabase;
28
+ auth;
29
+ constructor(supabase, auth) {
30
+ this.supabase = supabase;
31
+ this.auth = auth;
32
+ }
33
+ async getById(noteId) {
34
+ const { data, error } = await this.supabase
35
+ .from('notes')
36
+ .select(NOTE_SELECT)
37
+ .eq('organization_id', this.auth.organization_id)
38
+ .eq('mms_id', noteId)
39
+ .single();
40
+ if (error)
41
+ throw (0, errors_1.mapPostgrestError)(error);
42
+ return data;
43
+ }
44
+ async list(entity, entityId) {
45
+ const { data, error } = await this.supabase
46
+ .from('notes')
47
+ .select(NOTE_SELECT)
48
+ .eq('organization_id', this.auth.organization_id)
49
+ .eq('entity_type', entity)
50
+ .eq('entity_id', entityId)
51
+ .order('created_at', { ascending: false });
52
+ if (error)
53
+ throw (0, errors_1.mapPostgrestError)(error);
54
+ return data;
55
+ }
56
+ async create(entity, entityId, input) {
57
+ const { data, error } = await this.supabase
58
+ .from('notes')
59
+ .insert({
60
+ content: input.content,
61
+ entity_type: entity,
62
+ entity_id: entityId,
63
+ organization_id: this.auth.organization_id,
64
+ user_id: this.auth.mms_id,
65
+ })
66
+ .select(NOTE_SELECT)
67
+ .single();
68
+ if (error)
69
+ throw (0, errors_1.mapPostgrestError)(error);
70
+ return data;
71
+ }
72
+ async togglePin(noteId) {
73
+ const existing = await this.getById(noteId);
74
+ const { error } = await this.supabase
75
+ .from('notes')
76
+ .update({
77
+ pinned: !existing.pinned,
78
+ updated_at: new Date().toISOString(),
79
+ last_updated_by: this.auth.mms_id,
80
+ })
81
+ .eq('mms_id', noteId)
82
+ .eq('organization_id', this.auth.organization_id);
83
+ if (error)
84
+ throw (0, errors_1.mapPostgrestError)(error);
85
+ return this.getById(noteId);
86
+ }
87
+ async remove(noteId) {
88
+ const { error } = await this.supabase
89
+ .from('notes')
90
+ .delete()
91
+ .eq('mms_id', noteId)
92
+ .eq('organization_id', this.auth.organization_id);
93
+ if (error)
94
+ throw (0, errors_1.mapPostgrestError)(error);
95
+ }
96
+ }
97
+ exports.NotesResource = NotesResource;
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notes/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managemint-solutions/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Typed Supabase data-access SDK for ManageMint Solutions",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Scott Bebington <scottbebington@gmail.com>",