@managemint-solutions/sdk 0.54.0 → 0.56.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.
@@ -121,15 +121,17 @@ class ClientsResource {
121
121
  return (0, transforms_1.toMmsList)(data, page, pageSize, count);
122
122
  }
123
123
  async getById(clientId) {
124
- const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('clients').select(CLIENT_DETAIL_SELECT), this.auth)
124
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('clients').select((0, tenancy_1.withOrganization)(CLIENT_DETAIL_SELECT, this.auth)), this.auth)
125
125
  .eq('mms_id', clientId)
126
126
  .single();
127
127
  if (error)
128
128
  throw (0, errors_1.mapPostgrestError)(error);
129
+ // The select carries the staff embed, so its row type is not inferred from the string.
130
+ const row = data;
129
131
  // A soft-deleted client keeps its audit trail but gives up its details.
130
- if (data.deleted) {
132
+ if (row.deleted) {
131
133
  return {
132
- ...data,
134
+ ...row,
133
135
  name: '',
134
136
  email: '',
135
137
  phone: '',
@@ -6,8 +6,11 @@ import type { TypedSupabaseClient } from '../client';
6
6
  export declare class EmulationHandshakesResource {
7
7
  private readonly supabase;
8
8
  constructor(supabase: TypedSupabaseClient);
9
- /** Opens a handshake for `userId`'s next sign-in, good for thirty seconds. Returns its id. */
10
- open(userId: string, credentialId: string): Promise<number>;
9
+ /**
10
+ * Opens a handshake for `userId`'s next sign-in, good for thirty seconds. Returns its id. The
11
+ * credential is the one a public mint presented; a staff member's own mint has none.
12
+ */
13
+ open(userId: string, credentialId: string | null): Promise<number>;
11
14
  /** Deletes the handshake, spent or not, once the mint is over. */
12
15
  close(id: number): Promise<void>;
13
16
  }
@@ -11,7 +11,10 @@ class EmulationHandshakesResource {
11
11
  constructor(supabase) {
12
12
  this.supabase = supabase;
13
13
  }
14
- /** Opens a handshake for `userId`'s next sign-in, good for thirty seconds. Returns its id. */
14
+ /**
15
+ * Opens a handshake for `userId`'s next sign-in, good for thirty seconds. Returns its id. The
16
+ * credential is the one a public mint presented; a staff member's own mint has none.
17
+ */
15
18
  async open(userId, credentialId) {
16
19
  const { data, error } = await this.supabase
17
20
  .from('emulation_handshakes')
@@ -165,16 +165,18 @@ class LeadsResource {
165
165
  return (0, transforms_1.toMmsList)(data, page, pageSize, count);
166
166
  }
167
167
  async getById(leadId) {
168
- const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('leads').select(LEAD_DETAIL_SELECT), this.auth)
168
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('leads').select((0, tenancy_1.withOrganization)(LEAD_DETAIL_SELECT, this.auth)), this.auth)
169
169
  .eq('mms_id', leadId)
170
170
  .single();
171
171
  if (error)
172
172
  throw (0, errors_1.mapPostgrestError)(error);
173
+ // The select carries the staff embed, so its row type is not inferred from the string.
174
+ const row = data;
173
175
  // A soft-deleted lead keeps its audit trail but gives up its details. The client it became
174
176
  // stays, so a converted lead can still point at it.
175
- if (data.deleted) {
177
+ if (row.deleted) {
176
178
  return {
177
- ...data,
179
+ ...row,
178
180
  name: '',
179
181
  contact_person: null,
180
182
  email: '',
@@ -1,7 +1,7 @@
1
1
  import type { NoteEntity } from '@managemint-solutions/entities/notes';
2
2
  import type { AddNoteDto } from '@managemint-solutions/entities/notes/dto';
3
3
  import { NotesEntityTypes } from '@managemint-solutions/entities/notes/enum';
4
- import type { AuthContext } from '../auth';
4
+ import type { ClientContext } from '../auth';
5
5
  import { type AuditResource } from '../audit';
6
6
  import type { TypedSupabaseClient } from '../client';
7
7
  export * from './dto';
@@ -9,7 +9,7 @@ export declare class NotesResource {
9
9
  private readonly supabase;
10
10
  private readonly auth;
11
11
  private readonly table;
12
- constructor(supabase: TypedSupabaseClient, auth: AuthContext, audit: AuditResource);
12
+ constructor(supabase: TypedSupabaseClient, auth: ClientContext, audit: AuditResource);
13
13
  getById(noteId: string): Promise<NoteEntity>;
14
14
  list(entity: NotesEntityTypes, entityId: string): Promise<NoteEntity[]>;
15
15
  create(entity: NotesEntityTypes, entityId: string, input: AddNoteDto): Promise<NoteEntity>;
@@ -20,6 +20,7 @@ const enum_2 = require("@managemint-solutions/entities/audit-trail/enum");
20
20
  const audit_1 = require("../audit");
21
21
  const errors_1 = require("../errors");
22
22
  const won_1 = require("../leads/won");
23
+ const tenancy_1 = require("../tenancy");
23
24
  __exportStar(require("./dto"), exports);
24
25
  // The public contract is the shared NoteEntity from @managemint-solutions/entities; the casts at
25
26
  // the returns declare the shape the select string below produces (the columns are defined in the
@@ -38,10 +39,7 @@ class NotesResource {
38
39
  });
39
40
  }
40
41
  async getById(noteId) {
41
- const { data, error } = await this.supabase
42
- .from('notes')
43
- .select(NOTE_SELECT)
44
- .eq('organization_id', this.auth.organization_id)
42
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('notes').select(NOTE_SELECT), this.auth)
45
43
  .eq('mms_id', noteId)
46
44
  .single();
47
45
  if (error)
@@ -49,10 +47,7 @@ class NotesResource {
49
47
  return data;
50
48
  }
51
49
  async list(entity, entityId) {
52
- const { data, error } = await this.supabase
53
- .from('notes')
54
- .select(NOTE_SELECT)
55
- .eq('organization_id', this.auth.organization_id)
50
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('notes').select(NOTE_SELECT), this.auth)
56
51
  .eq('entity_type', entity)
57
52
  .eq('entity_id', entityId)
58
53
  .order('created_at', { ascending: false });
@@ -61,14 +56,15 @@ class NotesResource {
61
56
  return data;
62
57
  }
63
58
  async create(entity, entityId, input) {
59
+ const organizationId = (0, tenancy_1.requireOrganization)(this.auth);
64
60
  if (entity === enum_1.NotesEntityTypes.LEAD) {
65
- await (0, won_1.refuseWonLead)(this.supabase, this.auth.organization_id, entityId);
61
+ await (0, won_1.refuseWonLead)(this.supabase, organizationId, entityId);
66
62
  }
67
63
  const row = await this.table.insert({
68
64
  content: input.content,
69
65
  entity_type: entity,
70
66
  entity_id: entityId,
71
- organization_id: this.auth.organization_id,
67
+ organization_id: organizationId,
72
68
  user_id: this.auth.mms_id,
73
69
  });
74
70
  return this.getById(row.mms_id);
@@ -150,15 +150,17 @@ class ProjectsResource {
150
150
  return (0, transforms_1.toMmsList)(data, page, pageSize, count);
151
151
  }
152
152
  async getById(projectId) {
153
- const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('projects').select(PROJECT_DETAIL_SELECT), this.auth)
153
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('projects').select((0, tenancy_1.withOrganization)(PROJECT_DETAIL_SELECT, this.auth)), this.auth)
154
154
  .eq('mms_id', projectId)
155
155
  .single();
156
156
  if (error)
157
157
  throw (0, errors_1.mapPostgrestError)(error);
158
+ // The select carries the staff embed, so its row type is not inferred from the string.
159
+ const row = data;
158
160
  // A soft-deleted project keeps its creation audit but gives up its details.
159
- if (data.deleted) {
161
+ if (row.deleted) {
160
162
  return {
161
- ...data,
163
+ ...row,
162
164
  name: '',
163
165
  specification: null,
164
166
  has_budget: false,
@@ -13,6 +13,7 @@ import { OrganizationPaymentMethodsResource, type PaymentMethodLookupColumn } fr
13
13
  import { OrganizationsResource, OrganizationSignupResource } from '../organizations';
14
14
  import { PermissionsResource } from '../permissions';
15
15
  import { StaffPermissionsResource, StaffResource } from '../staff';
16
+ import { SupportingFilesResource } from '../supporting-files';
16
17
  import { UserApiCredentialsResource } from '../user-api-credentials';
17
18
  import { UsersResource } from '../users';
18
19
  import { WebhookEventsResource } from '../webhook-events';
@@ -41,6 +42,8 @@ export declare class SupabaseOrganizationScope {
41
42
  readonly organizations: OrganizationsResource;
42
43
  readonly paymentMethod: OrganizationPaymentMethodsResource;
43
44
  readonly permissions: PermissionsResource;
45
+ /** For the admin api's staff downloads: Storage's read policy names no staff, the service role passes it. */
46
+ readonly supportingFiles: SupportingFilesResource;
44
47
  readonly users: UsersResource;
45
48
  constructor(supabase: TypedSupabaseClient, actor: AuditActor, onAuditError?: AuditErrorHandler);
46
49
  /**
@@ -18,6 +18,7 @@ const organization_payment_methods_1 = require("../organization-payment-methods"
18
18
  const organizations_1 = require("../organizations");
19
19
  const permissions_1 = require("../permissions");
20
20
  const staff_1 = require("../staff");
21
+ const supporting_files_1 = require("../supporting-files");
21
22
  const user_api_credentials_1 = require("../user-api-credentials");
22
23
  const users_1 = require("../users");
23
24
  const webhook_events_1 = require("../webhook-events");
@@ -39,6 +40,8 @@ class SupabaseOrganizationScope {
39
40
  organizations;
40
41
  paymentMethod;
41
42
  permissions;
43
+ /** For the admin api's staff downloads: Storage's read policy names no staff, the service role passes it. */
44
+ supportingFiles;
42
45
  users;
43
46
  constructor(supabase, actor, onAuditError) {
44
47
  this.supabase = supabase;
@@ -54,6 +57,7 @@ class SupabaseOrganizationScope {
54
57
  this.organizations = new organizations_1.OrganizationsResource(supabase, actor, this.audit);
55
58
  this.paymentMethod = new organization_payment_methods_1.OrganizationPaymentMethodsResource(supabase, actor);
56
59
  this.permissions = new permissions_1.PermissionsResource(supabase, actor, this.audit);
60
+ this.supportingFiles = new supporting_files_1.SupportingFilesResource(supabase, actor, this.audit);
57
61
  this.users = new users_1.UsersResource(supabase, actor, this.audit);
58
62
  }
59
63
  /**
@@ -1,11 +1,14 @@
1
1
  import { type StaffContext } from './auth';
2
2
  import { AuditResource } from './audit';
3
+ import { AdditionalDetailsResource } from './additional-details';
3
4
  import type { SupabaseClientConfig, TypedSupabaseClient } from './client';
4
5
  import { ClientsResource } from './clients';
5
6
  import { LeadsResource } from './leads';
7
+ import { NotesResource } from './notes';
6
8
  import { OrganizationsResource } from './organizations';
7
9
  import { ProjectsResource } from './projects';
8
10
  import { StaffPermissionsResource, StaffResource } from './staff';
11
+ import { SupportingFilesResource } from './supporting-files';
9
12
  import { TasksResource } from './tasks';
10
13
  import { UserApiCredentialsReads } from './user-api-credentials';
11
14
  import { UsersResource } from './users';
@@ -22,14 +25,18 @@ export declare class SupabaseStaffClient {
22
25
  /** The staff member the token belongs to - the caller, for a service that records who acted. */
23
26
  readonly auth: StaffContext;
24
27
  readonly audit: AuditResource;
28
+ readonly additionalDetails: AdditionalDetailsResource;
25
29
  readonly clients: ClientsResource;
26
30
  readonly leads: LeadsResource;
31
+ readonly notes: NotesResource;
27
32
  readonly projects: ProjectsResource;
28
33
  readonly tasks: TasksResource;
29
34
  readonly users: UsersResource;
30
35
  readonly organizations: OrganizationsResource;
31
36
  readonly staff: StaffResource;
32
37
  readonly staffPermissions: StaffPermissionsResource;
38
+ /** Lists and parents only: Storage names no staff, so a download is signed on the service client. */
39
+ readonly supportingFiles: SupportingFilesResource;
33
40
  readonly userApiCredentials: UserApiCredentialsReads;
34
41
  constructor({ url, key, accessToken, auth, client }: SupabaseStaffClientConfig);
35
42
  }
@@ -6,9 +6,11 @@ const audit_1 = require("./audit");
6
6
  const additional_details_1 = require("./additional-details");
7
7
  const clients_1 = require("./clients");
8
8
  const leads_1 = require("./leads");
9
+ const notes_1 = require("./notes");
9
10
  const organizations_1 = require("./organizations");
10
11
  const projects_1 = require("./projects");
11
12
  const staff_1 = require("./staff");
13
+ const supporting_files_1 = require("./supporting-files");
12
14
  const tasks_1 = require("./tasks");
13
15
  const user_api_credentials_1 = require("./user-api-credentials");
14
16
  const users_1 = require("./users");
@@ -22,28 +24,34 @@ class SupabaseStaffClient {
22
24
  /** The staff member the token belongs to - the caller, for a service that records who acted. */
23
25
  auth;
24
26
  audit;
27
+ additionalDetails;
25
28
  clients;
26
29
  leads;
30
+ notes;
27
31
  projects;
28
32
  tasks;
29
33
  users;
30
34
  organizations;
31
35
  staff;
32
36
  staffPermissions;
37
+ /** Lists and parents only: Storage names no staff, so a download is signed on the service client. */
38
+ supportingFiles;
33
39
  userApiCredentials;
34
40
  constructor({ url, key, accessToken, auth, client }) {
35
41
  this.supabase = client ?? (0, auth_1.createRawClient)(url, key, accessToken);
36
42
  this.auth = auth;
37
43
  this.audit = new audit_1.AuditResource(this.supabase, auth);
38
44
  this.clients = new clients_1.ClientsResource(this.supabase, auth, this.audit);
39
- const additionalDetails = new additional_details_1.AdditionalDetailsResource(this.supabase, auth, this.audit);
40
- this.leads = new leads_1.LeadsResource(this.supabase, auth, this.audit, additionalDetails);
45
+ this.additionalDetails = new additional_details_1.AdditionalDetailsResource(this.supabase, auth, this.audit);
46
+ this.leads = new leads_1.LeadsResource(this.supabase, auth, this.audit, this.additionalDetails);
47
+ this.notes = new notes_1.NotesResource(this.supabase, auth, this.audit);
41
48
  this.projects = new projects_1.ProjectsResource(this.supabase, auth, this.audit);
42
49
  this.tasks = new tasks_1.TasksResource(this.supabase, auth, this.audit);
43
50
  this.users = new users_1.UsersResource(this.supabase, auth, this.audit);
44
51
  this.organizations = new organizations_1.OrganizationsResource(this.supabase, auth, this.audit);
45
52
  this.staff = new staff_1.StaffResource(this.supabase);
46
53
  this.staffPermissions = new staff_1.StaffPermissionsResource(this.supabase);
54
+ this.supportingFiles = new supporting_files_1.SupportingFilesResource(this.supabase, auth, this.audit);
47
55
  this.userApiCredentials = new user_api_credentials_1.UserApiCredentialsReads(this.supabase);
48
56
  }
49
57
  }
@@ -1,7 +1,6 @@
1
1
  import type { SupportingFileEntity, SupportingFilePresignedUrl, SupportingFileUploadTarget } from '@managemint-solutions/entities/supporting-files';
2
2
  import { SupportingFilesEntityTypes } from '@managemint-solutions/entities/supporting-files/enum';
3
- import type { AuthContext } from '../auth';
4
- import { type AuditResource } from '../audit';
3
+ import { type AuditResource, type ResourceActor } from '../audit';
5
4
  import type { TypedSupabaseClient } from '../client';
6
5
  export * from './dto';
7
6
  export * from './paths';
@@ -9,12 +8,21 @@ export declare class SupportingFilesResource {
9
8
  private readonly supabase;
10
9
  private readonly auth;
11
10
  private readonly table;
12
- constructor(supabase: TypedSupabaseClient, auth: AuthContext, audit: AuditResource);
11
+ constructor(supabase: TypedSupabaseClient, auth: ResourceActor, audit: AuditResource);
12
+ /**
13
+ * A short-lived download link. Storage checks the bucket's read policy as this client's
14
+ * caller, which names no staff - the admin api signs on the service client's organization
15
+ * scope instead.
16
+ */
13
17
  getPresignedUrl(supportingFileId: string): Promise<SupportingFilePresignedUrl>;
14
- /** The record a file hangs off - what the api checks the caller can reach before a download or delete. */
18
+ /**
19
+ * The record a file hangs off, and its organization - what the api checks the caller can
20
+ * reach before a download or delete.
21
+ */
15
22
  getParent(supportingFileId: string): Promise<{
16
23
  entity_type: SupportingFilesEntityTypes;
17
24
  entity_id: string;
25
+ organization_id: string;
18
26
  }>;
19
27
  list(entity: SupportingFilesEntityTypes, entityId: string): Promise<SupportingFileEntity[]>;
20
28
  /**
@@ -20,6 +20,7 @@ const enum_2 = require("@managemint-solutions/entities/audit-trail/enum");
20
20
  const audit_1 = require("../audit");
21
21
  const errors_1 = require("../errors");
22
22
  const won_1 = require("../leads/won");
23
+ const tenancy_1 = require("../tenancy");
23
24
  const paths_1 = require("./paths");
24
25
  __exportStar(require("./dto"), exports);
25
26
  __exportStar(require("./paths"), exports);
@@ -60,41 +61,40 @@ class SupportingFilesResource {
60
61
  entityType: enum_2.AuditTrailEntityType.SUPPORTING_FILES,
61
62
  });
62
63
  }
64
+ /**
65
+ * A short-lived download link. Storage checks the bucket's read policy as this client's
66
+ * caller, which names no staff - the admin api signs on the service client's organization
67
+ * scope instead.
68
+ */
63
69
  async getPresignedUrl(supportingFileId) {
64
- const { data, error } = await this.supabase
65
- .from('supporting_files')
66
- .select('name, extension, entity_type, entity_id')
70
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('supporting_files').select('organization_id, name, extension, entity_type, entity_id'), this.auth)
67
71
  .eq('mms_id', supportingFileId)
68
- .eq('organization_id', this.auth.organization_id)
69
72
  .single();
70
73
  if (error)
71
74
  throw (0, errors_1.mapPostgrestError)(error);
72
75
  const { data: signed, error: signedError } = await this.supabase.storage
73
76
  .from(BUCKET)
74
- .createSignedUrl((0, paths_1.storagePath)(this.auth.organization_id, data.entity_type, data.entity_id, data.name, data.extension), SIGNED_URL_TTL_SECONDS);
77
+ .createSignedUrl((0, paths_1.storagePath)(data.organization_id, data.entity_type, data.entity_id, data.name, data.extension), SIGNED_URL_TTL_SECONDS);
75
78
  if (signedError)
76
79
  throw (0, errors_1.mapStorageError)(signedError);
77
80
  return { url: signed.signedUrl, ttl: SIGNED_URL_TTL_SECONDS };
78
81
  }
79
- /** The record a file hangs off - what the api checks the caller can reach before a download or delete. */
82
+ /**
83
+ * The record a file hangs off, and its organization - what the api checks the caller can
84
+ * reach before a download or delete.
85
+ */
80
86
  async getParent(supportingFileId) {
81
- const { data, error } = await this.supabase
82
- .from('supporting_files')
83
- .select('entity_type, entity_id')
87
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('supporting_files').select('entity_type, entity_id, organization_id'), this.auth)
84
88
  .eq('mms_id', supportingFileId)
85
- .eq('organization_id', this.auth.organization_id)
86
89
  .single();
87
90
  if (error)
88
91
  throw (0, errors_1.mapPostgrestError)(error);
89
92
  return data;
90
93
  }
91
94
  async list(entity, entityId) {
92
- const { data, error } = await this.supabase
93
- .from('supporting_files')
94
- .select('mms_id, name, extension')
95
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('supporting_files').select('mms_id, name, extension'), this.auth)
95
96
  .eq('entity_type', entity)
96
97
  .eq('entity_id', entityId)
97
- .eq('organization_id', this.auth.organization_id)
98
98
  .order('created_at', { ascending: false });
99
99
  if (error)
100
100
  throw (0, errors_1.mapPostgrestError)(error);
@@ -128,6 +128,7 @@ class SupportingFilesResource {
128
128
  * object was refreshed in place). Returns the record's whole list.
129
129
  */
130
130
  async record(entity, entityId, names) {
131
+ const organizationId = (0, tenancy_1.requireOrganization)(this.auth);
131
132
  const files = await this.prepare(entity, entityId, names);
132
133
  for (let index = 0; index < files.length; index += BATCH_SIZE) {
133
134
  await Promise.all(files.slice(index, index + BATCH_SIZE).map(async ({ name, extension, path }) => {
@@ -148,7 +149,7 @@ class SupportingFilesResource {
148
149
  .select('name, extension')
149
150
  .eq('entity_type', entity)
150
151
  .eq('entity_id', entityId)
151
- .eq('organization_id', this.auth.organization_id);
152
+ .eq('organization_id', organizationId);
152
153
  if (existingError)
153
154
  throw (0, errors_1.mapPostgrestError)(existingError);
154
155
  const existingFileNames = existing.map(fileNameOf);
@@ -159,7 +160,7 @@ class SupportingFilesResource {
159
160
  extension,
160
161
  entity_type: entity,
161
162
  entity_id: entityId,
162
- organization_id: this.auth.organization_id,
163
+ organization_id: organizationId,
163
164
  created_at: new Date().toISOString(),
164
165
  created_by: this.auth.mms_id,
165
166
  })));
@@ -172,7 +173,7 @@ class SupportingFilesResource {
172
173
  const { error: storageError } = await this.supabase.storage
173
174
  .from(BUCKET)
174
175
  .remove([
175
- (0, paths_1.storagePath)(this.auth.organization_id, data.entity_type, data.entity_id, data.name, data.extension),
176
+ (0, paths_1.storagePath)((0, tenancy_1.requireOrganization)(this.auth), data.entity_type, data.entity_id, data.name, data.extension),
176
177
  ]);
177
178
  if (storageError) {
178
179
  const fileName = fileNameOf({
@@ -188,8 +189,9 @@ class SupportingFilesResource {
188
189
  * are one key. A converted lead takes no new files.
189
190
  */
190
191
  async prepare(entity, entityId, names) {
192
+ const organizationId = (0, tenancy_1.requireOrganization)(this.auth);
191
193
  if (entity === enum_1.SupportingFilesEntityTypes.LEAD) {
192
- await (0, won_1.refuseWonLead)(this.supabase, this.auth.organization_id, entityId);
194
+ await (0, won_1.refuseWonLead)(this.supabase, organizationId, entityId);
193
195
  }
194
196
  return names.map((fileName) => {
195
197
  const { name, extension } = (0, paths_1.splitFileName)((0, paths_1.sanitizeFileName)(fileName));
@@ -203,7 +205,7 @@ class SupportingFilesResource {
203
205
  return {
204
206
  name,
205
207
  extension: extension,
206
- path: (0, paths_1.storagePath)(this.auth.organization_id, entity, entityId, name, extension),
208
+ path: (0, paths_1.storagePath)(organizationId, entity, entityId, name, extension),
207
209
  };
208
210
  });
209
211
  }
@@ -221,7 +221,7 @@ class TasksResource {
221
221
  return (0, transforms_1.toMmsList)(rows, page, pageSize, count);
222
222
  }
223
223
  async getById(taskId) {
224
- const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('tasks').select(TASK_DETAIL_SELECT).eq('mms_id', taskId), this.auth)
224
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('tasks').select((0, tenancy_1.withOrganization)(TASK_DETAIL_SELECT, this.auth)).eq('mms_id', taskId), this.auth)
225
225
  .order('created_at', { referencedTable: 'links_out' })
226
226
  .order('created_at', { referencedTable: 'links_in' })
227
227
  .single();
package/dist/tenancy.d.ts CHANGED
@@ -7,7 +7,7 @@ export declare const scopeToOrganization: <Q extends PostgrestFilterBuilder<any,
7
7
  export declare const requireOrganization: (actor: {
8
8
  organization_id: string | null;
9
9
  }) => string;
10
- /** A list select, plus each row's organization on a staff read so the row says whose it is. */
10
+ /** A select, plus the row's organization on a staff read so the row says whose it is. */
11
11
  export declare const withOrganization: (select: string, actor: {
12
12
  organization_id: string | null;
13
13
  }) => string;
package/dist/tenancy.js CHANGED
@@ -20,6 +20,6 @@ const requireOrganization = (actor) => {
20
20
  return actor.organization_id;
21
21
  };
22
22
  exports.requireOrganization = requireOrganization;
23
- /** A list select, plus each row's organization on a staff read so the row says whose it is. */
23
+ /** A select, plus the row's organization on a staff read so the row says whose it is. */
24
24
  const withOrganization = (select, actor) => actor.organization_id === null ? `${select}, organization:organizations!organization_id(mms_id, name)` : select;
25
25
  exports.withOrganization = withOrganization;
@@ -75,7 +75,7 @@ class UsersResource {
75
75
  return (0, transforms_1.toMmsList)(data, page, pageSize, count);
76
76
  }
77
77
  async getRow(userId) {
78
- const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('users').select('*').eq('mms_id', userId), this.auth).single();
78
+ const { data, error } = await (0, tenancy_1.scopeToOrganization)(this.supabase.from('users').select((0, tenancy_1.withOrganization)('*', this.auth)).eq('mms_id', userId), this.auth).single();
79
79
  if (error)
80
80
  throw (0, errors_1.mapPostgrestError)(error);
81
81
  return (0, audit_1.withoutInternalId)(data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managemint-solutions/sdk",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "Typed Supabase data-access SDK for ManageMint Solutions",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Scott Bebington <scottbebington@gmail.com>",
@@ -51,7 +51,7 @@
51
51
  "testEnvironment": "node"
52
52
  },
53
53
  "dependencies": {
54
- "@managemint-solutions/entities": "^1.36.0"
54
+ "@managemint-solutions/entities": "^1.37.0"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@nestjs/common": "^11.0.0",