@go-labs-sg/bb 1.13.0 → 1.14.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
@@ -63,8 +63,9 @@ Global options and flags use `--key=value` or `--key value` (see `bb help`).
63
63
  | Area | Commands (non-exhaustive) |
64
64
  | --- | --- |
65
65
  | **Budgets** | `list-budgets` (full payload by default; `--summary` or `--includeDetails false` for slim list), `get-budget`, `get-budget-items`, `get-budget-details`, `get-budget-categories`, `get-budget-versions`, `update-budget-status` (`ESTIMATE_ACCEPTED` requires win proof, auto-marks `PITCH` or `LOST` projects `WON`, and auto-creates Asana project/section/tasks when enabled; `--projectStatusOnCommercialRejection PITCH\|LOST` is required when rejecting the only accepted/closed budget on a commercial project), `mark-budget-won` (`<budgetId>` + proof file path; `PITCH` or `LOST` projects become `WON` automatically), `create-budget` / `update-budget` (`--payload`), `delete-budget`, `create-budget-approval` (also sends approval request emails), `add-budget-items`, `update-budget-item`, `remove-budget-item`, `reorder-budget-items`, `update-budget-item-supplier`, `create-budget-category`, `update-budget-category`, `delete-budget-category`, `update-budget-commission`, `update-budget-discount` (`--payload` where noted), `upload-budget-attachment` (`<budgetId>` + local file path; uses `attachment.requestBudgetAttachmentUpload` + PUT + `attachment.confirmBudgetAttachment`) |
66
- | **Bills / claims** | `list-bills` (`--isClaimable false` for bills, `--isClaimable true` for claims, omit for both), `list-claims` (claims only), `create-bill` (`--payload`; set `isClaimable=false` for a bill or `isClaimable=true` for a claim), `update-bill` (`--payload`), `delete-bill`, `create-bill-approval` (also sends approval request emails), `update-bill-status`, `patch-bill-payment` (PAID bills: `--paymentTrackingUrl`, `--paymentReference`, `--quickbooksBillId`, `--paymentDate` ISO; clear with `--clearPaymentTrackingUrl` / `--clearPaymentReference` / `--clearQuickbooksBillId` / `--clearPaymentDate` `true`), `patch-bill-invoice-number`, `get-bill-attachments`, `upload-bill-attachment` (`<billId>` + local path), `get-bill-details` |
67
- | **Approvals** | `list-approvals` / `get-pending-approvals`, `approve-bill` / `reject-bill` (send reply email), `approve-budget` / `reject-budget` (send reply email), `approve-supplier` / `reject-supplier` (send reply email) |
66
+ | **Bills / claims** | `list-bills` (`--isClaimable false` for bills, `--isClaimable true` for claims, omit for both), `list-claims` (claims only), `create-bill` (`--payload`; set `isClaimable=false` for a bill or `isClaimable=true` for a claim; non-legacy supplier bills from 1 Jul 2026 00:00 SGT require approved quotation coverage), `update-bill` (`--payload`), `delete-bill`, `create-bill-approval` (also sends approval request emails), `update-bill-status`, `patch-bill-payment` (PAID bills: `--paymentTrackingUrl`, `--paymentReference`, `--quickbooksBillId`, `--paymentDate` ISO; clear with `--clearPaymentTrackingUrl` / `--clearPaymentReference` / `--clearQuickbooksBillId` / `--clearPaymentDate` `true`), `patch-bill-invoice-number`, `get-bill-attachments`, `upload-bill-attachment` (`<billId>` + local path), `get-bill-details` |
67
+ | **Quotations** | `list-quotations`, `get-quotation`, `upload-quotation-attachment` (`<projectId>` + local PDF path; returns attachment JSON for payload use), `create-quotation` (`--payload` for `quotation.createDraft`), `submit-quotation`, `approve-quotation`, `reject-quotation`, `download-quotation-pdf` (`original`, `staff`, or `final`) |
68
+ | **Approvals** | `list-approvals` / `get-pending-approvals` (`--type budget\|supplier\|bill\|quotation\|all`), `approve-bill` / `reject-bill` (send reply email), `approve-budget` / `reject-budget` (send reply email), `approve-supplier` / `reject-supplier` (send reply email), `approve-quotation` / `reject-quotation` |
68
69
  | **Companies & projects** | `list-companies`, `get-company`, `create-company`, `update-company` (`--payload`), `delete-company`, `list-projects`, `get-project`, `create-project` (required: `--name`, `--companyId`, `--contactPersonId`, `--insideSalesId`, `--businessDevelopmentId`, `--venue`, `--asanaTaskId`, `--slackChannelId`, `--slackChannelUrl`, `--slackChannelName`, `--startDate` as ISO datetime for project/window start; optional `--pax`; optional `--endDate`; optional `--description`; optional `--requestQboAccountantNotification false` to skip QBO accountant emails), `update-project` (`--payload` with `dateRange.from` / `dateRange.to` for the project window; optional `requestQboAccountantNotification` in JSON), `delete-project`, `update-project-status` (`<id>` `<status>`: `PITCH` \| `WON` \| `COMPLETED` \| `LOST`; for `PITCH` → `WON` also pass `--projectManagerId` or `--projectManagerName`; when marking `WON` without an accepted/closed budget or proof, pass `--wonOverrideReason`) |
