@monigo/sdk 0.1.6 → 0.1.8

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/dist/index.d.ts CHANGED
@@ -68,6 +68,22 @@ export declare interface CreatePlanRequest {
68
68
  prices?: CreatePriceRequest[];
69
69
  }
70
70
 
71
+ /** Request body for `portalTokens.create()`. */
72
+ export declare interface CreatePortalTokenRequest {
73
+ /**
74
+ * The `external_id` you assigned this customer when you called
75
+ * `customers.create()`.
76
+ */
77
+ customer_external_id: string;
78
+ /** Optional human-readable label, e.g. `"Main portal link"`. */
79
+ label?: string;
80
+ /**
81
+ * Optional RFC 3339 expiry timestamp. Omit to create a permanent link.
82
+ * Example: `"2027-01-01T00:00:00Z"`
83
+ */
84
+ expires_at?: string;
85
+ }
86
+
71
87
  /** Describes a price to attach when creating a plan. */
72
88
  export declare interface CreatePriceRequest {
73
89
  /** UUID of the metric this price is based on. */
@@ -93,6 +109,28 @@ export declare interface CreateSubscriptionRequest {
93
109
  plan_id: string;
94
110
  }
95
111
 
112
+ /** Request body for `wallets.createVirtualAccount()`. */
113
+ export declare interface CreateVirtualAccountRequest {
114
+ /** Use `VirtualAccountProvider` constants. */
115
+ provider: VirtualAccountProviderValue;
116
+ currency: string;
117
+ }
118
+
119
+ /** Request body for `wallets.credit()`. */
120
+ export declare interface CreditWalletRequest {
121
+ /** Amount as a decimal string, e.g. `"100.50"`. */
122
+ amount: string;
123
+ currency: string;
124
+ description: string;
125
+ /** Use `WalletEntryType` constants. */
126
+ entry_type: WalletEntryTypeValue;
127
+ reference_type: string;
128
+ reference_id: string;
129
+ idempotency_key: string;
130
+ /** Optional provider account UUID for the other side of double entry. */
131
+ provider_id?: string;
132
+ }
133
+
96
134
  /** An end-customer record in your Monigo organisation. */
97
135
  export declare interface Customer {
98
136
  id: string;
@@ -163,6 +201,33 @@ export declare class CustomersResource {
163
201
  delete(customerId: string): Promise<void>;
164
202
  }
165
203
 
204
+ /** A prepaid balance belonging to a single customer. All monetary values are decimal strings. */
205
+ export declare interface CustomerWallet {
206
+ id: string;
207
+ customer_id: string;
208
+ org_id: string;
209
+ currency: string;
210
+ /** Current available balance as a decimal string, e.g. `"500.000000"`. */
211
+ balance: string;
212
+ /** Balance reserved for pending operations. */
213
+ reserved_balance: string;
214
+ created_at: string;
215
+ updated_at: string;
216
+ }
217
+
218
+ /** Request body for `wallets.debit()`. */
219
+ export declare interface DebitWalletRequest {
220
+ /** Amount as a decimal string, e.g. `"50.25"`. */
221
+ amount: string;
222
+ currency: string;
223
+ description: string;
224
+ /** Use `WalletEntryType` constants. */
225
+ entry_type: WalletEntryTypeValue;
226
+ reference_type: string;
227
+ reference_id: string;
228
+ idempotency_key: string;
229
+ }
230
+
166
231
  /** Tracks the progress of an asynchronous event replay job. */
167
232
  export declare interface EventReplayJob {
168
233
  id: string;
@@ -247,6 +312,13 @@ export declare class EventsResource {
247
312
  getReplay(jobId: string): Promise<EventReplayJob>;
248
313
  }
249
314
 
315
+ /** Request body for `wallets.getOrCreate()`. */
316
+ export declare interface GetOrCreateWalletRequest {
317
+ org_id: string;
318
+ customer_id: string;
319
+ currency: string;
320
+ }
321
+
250
322
  /** A single usage event sent to the Monigo ingestion pipeline. */
251
323
  export declare interface IngestEvent {
252
324
  /**
@@ -390,6 +462,32 @@ export declare const InvoiceStatus: {
390
462
 
391
463
  export declare type InvoiceStatusValue = (typeof InvoiceStatus)[keyof typeof InvoiceStatus];
392
464
 
465
+ /** One side of a double-entry accounting record. */
466
+ export declare interface LedgerEntry {
467
+ id: string;
468
+ org_id: string;
469
+ transaction_id: string;
470
+ wallet_id: string | null;
471
+ /** `customer_wallet`, `provider`, or `revenue`. */
472
+ account_type: string;
473
+ account_id: string;
474
+ /** Use `WalletDirection` constants. */
475
+ direction: WalletDirectionValue;
476
+ /** Amount as a decimal string. */
477
+ amount: string;
478
+ currency: string;
479
+ balance_before: string;
480
+ balance_after: string;
481
+ description: string;
482
+ /** Use `WalletEntryType` constants. */
483
+ entry_type: WalletEntryTypeValue;
484
+ reference_type: string;
485
+ reference_id: string;
486
+ idempotency_key: string;
487
+ metadata: Record<string, unknown> | null;
488
+ created_at: string;
489
+ }
490
+
393
491
  export declare interface ListCustomersResponse {
394
492
  customers: Customer[];
395
493
  count: number;
@@ -422,6 +520,11 @@ export declare interface ListPlansResponse {
422
520
  count: number;
423
521
  }
424
522
 
523
+ export declare interface ListPortalTokensResponse {
524
+ tokens: PortalToken[];
525
+ count: number;
526
+ }
527
+
425
528
  export declare interface ListSubscriptionsParams {
426
529
  /** Filter to a specific customer UUID. */
427
530
  customer_id?: string;
@@ -436,6 +539,34 @@ export declare interface ListSubscriptionsResponse {
436
539
  count: number;
437
540
  }
438
541
 
542
+ export declare interface ListTransactionsParams {
543
+ /** Number of entries to return (1–100). Defaults to 25. */
544
+ limit?: number;
545
+ /** Number of entries to skip. Defaults to 0. */
546
+ offset?: number;
547
+ }
548
+
549
+ export declare interface ListTransactionsResponse {
550
+ transactions: LedgerEntry[];
551
+ total: number;
552
+ limit: number;
553
+ offset: number;
554
+ }
555
+
556
+ export declare interface ListVirtualAccountsResponse {
557
+ virtual_accounts: VirtualAccount[];
558
+ count: number;
559
+ }
560
+
561
+ export declare interface ListWalletsParams {
562
+ org_id: string;
563
+ }
564
+
565
+ export declare interface ListWalletsResponse {
566
+ wallets: CustomerWallet[];
567
+ count: number;
568
+ }
569
+
439
570
  /** Defines what usage is counted and how. */
440
571
  export declare interface Metric {
441
572
  id: string;
@@ -576,6 +707,10 @@ export declare class MonigoClient {
576
707
  readonly invoices: InvoicesResource;
577
708
  /** Query aggregated usage rollups per customer and metric. Requires `read` scope. */
578
709
  readonly usage: UsageResource;
710
+ /** Manage customer portal access links. Requires `read` / `write` scope. */
711
+ readonly portalTokens: PortalTokensResource;
712
+ /** Manage customer wallets, balance operations, and virtual accounts. Requires `read` / `write` scope. */
713
+ readonly wallets: WalletsResource;
579
714
  constructor(options: MonigoClientOptions);
580
715
  /* Excluded from this release type: _request */
581
716
  /** Normalise a `Date | string` value to an ISO 8601 string. */
@@ -799,6 +934,77 @@ export declare const PlanType: {
799
934
 
800
935
  export declare type PlanTypeValue = (typeof PlanType)[keyof typeof PlanType];
801
936
 
937
+ /**
938
+ * A portal token grants an end-customer read-only access to their invoices,
939
+ * payout slips, subscriptions, and payout accounts in the Monigo hosted portal.
940
+ */
941
+ export declare interface PortalToken {
942
+ id: string;
943
+ org_id: string;
944
+ customer_id: string;
945
+ /** The opaque 64-character hex token embedded in the portal URL. */
946
+ token: string;
947
+ label: string;
948
+ /** ISO 8601 expiry timestamp, or `null` for a permanent link. */
949
+ expires_at: string | null;
950
+ /** ISO 8601 revocation timestamp, or `null` if still active. */
951
+ revoked_at: string | null;
952
+ created_at: string;
953
+ updated_at: string;
954
+ /** Fully-qualified URL to share with the customer, e.g. `https://app.monigo.co/portal/<token>`. */
955
+ portal_url: string;
956
+ }
957
+
958
+ /**
959
+ * Manage customer portal access links.
960
+ *
961
+ * Portal tokens grant an end-customer read-only access to their invoices,
962
+ * payout slips, subscriptions, and payout accounts in the Monigo hosted portal.
963
+ * All operations require a write-scoped API key; the organisation is inferred
964
+ * automatically from the key.
965
+ */
966
+ export declare class PortalTokensResource {
967
+ private readonly client;
968
+ constructor(client: MonigoClient);
969
+ /**
970
+ * Generate a new portal link for a customer.
971
+ *
972
+ * **Requires `write` scope.**
973
+ *
974
+ * The returned `portal_url` is what you share with your customer — embed it
975
+ * in an email, open it in an iframe, or redirect the browser to it directly.
976
+ *
977
+ * @example
978
+ * ```ts
979
+ * const { portal_url } = await monigo.portalTokens.create({
980
+ * customer_external_id: 'usr_abc123',
981
+ * label: 'March 2026 invoice link',
982
+ * })
983
+ * await sendEmail(customer.email, { portalLink: portal_url })
984
+ * ```
985
+ */
986
+ create(request: CreatePortalTokenRequest, options?: MutationOptions): Promise<PortalToken>;
987
+ /**
988
+ * List all portal tokens for a customer.
989
+ *
990
+ * **Requires `read` scope.**
991
+ *
992
+ * @param customerId - The customer's Monigo UUID or their `external_id`.
993
+ */
994
+ list(customerId: string): Promise<ListPortalTokensResponse>;
995
+ /**
996
+ * Immediately revoke a portal token.
997
+ *
998
+ * **Requires `write` scope.**
999
+ *
1000
+ * Any customer holding the corresponding URL will receive a 401 on their
1001
+ * next request. This action is irreversible.
1002
+ *
1003
+ * @param tokenId - The UUID of the portal token record (not the raw token string).
1004
+ */
1005
+ revoke(tokenId: string, options?: MutationOptions): Promise<void>;
1006
+ }
1007
+
802
1008
  /** A pricing rule attached to a plan. */
803
1009
  export declare interface Price {
804
1010
  id: string;
@@ -1048,4 +1254,127 @@ export declare interface UsageRollup {
1048
1254
  updated_at: string;
1049
1255
  }
1050
1256
 
1257
+ /** A dedicated virtual bank account that funds a customer wallet. */
1258
+ export declare interface VirtualAccount {
1259
+ id: string;
1260
+ customer_id: string;
1261
+ wallet_id: string;
1262
+ org_id: string;
1263
+ /** Payment provider. Use `VirtualAccountProvider` constants. */
1264
+ provider: VirtualAccountProviderValue;
1265
+ account_number: string;
1266
+ account_name: string;
1267
+ bank_name: string;
1268
+ bank_code: string;
1269
+ currency: string;
1270
+ provider_ref: string;
1271
+ is_active: boolean;
1272
+ metadata: Record<string, unknown> | null;
1273
+ created_at: string;
1274
+ updated_at: string;
1275
+ }
1276
+
1277
+ export declare const VirtualAccountProvider: {
1278
+ readonly Paystack: "paystack";
1279
+ readonly Flutterwave: "flutterwave";
1280
+ readonly Monnify: "monnify";
1281
+ };
1282
+
1283
+ export declare type VirtualAccountProviderValue = (typeof VirtualAccountProvider)[keyof typeof VirtualAccountProvider];
1284
+
1285
+ export declare const WalletDirection: {
1286
+ /** Reduces the wallet balance. */
1287
+ readonly Debit: "debit";
1288
+ /** Increases the wallet balance. */
1289
+ readonly Credit: "credit";
1290
+ };
1291
+
1292
+ export declare type WalletDirectionValue = (typeof WalletDirection)[keyof typeof WalletDirection];
1293
+
1294
+ export declare const WalletEntryType: {
1295
+ /** Credit from an external funding source. */
1296
+ readonly Deposit: "deposit";
1297
+ /** Debit to an external destination. */
1298
+ readonly Withdrawal: "withdrawal";
1299
+ /** Automatic debit for metered usage charges. */
1300
+ readonly Usage: "usage";
1301
+ /** Credit reversing a previous charge. */
1302
+ readonly Refund: "refund";
1303
+ /** Manual balance correction. */
1304
+ readonly Adjustment: "adjustment";
1305
+ };
1306
+
1307
+ export declare type WalletEntryTypeValue = (typeof WalletEntryType)[keyof typeof WalletEntryType];
1308
+
1309
+ export declare interface WalletOperationResponse {
1310
+ wallet: CustomerWallet;
1311
+ ledger_entries: LedgerEntry[];
1312
+ }
1313
+
1314
+ /** Manage customer wallets, balance operations, and virtual accounts. */
1315
+ export declare class WalletsResource {
1316
+ private readonly client;
1317
+ constructor(client: MonigoClient);
1318
+ /**
1319
+ * Get an existing wallet or create a new one for the given customer and currency.
1320
+ *
1321
+ * **Requires `write` scope.**
1322
+ */
1323
+ getOrCreate(request: GetOrCreateWalletRequest, options?: MutationOptions): Promise<CustomerWallet>;
1324
+ /**
1325
+ * List all wallets for an organisation.
1326
+ *
1327
+ * **Requires `read` scope.**
1328
+ */
1329
+ list(params: ListWalletsParams): Promise<ListWalletsResponse>;
1330
+ /**
1331
+ * List all wallets belonging to a specific customer.
1332
+ *
1333
+ * **Requires `read` scope.**
1334
+ */
1335
+ listByCustomer(customerId: string): Promise<ListWalletsResponse>;
1336
+ /**
1337
+ * Fetch a single wallet by UUID, including its virtual accounts.
1338
+ *
1339
+ * **Requires `read` scope.**
1340
+ */
1341
+ get(walletId: string): Promise<WalletWithVirtualAccountsResponse>;
1342
+ /**
1343
+ * Credit (add funds to) a wallet. Returns the updated wallet and ledger entries.
1344
+ *
1345
+ * **Requires `write` scope.**
1346
+ */
1347
+ credit(walletId: string, request: CreditWalletRequest, options?: MutationOptions): Promise<WalletOperationResponse>;
1348
+ /**
1349
+ * Debit (remove funds from) a wallet. Returns the updated wallet and ledger entries.
1350
+ * Throws a 402 error if the wallet has insufficient balance.
1351
+ *
1352
+ * **Requires `write` scope.**
1353
+ */
1354
+ debit(walletId: string, request: DebitWalletRequest, options?: MutationOptions): Promise<WalletOperationResponse>;
1355
+ /**
1356
+ * List paginated ledger entries (transactions) for a wallet.
1357
+ *
1358
+ * **Requires `read` scope.**
1359
+ */
1360
+ listTransactions(walletId: string, params?: ListTransactionsParams): Promise<ListTransactionsResponse>;
1361
+ /**
1362
+ * Create a dedicated virtual bank account that automatically funds the wallet on deposit.
1363
+ *
1364
+ * **Requires `write` scope.**
1365
+ */
1366
+ createVirtualAccount(walletId: string, request: CreateVirtualAccountRequest, options?: MutationOptions): Promise<VirtualAccount>;
1367
+ /**
1368
+ * List all virtual accounts linked to a wallet.
1369
+ *
1370
+ * **Requires `read` scope.**
1371
+ */
1372
+ listVirtualAccounts(walletId: string): Promise<ListVirtualAccountsResponse>;
1373
+ }
1374
+
1375
+ export declare interface WalletWithVirtualAccountsResponse {
1376
+ wallet: CustomerWallet;
1377
+ virtual_accounts: VirtualAccount[];
1378
+ }
1379
+
1051
1380
  export { }
package/dist/monigo.cjs CHANGED
@@ -663,6 +663,183 @@ class UsageResource {
663
663
  return this.client._request("GET", "/v1/usage", { query });
664
664
  }
665
665
  }
666
+ class PortalTokensResource {
667
+ constructor(client) {
668
+ this.client = client;
669
+ }
670
+ /**
671
+ * Generate a new portal link for a customer.
672
+ *
673
+ * **Requires `write` scope.**
674
+ *
675
+ * The returned `portal_url` is what you share with your customer — embed it
676
+ * in an email, open it in an iframe, or redirect the browser to it directly.
677
+ *
678
+ * @example
679
+ * ```ts
680
+ * const { portal_url } = await monigo.portalTokens.create({
681
+ * customer_external_id: 'usr_abc123',
682
+ * label: 'March 2026 invoice link',
683
+ * })
684
+ * await sendEmail(customer.email, { portalLink: portal_url })
685
+ * ```
686
+ */
687
+ async create(request, options) {
688
+ const wrapper = await this.client._request(
689
+ "POST",
690
+ "/v1/portal/tokens",
691
+ { body: request, idempotencyKey: options?.idempotencyKey }
692
+ );
693
+ return wrapper.token;
694
+ }
695
+ /**
696
+ * List all portal tokens for a customer.
697
+ *
698
+ * **Requires `read` scope.**
699
+ *
700
+ * @param customerId - The customer's Monigo UUID or their `external_id`.
701
+ */
702
+ async list(customerId) {
703
+ return this.client._request(
704
+ "GET",
705
+ "/v1/portal/tokens",
706
+ { query: { customer_id: customerId } }
707
+ );
708
+ }
709
+ /**
710
+ * Immediately revoke a portal token.
711
+ *
712
+ * **Requires `write` scope.**
713
+ *
714
+ * Any customer holding the corresponding URL will receive a 401 on their
715
+ * next request. This action is irreversible.
716
+ *
717
+ * @param tokenId - The UUID of the portal token record (not the raw token string).
718
+ */
719
+ async revoke(tokenId, options) {
720
+ await this.client._request(
721
+ "DELETE",
722
+ `/v1/portal/tokens/${tokenId}`,
723
+ { idempotencyKey: options?.idempotencyKey }
724
+ );
725
+ }
726
+ }
727
+ class WalletsResource {
728
+ constructor(client) {
729
+ this.client = client;
730
+ }
731
+ /**
732
+ * Get an existing wallet or create a new one for the given customer and currency.
733
+ *
734
+ * **Requires `write` scope.**
735
+ */
736
+ async getOrCreate(request, options) {
737
+ const wrapper = await this.client._request(
738
+ "POST",
739
+ "/v1/wallets",
740
+ { body: request, idempotencyKey: options?.idempotencyKey }
741
+ );
742
+ return wrapper.wallet;
743
+ }
744
+ /**
745
+ * List all wallets for an organisation.
746
+ *
747
+ * **Requires `read` scope.**
748
+ */
749
+ async list(params) {
750
+ return this.client._request("GET", "/v1/wallets", {
751
+ query: { org_id: params.org_id }
752
+ });
753
+ }
754
+ /**
755
+ * List all wallets belonging to a specific customer.
756
+ *
757
+ * **Requires `read` scope.**
758
+ */
759
+ async listByCustomer(customerId) {
760
+ return this.client._request(
761
+ "GET",
762
+ `/v1/customers/${customerId}/wallets`
763
+ );
764
+ }
765
+ /**
766
+ * Fetch a single wallet by UUID, including its virtual accounts.
767
+ *
768
+ * **Requires `read` scope.**
769
+ */
770
+ async get(walletId) {
771
+ return this.client._request(
772
+ "GET",
773
+ `/v1/wallets/${walletId}`
774
+ );
775
+ }
776
+ /**
777
+ * Credit (add funds to) a wallet. Returns the updated wallet and ledger entries.
778
+ *
779
+ * **Requires `write` scope.**
780
+ */
781
+ async credit(walletId, request, options) {
782
+ return this.client._request(
783
+ "POST",
784
+ `/v1/wallets/${walletId}/credit`,
785
+ { body: request, idempotencyKey: options?.idempotencyKey }
786
+ );
787
+ }
788
+ /**
789
+ * Debit (remove funds from) a wallet. Returns the updated wallet and ledger entries.
790
+ * Throws a 402 error if the wallet has insufficient balance.
791
+ *
792
+ * **Requires `write` scope.**
793
+ */
794
+ async debit(walletId, request, options) {
795
+ return this.client._request(
796
+ "POST",
797
+ `/v1/wallets/${walletId}/debit`,
798
+ { body: request, idempotencyKey: options?.idempotencyKey }
799
+ );
800
+ }
801
+ /**
802
+ * List paginated ledger entries (transactions) for a wallet.
803
+ *
804
+ * **Requires `read` scope.**
805
+ */
806
+ async listTransactions(walletId, params) {
807
+ return this.client._request(
808
+ "GET",
809
+ `/v1/wallets/${walletId}/transactions`,
810
+ {
811
+ query: {
812
+ limit: params?.limit?.toString(),
813
+ offset: params?.offset?.toString()
814
+ }
815
+ }
816
+ );
817
+ }
818
+ /**
819
+ * Create a dedicated virtual bank account that automatically funds the wallet on deposit.
820
+ *
821
+ * **Requires `write` scope.**
822
+ */
823
+ async createVirtualAccount(walletId, request, options) {
824
+ const wrapper = await this.client._request(
825
+ "POST",
826
+ `/v1/wallets/${walletId}/virtual-accounts`,
827
+ { body: request, idempotencyKey: options?.idempotencyKey }
828
+ );
829
+ return wrapper.virtual_account;
830
+ }
831
+ /**
832
+ * List all virtual accounts linked to a wallet.
833
+ *
834
+ * **Requires `read` scope.**
835
+ */
836
+ async listVirtualAccounts(walletId) {
837
+ return this.client._request(
838
+ "GET",
839
+ `/v1/wallets/${walletId}/virtual-accounts`
840
+ );
841
+ }
842
+ }
666
843
  const DEFAULT_BASE_URL = "https://api.monigo.co";
667
844
  const DEFAULT_TIMEOUT_MS = 3e4;
668
845
  class MonigoClient {
@@ -688,6 +865,8 @@ class MonigoClient {
688
865
  this.payoutAccounts = new PayoutAccountsResource(this);
689
866
  this.invoices = new InvoicesResource(this);
690
867
  this.usage = new UsageResource(this);
868
+ this.portalTokens = new PortalTokensResource(this);
869
+ this.wallets = new WalletsResource(this);
691
870
  }
692
871
  /**
693
872
  * Execute an authenticated HTTP request against the Monigo API.
@@ -801,6 +980,29 @@ const PayoutMethod = {
801
980
  BankTransfer: "bank_transfer",
802
981
  MobileMoney: "mobile_money"
803
982
  };
983
+ const WalletEntryType = {
984
+ /** Credit from an external funding source. */
985
+ Deposit: "deposit",
986
+ /** Debit to an external destination. */
987
+ Withdrawal: "withdrawal",
988
+ /** Automatic debit for metered usage charges. */
989
+ Usage: "usage",
990
+ /** Credit reversing a previous charge. */
991
+ Refund: "refund",
992
+ /** Manual balance correction. */
993
+ Adjustment: "adjustment"
994
+ };
995
+ const WalletDirection = {
996
+ /** Reduces the wallet balance. */
997
+ Debit: "debit",
998
+ /** Increases the wallet balance. */
999
+ Credit: "credit"
1000
+ };
1001
+ const VirtualAccountProvider = {
1002
+ Paystack: "paystack",
1003
+ Flutterwave: "flutterwave",
1004
+ Monnify: "monnify"
1005
+ };
804
1006
  exports.Aggregation = Aggregation;
805
1007
  exports.BillingPeriod = BillingPeriod;
806
1008
  exports.CustomersResource = CustomersResource;
@@ -814,8 +1016,13 @@ exports.PayoutAccountsResource = PayoutAccountsResource;
814
1016
  exports.PayoutMethod = PayoutMethod;
815
1017
  exports.PlanType = PlanType;
816
1018
  exports.PlansResource = PlansResource;
1019
+ exports.PortalTokensResource = PortalTokensResource;
817
1020
  exports.PricingModel = PricingModel;
818
1021
  exports.SubscriptionStatus = SubscriptionStatus;
819
1022
  exports.SubscriptionsResource = SubscriptionsResource;
820
1023
  exports.UsageResource = UsageResource;
1024
+ exports.VirtualAccountProvider = VirtualAccountProvider;
1025
+ exports.WalletDirection = WalletDirection;
1026
+ exports.WalletEntryType = WalletEntryType;
1027
+ exports.WalletsResource = WalletsResource;
821
1028
  //# sourceMappingURL=monigo.cjs.map