@managemint-solutions/sdk 0.6.0 → 0.8.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 +69 -2
- package/dist/auth-client/dto.d.ts +19 -0
- package/dist/auth-client/dto.js +72 -0
- package/dist/auth-client/dto.js.map +1 -0
- package/dist/auth-client/index.d.ts +41 -0
- package/dist/auth-client/index.js +139 -0
- package/dist/auth-client/index.js.map +1 -0
- package/dist/errors.d.ts +7 -1
- package/dist/errors.js +12 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/nest/index.d.ts +5 -0
- package/dist/nest/index.js +10 -1
- package/dist/nest/index.js.map +1 -1
- package/dist/pricebooks/index.d.ts +19 -0
- package/dist/pricebooks/index.js +88 -0
- package/dist/pricebooks/index.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,9 @@ are peer dependencies — the request DTOs (`AddStatusDto`, `UpdateStatusDto`, `
|
|
|
15
15
|
`AdditionalDetailsIdDto`, `GetAdditionalDetailsDto`, `AddNoteDto`, `NoteIdDto`,
|
|
16
16
|
`GetNotesDto`, `SupportingFileIdDto`, `GetSupportingFilesDto`, `GetClientsDto`, `ClientIdDto`,
|
|
17
17
|
`CreateClientDto`, `UpdateClientDto`, `GetProjectsDto`, `ProjectIdDto`, `CreateProjectDto`,
|
|
18
|
-
`UpdateProjectDto`, `GetTasksDto`, `TaskIdDto`, `CreateTaskDto`, `UpdateTaskDto`
|
|
18
|
+
`UpdateProjectDto`, `GetTasksDto`, `TaskIdDto`, `CreateTaskDto`, `UpdateTaskDto`, `SignInDto`,
|
|
19
|
+
`ExchangeRefreshTokenDto`, `SendPasswordResetEmailDto`, `ExchangeTokenHashDto`,
|
|
20
|
+
`ResetPasswordDto`) ship with their class-validator
|
|
19
21
|
decorators so consumers validate against
|
|
20
22
|
the same rules the SDK's input types describe. `@nestjs/common` (^11) is an optional peer
|
|
21
23
|
dependency, needed only for the `@managemint-solutions/sdk/nest` subpath.
|
|
@@ -196,13 +198,78 @@ The client decodes `{ mms_id, organization_id }` from the JWT itself and scopes
|
|
|
196
198
|
by `organization_id`. `supabase.supabase` is the raw `@supabase/supabase-js` client
|
|
197
199
|
(`TypedSupabaseClient`) — the escape hatch for queries not yet covered by a resource.
|
|
198
200
|
|
|
201
|
+
## Auth
|
|
202
|
+
|
|
203
|
+
`SupabaseClient` needs the caller's JWT, which the auth flows are there to produce — so sign-in,
|
|
204
|
+
refresh and the password-reset exchanges live on a separate `SupabaseAuthClient`, built from the
|
|
205
|
+
publishable key alone.
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { createSupabaseAuthClient } from '@managemint-solutions/sdk';
|
|
209
|
+
|
|
210
|
+
const auth = createSupabaseAuthClient({
|
|
211
|
+
url: process.env.SUPABASE_URL!,
|
|
212
|
+
key: process.env.SUPABASE_PUBLISHABLE_KEY!, // no caller token — these callers are logged out
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const { access_token, refresh_token } = await auth.signIn({ email, password });
|
|
216
|
+
await auth.refreshSession({ refresh_token });
|
|
217
|
+
await auth.signOut();
|
|
218
|
+
|
|
219
|
+
// The redirect URL is passed in; the SDK reads no environment variables.
|
|
220
|
+
await auth.sendPasswordResetEmail({ email }, `${process.env.FRONTEND_URL}/reset-password`);
|
|
221
|
+
await auth.exchangeRecoveryToken({ token_hash }); // recovery link → tokens
|
|
222
|
+
await auth.exchangeConfirmToken({ token_hash }); // signup confirmation link → tokens
|
|
223
|
+
await auth.resetPassword({ password, access_token, refresh_token });
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`signIn` also stamps `users.last_logged_in` for the user who just signed in, on a throwaway
|
|
227
|
+
client carrying the fresh access token; a failed stamp never fails the login. `signOut` is a
|
|
228
|
+
no-op server-side — the client holds no session — and is kept for parity with the api endpoint
|
|
229
|
+
it replaces. `auth.supabase` is the raw `@supabase/supabase-js` client.
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import { SupabasePublicClient } from '@managemint-solutions/sdk/nest';
|
|
233
|
+
import { SignInDto, SupabaseAuthClient } from '@managemint-solutions/sdk';
|
|
234
|
+
|
|
235
|
+
@Controller('auth')
|
|
236
|
+
export class AuthController {
|
|
237
|
+
@Post('sign-in')
|
|
238
|
+
signIn(@SupabasePublicClient() auth: SupabaseAuthClient, @Body() body: SignInDto) {
|
|
239
|
+
return auth.signIn(body);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Pricebooks
|
|
245
|
+
|
|
246
|
+
The price catalog (`pricebooks`, `pricebook_modules`, `billing_modules`) is readable by `anon`
|
|
247
|
+
by design — an unauthenticated signup prices against it — so `pricebooks` hangs off the same
|
|
248
|
+
bearer-less `SupabaseAuthClient` as the auth flows, takes no auth context and scopes by nothing.
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { monthlyTotalMinor } from '@managemint-solutions/sdk';
|
|
252
|
+
import type { PricebookWithModules } from '@managemint-solutions/entities/modules';
|
|
253
|
+
|
|
254
|
+
const pricebook: PricebookWithModules = await auth.pricebooks.getActive();
|
|
255
|
+
await auth.pricebooks.getById(pricebookId); // e.g. the pricebook an organization is pinned to
|
|
256
|
+
|
|
257
|
+
// What the selected modules cost per month, in minor units. A module the pricebook does not
|
|
258
|
+
// price throws a 400 `Pricing Error`.
|
|
259
|
+
const total = monthlyTotalMinor(pricebook, ['CRM'], seatCount);
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Each pricebook comes back with its `modules` flattened to `PricedModule`s (the `pricebook_modules`
|
|
263
|
+
row joined with its `billing_modules` catalog entry). Exactly one pricebook is active at a time.
|
|
264
|
+
|
|
199
265
|
## Errors
|
|
200
266
|
|
|
201
267
|
Every error the SDK throws is a `SupabaseClientError` carrying the HTTP `status` to respond
|
|
202
268
|
with and the client-facing body, `toResponse()` → `{ error, message }`. Postgrest/Postgres
|
|
203
269
|
errors are translated by `mapPostgrestError` (Postgrest code → status, RLS permission and
|
|
204
270
|
module denials → readable messages), Storage errors by `mapStorageError` (the storage error's
|
|
205
|
-
own HTTP status, or 500 when it has none)
|
|
271
|
+
own HTTP status, or 500 when it has none), Supabase Auth errors by `mapAuthError` (same rule,
|
|
272
|
+
`Authentication Error`); JWT problems are `401 Authentication Error`. Consumers
|
|
206
273
|
return these as-is instead of mapping database errors themselves.
|
|
207
274
|
|
|
208
275
|
## NestJS
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExchangeRefreshTokenDto as ExchangeRefreshTokenDtoType, ExchangeTokenHashDto as ExchangeTokenHashDtoType, loginDto as LoginDtoType, ResetPasswordDto as ResetPasswordDtoType, SendPasswordResetEmailDto as SendPasswordResetEmailDtoType } from '@managemint-solutions/entities/auth/dto';
|
|
2
|
+
export declare class SignInDto implements LoginDtoType {
|
|
3
|
+
readonly email: string;
|
|
4
|
+
readonly password: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class ExchangeRefreshTokenDto implements ExchangeRefreshTokenDtoType {
|
|
7
|
+
readonly refresh_token: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class SendPasswordResetEmailDto implements SendPasswordResetEmailDtoType {
|
|
10
|
+
readonly email: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class ExchangeTokenHashDto implements ExchangeTokenHashDtoType {
|
|
13
|
+
readonly token_hash: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class ResetPasswordDto implements ResetPasswordDtoType {
|
|
16
|
+
readonly password: string;
|
|
17
|
+
readonly access_token: string;
|
|
18
|
+
readonly refresh_token: string;
|
|
19
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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.ResetPasswordDto = exports.ExchangeTokenHashDto = exports.SendPasswordResetEmailDto = exports.ExchangeRefreshTokenDto = exports.SignInDto = void 0;
|
|
13
|
+
const class_validator_1 = require("class-validator");
|
|
14
|
+
// class-validator versions of the shared DTO types from @managemint-solutions/entities.
|
|
15
|
+
// Each class `implements` its entities type so the wire contract cannot drift.
|
|
16
|
+
// The entities type is spelled `loginDto` (lowercase); the class keeps the `SignInDto` name.
|
|
17
|
+
class SignInDto {
|
|
18
|
+
email;
|
|
19
|
+
password;
|
|
20
|
+
}
|
|
21
|
+
exports.SignInDto = SignInDto;
|
|
22
|
+
__decorate([
|
|
23
|
+
(0, class_validator_1.IsEmail)({}, { message: 'Email is required' }),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], SignInDto.prototype, "email", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, class_validator_1.IsString)({ message: 'Password is required' }),
|
|
28
|
+
__metadata("design:type", String)
|
|
29
|
+
], SignInDto.prototype, "password", void 0);
|
|
30
|
+
class ExchangeRefreshTokenDto {
|
|
31
|
+
refresh_token;
|
|
32
|
+
}
|
|
33
|
+
exports.ExchangeRefreshTokenDto = ExchangeRefreshTokenDto;
|
|
34
|
+
__decorate([
|
|
35
|
+
(0, class_validator_1.IsString)({ message: 'Refresh token is required' }),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], ExchangeRefreshTokenDto.prototype, "refresh_token", void 0);
|
|
38
|
+
class SendPasswordResetEmailDto {
|
|
39
|
+
email;
|
|
40
|
+
}
|
|
41
|
+
exports.SendPasswordResetEmailDto = SendPasswordResetEmailDto;
|
|
42
|
+
__decorate([
|
|
43
|
+
(0, class_validator_1.IsEmail)({}, { message: 'Email is required' }),
|
|
44
|
+
__metadata("design:type", String)
|
|
45
|
+
], SendPasswordResetEmailDto.prototype, "email", void 0);
|
|
46
|
+
class ExchangeTokenHashDto {
|
|
47
|
+
token_hash;
|
|
48
|
+
}
|
|
49
|
+
exports.ExchangeTokenHashDto = ExchangeTokenHashDto;
|
|
50
|
+
__decorate([
|
|
51
|
+
(0, class_validator_1.IsString)({ message: 'Token hash is required' }),
|
|
52
|
+
__metadata("design:type", String)
|
|
53
|
+
], ExchangeTokenHashDto.prototype, "token_hash", void 0);
|
|
54
|
+
class ResetPasswordDto {
|
|
55
|
+
password;
|
|
56
|
+
access_token;
|
|
57
|
+
refresh_token;
|
|
58
|
+
}
|
|
59
|
+
exports.ResetPasswordDto = ResetPasswordDto;
|
|
60
|
+
__decorate([
|
|
61
|
+
(0, class_validator_1.IsString)({ message: 'Password is required' }),
|
|
62
|
+
__metadata("design:type", String)
|
|
63
|
+
], ResetPasswordDto.prototype, "password", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
(0, class_validator_1.IsString)({ message: 'Access token is required' }),
|
|
66
|
+
__metadata("design:type", String)
|
|
67
|
+
], ResetPasswordDto.prototype, "access_token", void 0);
|
|
68
|
+
__decorate([
|
|
69
|
+
(0, class_validator_1.IsString)({ message: 'Refresh token is required' }),
|
|
70
|
+
__metadata("design:type", String)
|
|
71
|
+
], ResetPasswordDto.prototype, "refresh_token", void 0);
|
|
72
|
+
//# sourceMappingURL=dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dto.js","sourceRoot":"","sources":["../../src/auth-client/dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAoD;AASpD,wFAAwF;AACxF,+EAA+E;AAE/E,6FAA6F;AAC7F,MAAa,SAAS;IAEX,KAAK,CAAU;IAGf,QAAQ,CAAU;CAC5B;AAND,8BAMC;AAJU;IADR,IAAA,yBAAO,EAAC,EAAE,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;;wCACtB;AAGf;IADR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;;2CACnB;AAG7B,MAAa,uBAAuB;IAEzB,aAAa,CAAU;CACjC;AAHD,0DAGC;AADU;IADR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;;8DACnB;AAGlC,MAAa,yBAAyB;IAE3B,KAAK,CAAU;CACzB;AAHD,8DAGC;AADU;IADR,IAAA,yBAAO,EAAC,EAAE,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;;wDACtB;AAG1B,MAAa,oBAAoB;IAEtB,UAAU,CAAU;CAC9B;AAHD,oDAGC;AADU;IADR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC;;wDACnB;AAG/B,MAAa,gBAAgB;IAElB,QAAQ,CAAU;IAGlB,YAAY,CAAU;IAGtB,aAAa,CAAU;CACjC;AATD,4CASC;AAPU;IADR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;;kDACnB;AAGlB;IADR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;;sDACnB;AAGtB;IADR,IAAA,0BAAQ,EAAC,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC;;uDACnB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type SupabaseClient as SupabaseJsClient } from '@supabase/supabase-js';
|
|
2
|
+
import type { ExchangeTokenResponse, LoginResponse } from '@managemint-solutions/entities/auth';
|
|
3
|
+
import type { ExchangeRefreshTokenDto, ExchangeTokenHashDto, loginDto, ResetPasswordDto, SendPasswordResetEmailDto } from '@managemint-solutions/entities/auth/dto';
|
|
4
|
+
import { PricebooksResource } from '../pricebooks';
|
|
5
|
+
export * from './dto';
|
|
6
|
+
export type SupabaseAuthClientConfig = {
|
|
7
|
+
url: string;
|
|
8
|
+
key: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The client for callers that do not have a JWT yet: the auth flows, and the public catalog
|
|
12
|
+
* (`pricebooks`) an unauthenticated signup prices against. `SupabaseClient` needs the caller's
|
|
13
|
+
* token to build its RLS context, so sign-in, refresh and the password-reset exchanges live on
|
|
14
|
+
* this separate client, built from the publishable key alone.
|
|
15
|
+
*/
|
|
16
|
+
export declare class SupabaseAuthClient {
|
|
17
|
+
private readonly config;
|
|
18
|
+
readonly supabase: SupabaseJsClient;
|
|
19
|
+
readonly pricebooks: PricebooksResource;
|
|
20
|
+
constructor(config: SupabaseAuthClientConfig);
|
|
21
|
+
signIn(input: loginDto): Promise<LoginResponse>;
|
|
22
|
+
refreshSession(input: ExchangeRefreshTokenDto): Promise<ExchangeTokenResponse>;
|
|
23
|
+
/**
|
|
24
|
+
* Parity with the api: this client never holds a session (`persistSession` is off), so
|
|
25
|
+
* server-side there is nothing to revoke and the call is a no-op. Kept as the api had it.
|
|
26
|
+
*/
|
|
27
|
+
signOut(): Promise<void>;
|
|
28
|
+
/** `redirectTo` is passed in — the SDK reads no environment variables. */
|
|
29
|
+
sendPasswordResetEmail(input: SendPasswordResetEmailDto, redirectTo: string): Promise<void>;
|
|
30
|
+
exchangeRecoveryToken(input: ExchangeTokenHashDto): Promise<ExchangeTokenResponse>;
|
|
31
|
+
exchangeConfirmToken(input: ExchangeTokenHashDto): Promise<ExchangeTokenResponse>;
|
|
32
|
+
resetPassword(input: ResetPasswordDto): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Stamps `users.last_logged_in` as the user who just signed in — the users UPDATE policy
|
|
35
|
+
* allows `auth.uid() = mms_id`, so the write goes through a throwaway client carrying the
|
|
36
|
+
* fresh access token rather than this session-less one. Parity with the api: the result is
|
|
37
|
+
* ignored, a failed stamp must not fail the login.
|
|
38
|
+
*/
|
|
39
|
+
private stampLastLoggedIn;
|
|
40
|
+
}
|
|
41
|
+
export declare const createSupabaseAuthClient: (config: SupabaseAuthClientConfig) => SupabaseAuthClient;
|
|
@@ -0,0 +1,139 @@
|
|
|
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.createSupabaseAuthClient = exports.SupabaseAuthClient = void 0;
|
|
18
|
+
const supabase_js_1 = require("@supabase/supabase-js");
|
|
19
|
+
const errors_1 = require("../errors");
|
|
20
|
+
const pricebooks_1 = require("../pricebooks");
|
|
21
|
+
__exportStar(require("./dto"), exports);
|
|
22
|
+
// The api's "no session/user returned" NotFoundException, as an SDK error.
|
|
23
|
+
const noSession = (message) => new errors_1.SupabaseClientError({ status: 404, error: 'Authentication Error', message });
|
|
24
|
+
const toTokens = (session) => ({
|
|
25
|
+
access_token: session.access_token,
|
|
26
|
+
refresh_token: session.refresh_token,
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* The client for callers that do not have a JWT yet: the auth flows, and the public catalog
|
|
30
|
+
* (`pricebooks`) an unauthenticated signup prices against. `SupabaseClient` needs the caller's
|
|
31
|
+
* token to build its RLS context, so sign-in, refresh and the password-reset exchanges live on
|
|
32
|
+
* this separate client, built from the publishable key alone.
|
|
33
|
+
*/
|
|
34
|
+
class SupabaseAuthClient {
|
|
35
|
+
config;
|
|
36
|
+
supabase; // escape hatch for flows not covered by a method
|
|
37
|
+
pricebooks;
|
|
38
|
+
constructor(config) {
|
|
39
|
+
this.config = config;
|
|
40
|
+
this.supabase = (0, supabase_js_1.createClient)(config.url, config.key, {
|
|
41
|
+
// Server-side and stateless: nothing is stored, refreshed or read out of a URL.
|
|
42
|
+
auth: { persistSession: false, autoRefreshToken: false, detectSessionInUrl: false },
|
|
43
|
+
});
|
|
44
|
+
this.pricebooks = new pricebooks_1.PricebooksResource(this.supabase);
|
|
45
|
+
}
|
|
46
|
+
async signIn(input) {
|
|
47
|
+
const { data, error } = await this.supabase.auth.signInWithPassword({
|
|
48
|
+
email: input.email,
|
|
49
|
+
password: input.password,
|
|
50
|
+
});
|
|
51
|
+
if (error)
|
|
52
|
+
throw (0, errors_1.mapAuthError)(error);
|
|
53
|
+
if (!data.session || !data.user) {
|
|
54
|
+
throw noSession('Authentication failed: No session or user data returned');
|
|
55
|
+
}
|
|
56
|
+
await this.stampLastLoggedIn(data.session.access_token, data.user.id);
|
|
57
|
+
return toTokens(data.session);
|
|
58
|
+
}
|
|
59
|
+
async refreshSession(input) {
|
|
60
|
+
const { data, error } = await this.supabase.auth.refreshSession({
|
|
61
|
+
refresh_token: input.refresh_token,
|
|
62
|
+
});
|
|
63
|
+
if (error)
|
|
64
|
+
throw (0, errors_1.mapAuthError)(error);
|
|
65
|
+
if (!data.session)
|
|
66
|
+
throw noSession('Token exchange failed: No session data returned');
|
|
67
|
+
return toTokens(data.session);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Parity with the api: this client never holds a session (`persistSession` is off), so
|
|
71
|
+
* server-side there is nothing to revoke and the call is a no-op. Kept as the api had it.
|
|
72
|
+
*/
|
|
73
|
+
async signOut() {
|
|
74
|
+
const { error } = await this.supabase.auth.signOut();
|
|
75
|
+
if (error)
|
|
76
|
+
throw (0, errors_1.mapAuthError)(error);
|
|
77
|
+
}
|
|
78
|
+
/** `redirectTo` is passed in — the SDK reads no environment variables. */
|
|
79
|
+
async sendPasswordResetEmail(input, redirectTo) {
|
|
80
|
+
const { error } = await this.supabase.auth.resetPasswordForEmail(input.email, { redirectTo });
|
|
81
|
+
if (error)
|
|
82
|
+
throw (0, errors_1.mapAuthError)(error);
|
|
83
|
+
}
|
|
84
|
+
async exchangeRecoveryToken(input) {
|
|
85
|
+
const { data, error } = await this.supabase.auth.verifyOtp({
|
|
86
|
+
type: 'recovery',
|
|
87
|
+
token_hash: input.token_hash,
|
|
88
|
+
});
|
|
89
|
+
if (error)
|
|
90
|
+
throw (0, errors_1.mapAuthError)(error);
|
|
91
|
+
if (!data.session)
|
|
92
|
+
throw noSession('Token exchange failed: No session data returned');
|
|
93
|
+
return toTokens(data.session);
|
|
94
|
+
}
|
|
95
|
+
async exchangeConfirmToken(input) {
|
|
96
|
+
const { data, error } = await this.supabase.auth.verifyOtp({
|
|
97
|
+
type: 'signup',
|
|
98
|
+
token_hash: input.token_hash,
|
|
99
|
+
});
|
|
100
|
+
if (error)
|
|
101
|
+
throw (0, errors_1.mapAuthError)(error);
|
|
102
|
+
if (!data.session)
|
|
103
|
+
throw noSession('Token exchange failed: No session data returned');
|
|
104
|
+
return toTokens(data.session);
|
|
105
|
+
}
|
|
106
|
+
async resetPassword(input) {
|
|
107
|
+
const { error: sessionError } = await this.supabase.auth.setSession({
|
|
108
|
+
access_token: input.access_token,
|
|
109
|
+
refresh_token: input.refresh_token,
|
|
110
|
+
});
|
|
111
|
+
if (sessionError)
|
|
112
|
+
throw (0, errors_1.mapAuthError)(sessionError);
|
|
113
|
+
const { error: updateError } = await this.supabase.auth.updateUser({
|
|
114
|
+
password: input.password,
|
|
115
|
+
});
|
|
116
|
+
if (updateError)
|
|
117
|
+
throw (0, errors_1.mapAuthError)(updateError);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Stamps `users.last_logged_in` as the user who just signed in — the users UPDATE policy
|
|
121
|
+
* allows `auth.uid() = mms_id`, so the write goes through a throwaway client carrying the
|
|
122
|
+
* fresh access token rather than this session-less one. Parity with the api: the result is
|
|
123
|
+
* ignored, a failed stamp must not fail the login.
|
|
124
|
+
*/
|
|
125
|
+
async stampLastLoggedIn(accessToken, userId) {
|
|
126
|
+
const asUser = (0, supabase_js_1.createClient)(this.config.url, this.config.key, {
|
|
127
|
+
global: { headers: { Authorization: `Bearer ${accessToken}` } },
|
|
128
|
+
auth: { persistSession: false, autoRefreshToken: false },
|
|
129
|
+
});
|
|
130
|
+
await asUser
|
|
131
|
+
.from('users')
|
|
132
|
+
.update({ last_logged_in: new Date().toISOString() })
|
|
133
|
+
.eq('mms_id', userId);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.SupabaseAuthClient = SupabaseAuthClient;
|
|
137
|
+
const createSupabaseAuthClient = (config) => new SupabaseAuthClient(config);
|
|
138
|
+
exports.createSupabaseAuthClient = createSupabaseAuthClient;
|
|
139
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth-client/index.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StorageError } from '@supabase/storage-js';
|
|
2
|
-
import type { PostgrestError } from '@supabase/supabase-js';
|
|
2
|
+
import type { AuthError, PostgrestError } from '@supabase/supabase-js';
|
|
3
3
|
export type SupabaseClientErrorInit = {
|
|
4
4
|
/** HTTP status the consumer should respond with. */
|
|
5
5
|
status: number;
|
|
@@ -34,3 +34,9 @@ export declare const mapPostgrestError: (error: PostgrestError) => SupabaseClien
|
|
|
34
34
|
* network/unknown failures have none, hence the 500 fallback.
|
|
35
35
|
*/
|
|
36
36
|
export declare const mapStorageError: (error: StorageError, message?: string) => SupabaseClientError;
|
|
37
|
+
/**
|
|
38
|
+
* Converts a Supabase Auth (GoTrue) error into the SupabaseClientError the SDK throws — the
|
|
39
|
+
* SDK-side equivalent of the api's `throwAuthErrorResponse`. `AuthError.status` is the HTTP
|
|
40
|
+
* status GoTrue answered with; network/unknown failures carry none, hence the 500 fallback.
|
|
41
|
+
*/
|
|
42
|
+
export declare const mapAuthError: (error: AuthError) => SupabaseClientError;
|
package/dist/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mapStorageError = exports.mapPostgrestError = exports.SupabaseClientError = void 0;
|
|
3
|
+
exports.mapAuthError = exports.mapStorageError = exports.mapPostgrestError = exports.SupabaseClientError = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Every error the SDK throws. It already carries the HTTP status and the body the
|
|
6
6
|
* consumer sends back to the client (`toResponse()`), so the api needs no mapping.
|
|
@@ -140,4 +140,15 @@ const mapStorageError = (error, message = error.message) => new SupabaseClientEr
|
|
|
140
140
|
message,
|
|
141
141
|
}, { cause: error });
|
|
142
142
|
exports.mapStorageError = mapStorageError;
|
|
143
|
+
/**
|
|
144
|
+
* Converts a Supabase Auth (GoTrue) error into the SupabaseClientError the SDK throws — the
|
|
145
|
+
* SDK-side equivalent of the api's `throwAuthErrorResponse`. `AuthError.status` is the HTTP
|
|
146
|
+
* status GoTrue answered with; network/unknown failures carry none, hence the 500 fallback.
|
|
147
|
+
*/
|
|
148
|
+
const mapAuthError = (error) => new SupabaseClientError({
|
|
149
|
+
status: error.status ?? 500,
|
|
150
|
+
error: 'Authentication Error',
|
|
151
|
+
message: error.message,
|
|
152
|
+
}, { cause: error });
|
|
153
|
+
exports.mapAuthError = mapAuthError;
|
|
143
154
|
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './client';
|
|
2
2
|
export * from './auth';
|
|
3
|
+
export * from './auth-client';
|
|
3
4
|
export * from './errors';
|
|
4
5
|
export * from './validators';
|
|
5
6
|
export * from './transforms';
|
|
@@ -10,3 +11,4 @@ export * from './supporting-files';
|
|
|
10
11
|
export * from './clients';
|
|
11
12
|
export * from './projects';
|
|
12
13
|
export * from './tasks';
|
|
14
|
+
export * from './pricebooks';
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./client"), exports);
|
|
18
18
|
__exportStar(require("./auth"), exports);
|
|
19
|
+
__exportStar(require("./auth-client"), exports);
|
|
19
20
|
__exportStar(require("./errors"), exports);
|
|
20
21
|
__exportStar(require("./validators"), exports);
|
|
21
22
|
__exportStar(require("./transforms"), exports);
|
|
@@ -26,4 +27,5 @@ __exportStar(require("./supporting-files"), exports);
|
|
|
26
27
|
__exportStar(require("./clients"), exports);
|
|
27
28
|
__exportStar(require("./projects"), exports);
|
|
28
29
|
__exportStar(require("./tasks"), exports);
|
|
30
|
+
__exportStar(require("./pricebooks"), exports);
|
|
29
31
|
//# 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,+CAA6B;AAC7B,+CAA6B;AAC7B,6CAA2B;AAC3B,uDAAqC;AACrC,0CAAwB;AACxB,qDAAmC;AACnC,4CAA0B;AAC1B,6CAA2B;AAC3B,0CAAwB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,yCAAuB;AACvB,gDAA8B;AAC9B,2CAAyB;AACzB,+CAA6B;AAC7B,+CAA6B;AAC7B,6CAA2B;AAC3B,uDAAqC;AACrC,0CAAwB;AACxB,qDAAmC;AACnC,4CAA0B;AAC1B,6CAA2B;AAC3B,0CAAwB;AACxB,+CAA6B"}
|
package/dist/nest/index.d.ts
CHANGED
|
@@ -7,3 +7,8 @@ import { SupabaseClientError } from '../errors';
|
|
|
7
7
|
*/
|
|
8
8
|
export declare const toHttpException: (error: SupabaseClientError) => HttpException;
|
|
9
9
|
export declare const SupabaseUserClient: (...dataOrPipes: unknown[]) => ParameterDecorator;
|
|
10
|
+
/**
|
|
11
|
+
* A `SupabaseAuthClient` for routes a logged-out caller hits (sign-in, refresh, password
|
|
12
|
+
* reset) — built from the publishable key alone, with no bearer token involved.
|
|
13
|
+
*/
|
|
14
|
+
export declare const SupabasePublicClient: (...dataOrPipes: any[]) => ParameterDecorator;
|
package/dist/nest/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SupabaseUserClient = exports.toHttpException = void 0;
|
|
3
|
+
exports.SupabasePublicClient = exports.SupabaseUserClient = exports.toHttpException = void 0;
|
|
4
4
|
const common_1 = require("@nestjs/common");
|
|
5
|
+
const auth_client_1 = require("../auth-client");
|
|
5
6
|
const client_1 = require("../client");
|
|
6
7
|
const errors_1 = require("../errors");
|
|
7
8
|
/**
|
|
@@ -44,4 +45,12 @@ exports.SupabaseUserClient = (0, common_1.createParamDecorator)((_, ctx) => {
|
|
|
44
45
|
throw error;
|
|
45
46
|
}
|
|
46
47
|
});
|
|
48
|
+
/**
|
|
49
|
+
* A `SupabaseAuthClient` for routes a logged-out caller hits (sign-in, refresh, password
|
|
50
|
+
* reset) — built from the publishable key alone, with no bearer token involved.
|
|
51
|
+
*/
|
|
52
|
+
exports.SupabasePublicClient = (0, common_1.createParamDecorator)(() => (0, auth_client_1.createSupabaseAuthClient)({
|
|
53
|
+
url: getEnvOrThrow('SUPABASE_URL'),
|
|
54
|
+
key: getEnvOrThrow('SUPABASE_PUBLISHABLE_KEY'),
|
|
55
|
+
}));
|
|
47
56
|
//# sourceMappingURL=index.js.map
|
package/dist/nest/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nest/index.ts"],"names":[],"mappings":";;;AAAA,2CAMwB;AAExB,sCAAsE;AACtE,sCAAgD;AAEhD;;;;GAIG;AACI,MAAM,eAAe,GAAG,CAAC,KAA0B,EAAiB,EAAE,CAC3E,IAAI,sBAAa,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAD3D,QAAA,eAAe,mBAC4C;AAExE,MAAM,aAAa,GAAG,CAAC,GAAgD,EAAU,EAAE;IACjF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,qCAA4B,CAAC,GAAG,GAAG,oBAAoB,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAU,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,8BAAqB,CAAC,0BAA0B,CAAC,CAAC;IACzE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,MAAM,EAAE,WAAW,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACjD,MAAM,IAAI,8BAAqB,CAAC,4CAA4C,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEW,QAAA,kBAAkB,GAAG,IAAA,6BAAoB,EACpD,CAAC,CAAU,EAAE,GAAqB,EAAkB,EAAE;IACpD,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,OAAO,IAAA,6BAAoB,EAAC;YAC1B,GAAG,EAAE,aAAa,CAAC,cAAc,CAAC;YAClC,GAAG,EAAE,aAAa,CAAC,0BAA0B,CAAC;YAC9C,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,+EAA+E;QAC/E,qCAAqC;QACrC,IAAI,KAAK,YAAY,4BAAmB;YAAE,MAAM,IAAA,uBAAe,EAAC,KAAK,CAAC,CAAC;QACvE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nest/index.ts"],"names":[],"mappings":";;;AAAA,2CAMwB;AAExB,gDAAmF;AACnF,sCAAsE;AACtE,sCAAgD;AAEhD;;;;GAIG;AACI,MAAM,eAAe,GAAG,CAAC,KAA0B,EAAiB,EAAE,CAC3E,IAAI,sBAAa,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAD3D,QAAA,eAAe,mBAC4C;AAExE,MAAM,aAAa,GAAG,CAAC,GAAgD,EAAU,EAAE;IACjF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,qCAA4B,CAAC,GAAG,GAAG,oBAAoB,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAU,EAAE;IAClD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,8BAAqB,CAAC,0BAA0B,CAAC,CAAC;IACzE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,MAAM,EAAE,WAAW,EAAE,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACjD,MAAM,IAAI,8BAAqB,CAAC,4CAA4C,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEW,QAAA,kBAAkB,GAAG,IAAA,6BAAoB,EACpD,CAAC,CAAU,EAAE,GAAqB,EAAkB,EAAE;IACpD,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC,CAAC;IACvE,IAAI,CAAC;QACH,OAAO,IAAA,6BAAoB,EAAC;YAC1B,GAAG,EAAE,aAAa,CAAC,cAAc,CAAC;YAClC,GAAG,EAAE,aAAa,CAAC,0BAA0B,CAAC;YAC9C,WAAW,EAAE,KAAK;SACnB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,+EAA+E;QAC/E,qCAAqC;QACrC,IAAI,KAAK,YAAY,4BAAmB;YAAE,MAAM,IAAA,uBAAe,EAAC,KAAK,CAAC,CAAC;QACvE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CACF,CAAC;AAEF;;;GAGG;AACU,QAAA,oBAAoB,GAAG,IAAA,6BAAoB,EACtD,GAAuB,EAAE,CACvB,IAAA,sCAAwB,EAAC;IACvB,GAAG,EAAE,aAAa,CAAC,cAAc,CAAC;IAClC,GAAG,EAAE,aAAa,CAAC,0BAA0B,CAAC;CAC/C,CAAC,CACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SupabaseClient as SupabaseJsClient } from '@supabase/supabase-js';
|
|
2
|
+
import type { PricebookWithModules } from '@managemint-solutions/entities/modules';
|
|
3
|
+
/**
|
|
4
|
+
* The public price catalog. `pricebooks`, `pricebook_modules` and `billing_modules` are readable
|
|
5
|
+
* by `anon` by design — unauthenticated signup prices against them — so this resource takes no
|
|
6
|
+
* auth context and scopes by nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PricebooksResource {
|
|
9
|
+
private readonly supabase;
|
|
10
|
+
constructor(supabase: SupabaseJsClient);
|
|
11
|
+
getActive(): Promise<PricebookWithModules>;
|
|
12
|
+
getById(pricebookId: string): Promise<PricebookWithModules>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* What the given modules cost per month, in minor units: every module's unit price summed and
|
|
16
|
+
* multiplied by the seat count. A module the pricebook does not price is a 400 — the caller
|
|
17
|
+
* asked for something that cannot be billed.
|
|
18
|
+
*/
|
|
19
|
+
export declare const monthlyTotalMinor: (pricebook: PricebookWithModules, moduleKeys: string[], seatCount: number) => number;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.monthlyTotalMinor = exports.PricebooksResource = void 0;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
// The public contract is PricebookWithModules from @managemint-solutions/entities; the row
|
|
6
|
+
// types below only declare the shape this select string produces (the columns are defined in
|
|
7
|
+
// the api's supabase/migrations).
|
|
8
|
+
const PRICEBOOK_SELECT = `
|
|
9
|
+
mms_id,
|
|
10
|
+
name,
|
|
11
|
+
description,
|
|
12
|
+
active,
|
|
13
|
+
pricebook_modules (
|
|
14
|
+
module_id,
|
|
15
|
+
unit_amount_minor,
|
|
16
|
+
currency,
|
|
17
|
+
billing_modules (
|
|
18
|
+
module_key
|
|
19
|
+
)
|
|
20
|
+
)
|
|
21
|
+
`;
|
|
22
|
+
// A pricebook_modules row whose catalog entry did not come back leaves `module_key` undefined —
|
|
23
|
+
// the cast keeps the mapping honest about that rather than inventing a key.
|
|
24
|
+
const toPricebookWithModules = (row) => ({
|
|
25
|
+
mms_id: row.mms_id,
|
|
26
|
+
name: row.name,
|
|
27
|
+
active: row.active,
|
|
28
|
+
description: row.description,
|
|
29
|
+
modules: (row.pricebook_modules || []).map((pricedModule) => ({
|
|
30
|
+
module_id: pricedModule.module_id,
|
|
31
|
+
module_key: pricedModule.billing_modules?.module_key,
|
|
32
|
+
unit_amount_minor: pricedModule.unit_amount_minor,
|
|
33
|
+
currency: pricedModule.currency,
|
|
34
|
+
})),
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* The public price catalog. `pricebooks`, `pricebook_modules` and `billing_modules` are readable
|
|
38
|
+
* by `anon` by design — unauthenticated signup prices against them — so this resource takes no
|
|
39
|
+
* auth context and scopes by nothing.
|
|
40
|
+
*/
|
|
41
|
+
class PricebooksResource {
|
|
42
|
+
supabase;
|
|
43
|
+
constructor(supabase) {
|
|
44
|
+
this.supabase = supabase;
|
|
45
|
+
}
|
|
46
|
+
async getActive() {
|
|
47
|
+
const { data, error } = await this.supabase
|
|
48
|
+
.from('pricebooks')
|
|
49
|
+
.select(PRICEBOOK_SELECT)
|
|
50
|
+
.eq('active', true)
|
|
51
|
+
.single();
|
|
52
|
+
if (error)
|
|
53
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
54
|
+
return toPricebookWithModules(data);
|
|
55
|
+
}
|
|
56
|
+
async getById(pricebookId) {
|
|
57
|
+
const { data, error } = await this.supabase
|
|
58
|
+
.from('pricebooks')
|
|
59
|
+
.select(PRICEBOOK_SELECT)
|
|
60
|
+
.eq('mms_id', pricebookId)
|
|
61
|
+
.single();
|
|
62
|
+
if (error)
|
|
63
|
+
throw (0, errors_1.mapPostgrestError)(error);
|
|
64
|
+
return toPricebookWithModules(data);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.PricebooksResource = PricebooksResource;
|
|
68
|
+
/**
|
|
69
|
+
* What the given modules cost per month, in minor units: every module's unit price summed and
|
|
70
|
+
* multiplied by the seat count. A module the pricebook does not price is a 400 — the caller
|
|
71
|
+
* asked for something that cannot be billed.
|
|
72
|
+
*/
|
|
73
|
+
const monthlyTotalMinor = (pricebook, moduleKeys, seatCount) => {
|
|
74
|
+
const total = moduleKeys.reduce((sum, moduleKey) => {
|
|
75
|
+
const pricedModule = pricebook.modules.find((module) => module.module_key === moduleKey);
|
|
76
|
+
if (!pricedModule) {
|
|
77
|
+
throw new errors_1.SupabaseClientError({
|
|
78
|
+
status: 400,
|
|
79
|
+
error: 'Pricing Error',
|
|
80
|
+
message: `Module ${moduleKey} is not priced by pricebook ${pricebook.name}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return sum + pricedModule.unit_amount_minor;
|
|
84
|
+
}, 0);
|
|
85
|
+
return total * seatCount;
|
|
86
|
+
};
|
|
87
|
+
exports.monthlyTotalMinor = monthlyTotalMinor;
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pricebooks/index.ts"],"names":[],"mappings":";;;AAEA,sCAAmE;AAEnE,2FAA2F;AAC3F,6FAA6F;AAC7F,kCAAkC;AAClC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;CAaf,CAAC;AAoBX,gGAAgG;AAChG,4EAA4E;AAC5E,MAAM,sBAAsB,GAAG,CAAC,GAAiB,EAAwB,EAAE,CAAC,CAAC;IAC3E,MAAM,EAAE,GAAG,CAAC,MAAM;IAClB,IAAI,EAAE,GAAG,CAAC,IAAI;IACd,MAAM,EAAE,GAAG,CAAC,MAAM;IAClB,WAAW,EAAE,GAAG,CAAC,WAAW;IAC5B,OAAO,EAAE,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC5D,SAAS,EAAE,YAAY,CAAC,SAAS;QACjC,UAAU,EAAE,YAAY,CAAC,eAAe,EAAE,UAAU;QACpD,iBAAiB,EAAE,YAAY,CAAC,iBAAiB;QACjD,QAAQ,EAAE,YAAY,CAAC,QAAQ;KAChC,CAAC,CAAmB;CACtB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAa,kBAAkB;IACA;IAA7B,YAA6B,QAA0B;QAA1B,aAAQ,GAAR,QAAQ,CAAkB;IAAG,CAAC;IAE3D,KAAK,CAAC,SAAS;QACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aACxC,IAAI,CAAC,YAAY,CAAC;aAClB,MAAM,CAAC,gBAAgB,CAAC;aACxB,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC;aAClB,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,sBAAsB,CAAC,IAA+B,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,WAAmB;QAC/B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ;aACxC,IAAI,CAAC,YAAY,CAAC;aAClB,MAAM,CAAC,gBAAgB,CAAC;aACxB,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;aACzB,MAAM,EAAE,CAAC;QACZ,IAAI,KAAK;YAAE,MAAM,IAAA,0BAAiB,EAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,sBAAsB,CAAC,IAA+B,CAAC,CAAC;IACjE,CAAC;CACF;AAtBD,gDAsBC;AAED;;;;GAIG;AACI,MAAM,iBAAiB,GAAG,CAC/B,SAA+B,EAC/B,UAAoB,EACpB,SAAiB,EACT,EAAE;IACV,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE;QACjD,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;QAEzF,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,4BAAmB,CAAC;gBAC5B,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,eAAe;gBACtB,OAAO,EAAE,UAAU,SAAS,+BAA+B,SAAS,CAAC,IAAI,EAAE;aAC5E,CAAC,CAAC;QACL,CAAC;QAED,OAAO,GAAG,GAAG,YAAY,CAAC,iBAAiB,CAAC;IAC9C,CAAC,EAAE,CAAC,CAAC,CAAC;IAEN,OAAO,KAAK,GAAG,SAAS,CAAC;AAC3B,CAAC,CAAC;AApBW,QAAA,iBAAiB,qBAoB5B"}
|
package/package.json
CHANGED