69
70
  | **Contacts** | `list-contacts`, `create-contact-person` (`--payload`), `update-contact-person` (`--payload`) |
70
71
  | **Suppliers & items** | `list-suppliers` (defaults to active suppliers, `--perPage 10`, sorted by `createdAt` desc; supports `--name`, `--sortBy` for scalar supplier fields, `--sortDir`, `--createdBy`, `--gstRegistered`, `--status`, `--supplierTags`, `--active false` for archived suppliers), `create-supplier` (`--payload`; when supplier status is `PENDING_APPROVAL`, also runs `supplier.createSupplierApproval` and `email.sendSupplierApprovalRequestEmail`), `update-supplier` (`--payload`; when supplier status is `PENDING_APPROVAL`, also runs `supplier.createSupplierApproval` and `email.sendSupplierApprovalRequestEmail`), `delete-suppliers` (`--ids` CSV; admin; archives/deactivates related items), `reactivate-suppliers` (`--ids` CSV; admin; reactivates related items), `create-certification` / `create-payment-method` / `create-supplier-role` / `create-supplier-tag` (`--name`), `get-supplier-details` (includes `supplierApprovalSummary` for pending approvers, superseded approvers, and the actual responder/respondedAt metadata), `get-supplier-analytics`, `list-items`, `create-item` (`--payload`), `update-item` (`--payload`), `delete-item`, `get-item`, `list-item-categories`, `create-item-category`, `update-item-category`, `delete-item-categories` (`--ids` CSV; admin) |
package/dist/commands.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import { readFile } from "node:fs/promises";
2
3
  import { basename } from "node:path";
3
4
  import { contentType } from "mime-types";
@@ -9,6 +10,7 @@ import { createRichTextFromPlainText } from "./rich-text.js";
9
10
  const BUDGET = "BUDGET";
10
11
  const BILL = "BILL";
11
12
  const SUPPLIER = "SUPPLIER";
13
+ const QUOTATION = "QUOTATION";
12
14
  function isPendingRequest(n) {
13
15
  return n.notificationType === "request" && n.status === "PENDING_APPROVAL";
14
16
  }
@@ -199,6 +201,10 @@ export async function listApprovals(opts) {
199
201
  id = n.supplier.id;
200
202
  name = n.supplier.name;
201
203
  }
204
+ else if (n.type === QUOTATION && n.supplierQuotation) {
205
+ id = n.supplierQuotation.id;
206
+ name = `Quotation ${n.supplierQuotation.supplier.name}`;
207
+ }
202
208
  else {
203
209
  id = n.id;
204
210
  name = "Unknown";
@@ -323,6 +329,33 @@ export async function uploadBillAttachmentFromPath(billId, filePath) {
323
329
  });
324
330
  out(confirmed);
325
331
  }
332
+ export async function uploadQuotationAttachmentFromPath(projectId, filePath) {
333
+ const buf = await readFile(filePath);
334
+ const fileName = basename(filePath);
335
+ const ext = fileName
336
+ .split(".")
337
+ .pop()
338
+ ?.toLowerCase()
339
+ .replace(/[^a-z0-9]/g, "");
340
+ const key = `quotations/${projectId}/${randomUUID()}.${ext || "pdf"}`;
341
+ const uploadUrl = await api.attachment.getPresignedUrlToUpload.mutate({
342
+ key,
343
+ });
344
+ const res = await fetch(uploadUrl, {
345
+ method: "PUT",
346
+ body: buf,
347
+ headers: { "Content-Type": contentTypeHeaderForFileName(fileName) },
348
+ });
349
+ if (!res.ok) {
350
+ throw new Error(`S3 upload failed: HTTP ${res.status} ${(await res.text()).slice(0, 500)}`);
351
+ }
352
+ out({
353
+ id: randomUUID(),
354
+ name: fileName,
355
+ key,
356
+ size: buf.byteLength,
357
+ });
358
+ }
326
359
  export async function uploadBudgetAttachmentFromPath(budgetId, filePath) {
327
360
  const buf = await readFile(filePath);
328
361
  const fileName = basename(filePath);
@@ -568,6 +601,29 @@ export async function createBillFromPayload(raw) {
568
601
  const result = await api.bill.create.mutate(input);
569
602
  out(result);
570
603
  }
604
+ export async function listQuotations(opts) {
605
+ const result = await api.quotation.list.query(opts);
606
+ out(result);
607
+ }
608
+ export async function getQuotationDetails(id) {
609
+ const result = await api.quotation.getById.query({ id });
610
+ out(result);
611
+ }
612
+ export async function createQuotationFromPayload(raw) {
613
+ const result = await api.quotation.createDraft.mutate(raw);
614
+ out(result);
615
+ }
616
+ export async function submitQuotation(id) {
617
+ const result = await api.quotation.submitForApproval.mutate({ id });
618
+ out(result);
619
+ }
620
+ export async function downloadQuotationPdf(id, fileRole) {
621
+ const result = await api.quotation.getSignedDownloadUrl.query({
622
+ id,
623
+ fileRole,
624
+ });
625
+ out(result);
626
+ }
571
627
  export async function updateBillFromPayload(raw) {
572
628
  const input = parseUpdateBillPayload(raw);
573
629
  const result = await api.bill.update.mutate(input);
@@ -924,6 +980,37 @@ export async function rejectBill(billId, reason) {
924
980
  email,
925
981
  });
926
982
  }
983
+ export async function approveQuotation(quotationId) {
984
+ const notifications = await api.budget.getNotifications.query();
985
+ const pending = notifications.filter((n) => isPendingRequest(n) &&
986
+ n.type === QUOTATION &&
987
+ (n.supplierQuotationId === quotationId ||
988
+ n.supplierQuotation?.id === quotationId));
989
+ const approval = pending[0];
990
+ if (!approval) {
991
+ throw new Error("No pending quotation approval found.");
992
+ }
993
+ const result = await api.quotation.approve.mutate({
994
+ quotationApprovalId: approval.id,
995
+ });
996
+ out(result);
997
+ }
998
+ export async function rejectQuotation(quotationId, reason) {
999
+ const notifications = await api.budget.getNotifications.query();
1000
+ const pending = notifications.filter((n) => isPendingRequest(n) &&
1001
+ n.type === QUOTATION &&
1002
+ (n.supplierQuotationId === quotationId ||
1003
+ n.supplierQuotation?.id === quotationId));
1004
+ const approval = pending[0];
1005
+ if (!approval) {
1006
+ throw new Error("No pending quotation approval found.");
1007
+ }
1008
+ const result = await api.quotation.reject.mutate({
1009
+ quotationApprovalId: approval.id,
1010
+ rejectionReason: reason,
1011
+ });
1012
+ out(result);
1013
+ }
927
1014
  // --- Companies & projects ---
928
1015
  export async function listCompanies(opts) {
929
1016
  const result = await api.company.getCompanies.query({
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import "./load-env.js";
3
3
  import { requireApiKey } from "./api-client.js";
4
4
  import { consumeCliQuietFlags, logCliAction, sanitizeFlagsForTrace, setCliQuiet, shouldLogCliActions, } from "./cli-trace.js";
5
- import { addBudgetItems, approveBill, approveBudget, approveSupplier, createBillApproval, createBillFromPayload, createBudgetApproval, createBudgetCategory, createBudgetFromPayload, createCompany, createContactPersonFromPayload, createEstimate, createItemCategory, createItemFromPayload, createProject, createSupplierCertification, createSupplierFromPayload, createSupplierPaymentMethod, createSupplierRoleOption, createSupplierTagOption, deleteBillById, deleteBudgetById, deleteBudgetCategory, deleteCompanyById, deleteItemById, deleteItemCategoriesByIds, deleteProjectById, deleteSuppliersByIds, getApprovedBudgets, getBillAttachments, getBillDetails, getBudget, getBudgetCategories, getBudgetCategoryBenchmarks, getBudgetDetails, getBudgetItemsOnly, getBudgetVersions, getCompany, getDashboard, getErrorMetrics, getEstimatePerformance, getFinancialOverview, getItem, getItemPricingHistory, getMonthlyMetrics, getProject, getRecentErrors, getSupplierAnalytics, getSupplierDetails, getSupplierPricingHistory, getSystemOverview, getUserPerformance, listApprovals, listBills, listBudgets, listCompanies, listContacts, listItemCategories, listItems, listProjects, listSuppliers, listUsers, markBudgetWonWithProof, patchBillInvoiceNumber, patchBillPayment, reactivateSuppliersByIds, rejectBill, rejectBudget, rejectSupplier, removeBudgetItem, reorderBudgetItemsCli, updateBillFromPayload, updateBillStatus, updateBudgetCategory, updateBudgetCommissionFromPayload, updateBudgetDiscountFromPayload, updateBudgetFromPayload, updateBudgetItem, updateBudgetItemSupplierCli, updateBudgetStatus, updateCompanyFromPayload, updateContactPersonFromPayload, updateItemCategory, updateItemFromPayload, updateProjectFromPayload, updateProjectStatus, updateSupplierFromPayload, uploadBillAttachmentFromPath, uploadBudgetAttachmentFromPath, } from "./commands.js";
5
+ import { addBudgetItems, approveBill, approveBudget, approveQuotation, approveSupplier, createBillApproval, createBillFromPayload, createBudgetApproval, createBudgetCategory, createBudgetFromPayload, createCompany, createContactPersonFromPayload, createEstimate, createItemCategory, createItemFromPayload, createProject, createQuotationFromPayload, createSupplierCertification, createSupplierFromPayload, createSupplierPaymentMethod, createSupplierRoleOption, createSupplierTagOption, deleteBillById, deleteBudgetById, deleteBudgetCategory, deleteCompanyById, deleteItemById, deleteItemCategoriesByIds, deleteProjectById, deleteSuppliersByIds, downloadQuotationPdf, getApprovedBudgets, getBillAttachments, getBillDetails, getBudget, getBudgetCategories, getBudgetCategoryBenchmarks, getBudgetDetails, getBudgetItemsOnly, getBudgetVersions, getCompany, getDashboard, getErrorMetrics, getEstimatePerformance, getFinancialOverview, getItem, getItemPricingHistory, getMonthlyMetrics, getProject, getQuotationDetails, getRecentErrors, getSupplierAnalytics, getSupplierDetails, getSupplierPricingHistory, getSystemOverview, getUserPerformance, listApprovals, listBills, listBudgets, listCompanies, listContacts, listItemCategories, listItems, listProjects, listQuotations, listSuppliers, listUsers, markBudgetWonWithProof, patchBillInvoiceNumber, patchBillPayment, reactivateSuppliersByIds, rejectBill, rejectBudget, rejectQuotation, rejectSupplier, removeBudgetItem, reorderBudgetItemsCli, submitQuotation, updateBillFromPayload, updateBillStatus, updateBudgetCategory, updateBudgetCommissionFromPayload, updateBudgetDiscountFromPayload, updateBudgetFromPayload, updateBudgetItem, updateBudgetItemSupplierCli, updateBudgetStatus, updateCompanyFromPayload, updateContactPersonFromPayload, updateItemCategory, updateItemFromPayload, updateProjectFromPayload, updateProjectStatus, updateSupplierFromPayload, uploadBillAttachmentFromPath, uploadBudgetAttachmentFromPath, uploadQuotationAttachmentFromPath, } from "./commands.js";
6
6
  import { getFlag, parseArgs } from "./parse-args.js";
7
7
  import { billStatusesForUpdateHelp, budgetStatusesForHelp, isBudgetStatusUpdate, parseApprovalTypeFlag, parseBillStatusForUpdate, parseCommaSeparatedBillStatuses, parseCommaSeparatedBudgetStatuses, parseCommaSeparatedIds, parseCommaSeparatedSupplierStatuses, parseOptionalBillListSortBy, parseOptionalBillListSortDir, parseOptionalDashboardRole, parseOptionalDeals, parseOptionalErrorSeverity, parseOptionalErrorStatus, parseOptionalExtendedProjectStatus, parseOptionalFinancialRole, parseOptionalSupplierAnalyticsTimeFrame, parseOptionalTimeFrame, parseProjectStatusForUpdate, projectStatusesForHelp, } from "./parse-cli-enums.js";
8
8
  import { parseJsonFlag, parseOptionalNumber as parseOptNum, } from "./parse-json-flag.js";
@@ -152,6 +152,7 @@ Bills
152
152
  list-bills [--projectId] [--budgetId] [--status CSV] [--search <text>] [--isClaimable true|false] [--createdByIds <csv>] [--sortBy createdAt|amount|status] [--sortDir asc|desc] [--page] [--pageSize]
153
153
  list-claims same flags as list-bills; only reimbursable claims (ignores --isClaimable)
154
154
  isClaimable differentiates the shared bill/claim records: false = bill, true = claim.
155
+ New supplier bills from 1 Jul 2026 00:00 SGT require approved quotation coverage for each non-legacy line item.
155
156
  create-bill-approval <billId> (also sends approval request emails)
156
157
  create-bill --payload '<json>' (bill.create; payload.isClaimable false = bill, true = claim; use upload-bill-attachment after create to add files)
157
158
  update-bill --payload '<json>' (bill.update; must include id)
@@ -165,8 +166,18 @@ Bills
165
166
  upload-bill-attachment <billId> <filePath> Presigned S3 upload + confirm (same flow as web UI)
166
167
  get-bill-details <billId>
167
168
 
169
+ Quotations
170
+ list-quotations [--projectId] [--budgetId] [--supplierId] [--status CSV] [--page] [--pageSize]
171
+ get-quotation <quotationId>
172
+ upload-quotation-attachment <projectId> <filePath> Presigned S3 upload; returns attachment JSON for create-quotation payload
173
+ create-quotation --payload '<json>' (quotation.createDraft)
174
+ submit-quotation <quotationId>
175
+ approve-quotation <quotationId>
176
+ reject-quotation <quotationId> --reason <text>
177
+ download-quotation-pdf <quotationId> [original|staff|final]
178
+
168
179
  Approvals
169
- list-approvals | get-pending-approvals [--type budget|supplier|bill|all]
180
+ list-approvals | get-pending-approvals [--type budget|supplier|bill|quotation|all]
170
181
  approve-bill <billId> (also sends requester reply email)
171
182
  reject-bill <billId> --reason <text> (also sends requester reply email)
172
183
  approve-budget <budgetId> (also sends requester reply email)
@@ -674,6 +685,88 @@ async function main() {
674
685
  await getBillDetails(id);
675
686
  break;
676
687
  }
688
+ case "list-quotations": {
689
+ const statusRaw = getFlag(flags, "status");
690
+ await listQuotations({
691
+ projectId: getFlag(flags, "projectId"),
692
+ budgetId: getFlag(flags, "budgetId"),
693
+ supplierId: getFlag(flags, "supplierId"),
694
+ status: statusRaw !== undefined
695
+ ? String(statusRaw)
696
+ .split(",")
697
+ .map((value) => value.trim().toUpperCase())
698
+ .filter(Boolean)
699
+ : undefined,
700
+ page: getFlag(flags, "page") !== undefined
701
+ ? Number(getFlag(flags, "page"))
702
+ : undefined,
703
+ pageSize: getFlag(flags, "pageSize") !== undefined
704
+ ? Number(getFlag(flags, "pageSize"))
705
+ : undefined,
706
+ });
707
+ break;
708
+ }
709
+ case "get-quotation": {
710
+ const id = positional[0];
711
+ if (!id)
712
+ throw new Error("get-quotation requires <quotationId>");
713
+ await getQuotationDetails(id);
714
+ break;
715
+ }
716
+ case "upload-quotation-attachment": {
717
+ const [projectId, filePath] = positional;
718
+ if (!projectId || !filePath) {
719
+ throw new Error("upload-quotation-attachment requires <projectId> <filePath>");
720
+ }
721
+ await uploadQuotationAttachmentFromPath(projectId, filePath);
722
+ break;
723
+ }
724
+ case "create-quotation": {
725
+ const payloadRaw = getFlag(flags, "payload");
726
+ if (!payloadRaw) {
727
+ throw new Error("create-quotation requires --payload '<json>'");
728
+ }
729
+ const raw = parseJsonFlag(String(payloadRaw), "--payload");
730
+ await createQuotationFromPayload(raw);
731
+ break;
732
+ }
733
+ case "submit-quotation": {
734
+ const id = positional[0];
735
+ if (!id)
736
+ throw new Error("submit-quotation requires <quotationId>");
737
+ await submitQuotation(id);
738
+ break;
739
+ }
740
+ case "approve-quotation": {
741
+ const id = positional[0];
742
+ if (!id)
743
+ throw new Error("approve-quotation requires <quotationId>");
744
+ await approveQuotation(id);
745
+ break;
746
+ }
747
+ case "reject-quotation": {
748
+ const id = positional[0];
749
+ const reason = getFlag(flags, "reason");
750
+ if (!id || reason === undefined) {
751
+ throw new Error("reject-quotation requires <quotationId> --reason <text>");
752
+ }
753
+ await rejectQuotation(id, reason);
754
+ break;
755
+ }
756
+ case "download-quotation-pdf": {
757
+ const id = positional[0];
758
+ if (!id) {
759
+ throw new Error("download-quotation-pdf requires <quotationId> [original|staff|final]");
760
+ }
761
+ const roleRaw = (positional[1] ?? "final").toLowerCase();
762
+ const fileRole = roleRaw === "original"
763
+ ? "ORIGINAL"
764
+ : roleRaw === "staff"
765
+ ? "STAFF_SIGNED"
766
+ : "FINAL_SIGNED";
767
+ await downloadQuotationPdf(id, fileRole);
768
+ break;
769
+ }
677
770
  case "list-approvals":
678
771
  case "get-pending-approvals": {
679
772
  const typeRaw = getFlag(flags, "type");
@@ -215,7 +215,7 @@ export function parseOptionalBillListSortDir(raw) {
215
215
  return raw;
216
216
  }
217
217
  function isPendingRequestType(s) {
218
- return s === "BUDGET" || s === "BILL" || s === "SUPPLIER";
218
+ return (s === "BUDGET" || s === "BILL" || s === "SUPPLIER" || s === "QUOTATION");
219
219
  }
220
220
  export function parseApprovalTypeFlag(raw) {
221
221
  if (raw === undefined)
@@ -224,7 +224,7 @@ export function parseApprovalTypeFlag(raw) {
224
224
  if (u === "ALL")
225
225
  return "ALL";
226
226
  if (!isPendingRequestType(u)) {
227
- throw new Error(`Invalid --type "${raw}". Use budget, supplier, bill, or all.`);
227
+ throw new Error(`Invalid --type "${raw}". Use budget, supplier, bill, quotation, or all.`);
228
228
  }
229
229
  return u;
230
230
  }
@@ -33,6 +33,8 @@ export const ApprovalType = {
33
33
  BUDGET: "BUDGET",
34
34
  SUPPLIER: "SUPPLIER",
35
35
  BILL: "BILL",
36
+ CUSTOMER_INVOICE: "CUSTOMER_INVOICE",
37
+ QUOTATION: "QUOTATION",
36
38
  };
37
39
  export const ErrorSeverity = {
38
40
  LOW: "LOW",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/bb",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Budget Builder CLI for AI agents — manage budgets, bills, and claims; bill records use isClaimable=false for bills and isClaimable=true for claims.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",