@apigrate/quickbooks

中文文档
4.6.0发布于 2026/03/03Apache-2.0CommonJS近 30 天下载 2175

Intuit快取快取API的节点JS API连接器.

中文使用文档
文档目录14 节
  1. 版本4.x 变动
  2. 支助的实体
  3. 使用量
  4. 制作API电话
  5. 查询
  6. 获取身份
  7. 创建
  8. 更新
  9. 删除
  10. 虚拟
  11. 批量请求
  12. 运行报表
  13. 处理错误
  14. OAuth 获得 IntuitAuthorization Url = 函数(状态)

@apigrate/快书

透明 单站 用于与快书在线API互动的库。 它支持您需要与快书在线会计API互动的所有功能,包括:

  1. 自动 OAuth2 令牌刷新(包括事件处理器)
  2. 支持本土承诺
  3. 未显示的错误处理
  4. 构造器 OAuth URL 的方便方法
  5. 最重要的是, quickBooks 在线会计 API 的完整覆盖。 。 。 .

版本4.x 变动

现在使用Intuit发现文档,动态地从Intuit OAuth上加载正确的URL.

变化 :

  • 已添加 is_sandbox 布尔到构造器。 使用此选项来指定沙盒 vs 生产环境 .
  • 已添加 intuit_tid 将返回 accountingApi()。这个包含最后一个 API 调用 intuit_tid 值,用于开发者支持排除出错.
  • intuit_tid 属性添加到 ApiErrors 和 ApiThrotlingErrors .
  • 为某些实体增加了虚拟支持。 你可以使用一个 .voidTransaction() 发票、账单、付款和销售交易业务

中断更改 :

  • getIntuitAuthorizationUrl 函数现在是连接器实例上的一种同步方法.

支助的实体

支持的交易实体:

实体查询创建由 id 获取更新删除无效
比尔✓✓✓✓✓
账单付款✓✓✓✓✓✓
信用备忘录✓✓✓✓✓
交存✓✓✓✓✓
估计数✓✓✓✓✓
发票✓✓✓✓✓✓
日记条目✓✓✓✓✓
付款✓✓✓✓✓✓
采购✓✓✓✓✓
定购单✓✓✓✓✓
退款收回✓✓✓✓✓
销售检索✓✓✓✓✓✓
时间活性✓✓✓✓✓
转让✓✓✓✓✓
供应商编辑✓✓✓✓✓

已命名的列表实体 :

实体参考文献查询创建由 id 获取更新删除
账户账户✓✓✓✓ 
预算预算✓ ✓  
类类✓✓✓✓ 
公司数量公司货币✓✓✓✓ 
客户客户✓✓✓✓ 
部门部门✓✓✓✓ 
雇员雇员✓✓✓✓ 
项目项目✓✓✓✓ 
日记码日记代码✓✓✓✓ 
支付方法付款方法✓✓✓✓ 
税务机构税务机构✓✓✓  
税则税码✓✓✓  
税收税率✓✓✓  
税务服务税务/税法✓✓   
任期任期✓✓✓✓ 
供应商供应商✓✓✓✓ 

支助实体:

实体参考文献查询创建由 id 获取更新删除
可附加可附加✓✓✓✓✓
公司信息公司信息✓ ✓✓ 
首选项偏好✓ ✓✓ 

报告:

报告
账户列表详细报告
APAGING 详细报告
APAGING 简要报告
详细报告
ARAGING 简要报告
平衡面板报告
现金
客户报告
客户详细报告
客户收入报告
一般编辑报告
通用编目报告FR
库存估价 摘要报告
《日刊》报告
利润和损失报告
利润和损失详细报告
销售分类摘要报告
销售情况报告
销售部报告
销售产品报告
税务简要报告
交易列表报告
审判报告FR
审判报告
供应商报告
供应商详细报告
供应商支出报告

使用量

let {QboConnector} = require('@apigrate/quickbooks');

let connector = new QboConnector(
  client_id,        
  client_secret,    
  redirect_uri,
  access_token,     
  refresh_token,    
  realm_id,         
  minorversion
);

//Get the accounting API object.
let qbo = await connector.accountingApi();  

//Now you can make API calls!

构造器选项 :

  • 客户端( d) (单位:千美元)字符串,要求) 因图伊特为您的应用程序指定客户端ID.
  • 客户端 机密 (单位:千美元)字符串,要求) Intuit为您的应用程序指定了客户端秘密.
  • 方向调整 uri (单位:千美元)字符串, 需要) 用于您的应用程序的有效注册重定向 URI 。 注意,对于生产,这必须是SSL链接(HTTPS).
  • 访问( t) (单位:千美元)字符串,有条件的) 熊克令牌,用于API调用授权头. 你应该从自己的仓库里拿到这个.
  • 刷新( tk) (单位:千美元)字符串,有条件) 切换到过期时刷新 access token 。 你应该从自己的仓库里拿到这个.
  • 域名( d) 编号 (单位:千美元)字符串,有条件的)Intuit公司标识,用于API调用URL. 你应该从自己的仓库里拿到这个.
  • 证书 初始化器 (单位:千美元)函数,有条件) 初始化的同步函数 access_token, (中文(简体) ), refresh_token,以及 realm_id;它被设计为bbe用来代替提供它们作为构造参数. 您执行的函数必须返回表单的证书对象 : { access_token, refresh_token, realm_id}。在第一个API方法引用时自动引用此函数。 如果您省略了此功能, 您需要调用 setCredentials 方法,在您第一次 API 方法引用之前使用同一结构的对象.
  • 微调 (单位:千美元)编号,可选)指定每个API呼叫上要传递的QuickBooks API小版本参数
  • 转向后退 (单位:千美元)编号,可选),在收到HTTP 429(速率限制)响应后,等待重试请求的毫秒数. 默认为 10000 (10秒钟). 见 处理错误 更多细节.
  • 基数Url (单位:千美元)字符串,有条件) API呼叫的Intuit基础URL. 未提供时, 它默认为 API 的 Intuit 生产基础 URL : https://quickbooks.api.intuit.com/v3然而对于快书沙盒的使用, 您必须明确提供数字 : https://sandbox-quickbooks.api.intuit.com/v3

连接器会自动使用任何提供的证书来更新过期的 access token 。 连接器发出 a token.refreshed 内部事件,当它这样做。 执行您自己的收听器功能来存储证书 .


//Event hook to handle a token refresh.
connector.on('token.refreshed', function(credentials){
  console.log('Token was refreshed.');
  
  //Use this function to store/update your OAuth data

  //The credentials object may have the following properties:
  credentials.access_token; //Bearer token for API calls.
  credentials.expires_in; //how long before access token expires, in s
  credentials.refresh_token; //for getting another access token
  credentials.x_refresh_token_expires_in; //how long before refresh_token expires, in s
  credentials.realm_id; //the qbo company id
  
});

制作API电话

您使用从 QD 中返回的对象进行 QuickBooks 会计 API 调用 connector.accountingApi() 方法(以下简称示例) qbo) (中文(简体) ). 此实体将 快书在线会计API。 。 。 .

查询

使用 Intuit 查询语法查询任意类型的对象 .

实体.query(报表,选择)

  • statement (单位:千美元)字符串查询语句(参见数据查询用于您正在合作的实体
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.
let result = await qbo.Item.query(
  `select * from Item where Active=true and Type='Inventory'`
  );

这个 result 为:

{
  "QueryResponse": {
    "Item": [
      {
        "Name": "Pump",
        "Description": "Fountain Pump",
        "Active": true,
        "FullyQualifiedName": "Pump",
        "Taxable": true,
        "UnitPrice": 15,
        "Type": "Inventory",
        "IncomeAccountRef": {
          "value": "79",
          "name": "Sales of Product Income"
        },
        "PurchaseDesc": "Fountain Pump",
        "PurchaseCost": 10,
        "ExpenseAccountRef": {
          "value": "80",
          "name": "Cost of Goods Sold"
        },
        "AssetAccountRef": {
          "value": "81",
          "name": "Inventory Asset"
        },
        "TrackQtyOnHand": true,
        "QtyOnHand": 25,
        "InvStartDate": "2018-03-29",
        "domain": "QBO",
        "sparse": false,
        "Id": "11",
        "SyncToken": "3",
        "MetaData": {
          "CreateTime": "2018-03-26T10:46:45-07:00",
          "LastUpdatedTime": "2018-03-29T13:16:17-07:00"
        }
      }
    ]
  }
}

注意,虽然Intuit查询API端点对所有实体都是通用的,但如果在适当的实体端点上使用查询方法,连接器会提供一些额外的保障验证. 例如,我们建议使用 qbo.Items.query 改为 qbo.query 以明确代码.

获取身份

你需要的只是实体身份,你可以找到实体的全部细节.

实体. get( id, 选项)

  • id (单位:千美元)编号用于您想要获取的实体的 id
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.

示例:获取项目:

let result = await qbo.Item.get(11);

这个 result 为:

{
  "Item": {
    "Name": "Widget",
    "Active": true,
    "FullyQualifiedName": "Widget",
    "Taxable": false,
    "UnitPrice": 0,
    "Type": "Service",
    "IncomeAccountRef": {
      "value": "79",
      "name": "Sales of Product Income"
    },
    "PurchaseCost": 0,
    "TrackQtyOnHand": false,
    "domain": "QBO",
    "sparse": false,
    "Id": "21",
    "SyncToken": "0",
    "MetaData": {
      "CreateTime": "2018-11-13T14:41:34-08:00",
      "LastUpdatedTime": "2018-11-13T14:41:34-08:00"
    }
  },
  "time": "2018-11-13T15:08:40.458-08:00"
}

创建

这个 .create() 方法用于创建实体。 记住,根据您创建的实体类型,可以有条件地要求一些字段.

实体. 创建( 负载, 选择)

  • payload (单位:千美元)对象) 包含要创建的物体的所有可写入字段的物体有效载荷.
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.

示例: 创建项目

let result = await qbo.Item.create({
  "Name": 'Widget',
  "Type": 'Inventory',
  "IncomeAccountRef": {
      "value": "79",
      "name": "Sales of Product Income"
  }
});

这个 result 为:

{
  "Item": {
    "Name": "Widget",
    "Active": true,
    "FullyQualifiedName": "Widget",
    "Taxable": false,
    "UnitPrice": 0,
    "Type": "Service",
    "IncomeAccountRef": {
      "value": "79",
      "name": "Sales of Product Income"
    },
    "PurchaseCost": 0,
    "TrackQtyOnHand": false,
    "domain": "QBO",
    "sparse": false,
    "Id": "21",
    "SyncToken": "0",
    "MetaData": {
      "CreateTime": "2018-11-13T14:41:34-08:00",
      "LastUpdatedTime": "2018-11-13T14:41:34-08:00"
    }
  },
  "time": "2018-11-13T14:41:34.885-08:00"
}

示例:创建比尔

let result = await qbo.Bill.create({
  "Line": [
    {
      "DetailType": "AccountBasedExpenseLineDetail", 
      "Amount": 200.0, 
      "Id": "1", 
      "AccountBasedExpenseLineDetail": {
        "AccountRef": {
          "value": "7"
        }
      }
    }
  ], 
  "VendorRef": {
    "value": "42"
  }
});

这个 result 为:

{
  "Bill": {
    "DueDate": "2020-08-25",
    "Balance": 200,
    "domain": "QBO",
    "sparse": false,
    "Id": "145",
    "SyncToken": "0",
    "MetaData": {
      "CreateTime": "2020-08-25T06:27:05-07:00",
      "LastUpdatedTime": "2020-08-25T06:27:05-07:00"
    },
    "TxnDate": "2020-08-25",
    "CurrencyRef": {
      "value": "USD",
      "name": "United States Dollar"
    },
    "Line": [
      {
        "Id": "1",
        "LineNum": 1,
        "Amount": 200,
        "LinkedTxn": [],
        "DetailType": "AccountBasedExpenseLineDetail",
        "AccountBasedExpenseLineDetail": {
          "AccountRef": {
            "value": "7",
            "name": "Advertising"
          },
          "BillableStatus": "NotBillable",
          "TaxCodeRef": {
            "value": "NON"
          }
        }
      }
    ],
    "VendorRef": {
      "value": "42",
      "name": "Lee Advertising"
    },
    "APAccountRef": {
      "value": "33",
      "name": "Accounts Payable (A/P)"
    },
    "TotalAmt": 200
  },
  "time": "2020-08-25T06:27:05.412-07:00"
}

更新

和 .update() 用于更新 API 实体的方法。 在更新实体时,大多数实体支持一个"完整更新"模式,在此模式中,预计您会发送整个一组要更新的字段(任何缺失都会被设定为无效). 因此,建议你:

  1. 先把完整的实体拿来,
  2. 修改要更改的字段,
  3. 将完整对象送回,作为更新操作的一部分.
    见 退出快书在线 API 文档 以了解更多关于您与之合作的实体的详细信息.

实体.update(载荷,选择)

  • payload (单位:千美元)对象) 包含要更新的物体所有可写入字段的物体有效载荷.
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.

示例:更新项目

let existing = await qbo.Item.get(19);
existing.Item.Name="Rubber Ducky";
let result = await qbo.Item.update(existing.Item);

这个 result 为:

{
  "Item": {
    "Name": "Rubber Ducky",
    "Active": true,
    "FullyQualifiedName": "Rubber Ducky",
    "Taxable": false,
    "UnitPrice": 0,
    "Type": "Service",
    "IncomeAccountRef": {
      "value": "79",
      "name": "Sales of Product Income"
    },
    "PurchaseCost": 0,
    "TrackQtyOnHand": false,
    "domain": "QBO",
    "sparse": false,
    "Id": "21",
    "SyncToken": "1",
    "MetaData": {
      "CreateTime": "2018-11-13T14:41:34-08:00",
      "LastUpdatedTime": "2019-08-28T12:05:02-08:00"
    }
  },
  "time": "2019-08-28T12:05:02.148-08:00"
}

删除

大多数交易实体都支持删除,但只有少数命名列表实体支持. 在删除时,你需要两个 Id 编辑 SyncToken类似 update() 方法,通常最好在删除之前立即取出一个实体,以获取最新的 SyncToken。 。 。 .

你可以考虑 SyncToken 作为你与之合作的实体的"版本号". 它是一种防止两个人同时对同一个实体进行修改的机制.

实体. delete( 载荷, 选择)

  • payload (单位:千美元)对象(b) 载有下列两种物体的有效载荷: Id 编辑 SyncToken 对象的属性.
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.

示例:删除法案

let result = await qbo.Bill.delete({
  "Id": 145,
  "SyncToken": 0 
});

这个 result 为:

{
  "Bill": {
    "domain": "QBO",
    "status": "Deleted",
    "Id": "145"
  },
  "time": "2020-08-25T06:48:57.291-07:00"
}

对于不支持"硬删除"的entites,通常有通过设置来"软删除"的方法 Active=false 使用 update() 方法,或者类似的东西.

虚拟

某些因图伊特实体(BillPayment、发票、付款、销售回购)支持Void。 这些与更新类似, 但您必须使用 .voidTransaction() 执行空隙的方法.

实体.void 交易(载荷,选择)

  • payload (单位:千美元)对象含有物体空有效载荷场的物体有效载荷。 通常你需要提供有效载荷,例如: {Id: 192, SyncToken: 0}。注意,这意味着您应该先取回实体,然后将其撤销,因为您应该使用当前实体的同步符号.
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.

批量请求

批量请求( 包含一个请求的多个操作) 已支持 ! 这里有一个代码示例。 这将删除多个时间活动, 但您可以混合您自己的交易类型 。 它们不需要是同一类实体或行动.

实体.batch( 有效载荷, 选择)

  • payload (单位:千美元)对象载有批量请求的物体有效载荷。 (见 因纽特文档 关于如何进行批量操作的详情.
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.
try{
  let activities = [
    {Id: 123489, SyncToken: 0},
    {Id: 178275, SyncToken: 0},
    {Id: 189085, SyncToken: 0},
    ///...
    {Id: 190239, SyncToken: 0},
  ];//Only Id and SyncToken are needed on each for delete


  let batch = {
    BatchItemRequest: []
  }

  for(let i=0; i<activities.length; i++){
    let activityToDelete = activities[i];

    batch.BatchItemRequest.push({
      bId: i,
      operation: "delete",
      TimeActivity: {
        Id: activityToDelete.Id,
        SyncToken: activityToDelete.SyncToken
      }
    });
  }

  //Invoke Batch API
  await qbo.batch(batch);

} catch (err) {
  //...
}

请注意,由于您可以在批量请求中混合实体的类型,所以这种方法不会在实体上命名空格(它直接存在于 qbo 对象).

运行报表

只需使用 query 对每个报告实体采用方法,作为散列提供参数.

报告实体.query(武器,选择)

  • parms (单位:千美元)对象一个其属性将作为报告请求参数的对象.
  • opts (单位:千美元)对象,可选)
    • reqid (单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.
    • minor_version (单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖 minor_version 构造参数,如果提供了.

示例:运行客户收入报告

let result = await qbo.CustomerIncomeReport.query(
  {
    start_date: '2019-01-01', 
    end_date: '2020-04-01'
  }
);

这个 result 为:

{
  "Header": {
    "Time": "2020-08-21T15:04:49-07:00",
    "ReportName": "CustomerIncome",
    "ReportBasis": "Accrual",
    "StartPeriod": "2019-01-01",
    "EndPeriod": "2020-04-01",
    "Currency": "USD",
    "Option": [
      {
        "Name": "NoReportData",
        "Value": "false"
      }
    ]
  },
  "Columns": {
    ...etc
  },
  "Rows": {
    ...etc
  }
}

(为长度删除了一些细节)

处理错误

API 特定错误( 通常为 HTTP-4xx) 响应, 被困入并被扔入 ApiError 课。 下列错误类别可供使用:

  • 痛苦 - API一般错误(HTTP 4xx/5xx答复)
  • Apithrottling (英语) 错误 - 亚类 ApiError,当HTTP 429在尝试用尽后遇到回复时抛出
  • 证书错误 - OAuth 证书缺失或无效时丢弃
  • Token Refresh 错误 - 当访问令牌刷新失败时丢弃

自动刷新

当API呼叫收到HTTP 401(未经授权)响应后,连接器会自动尝试使用刷新符刷新访问令牌并重试请求一次. 如果刷新成功的话 token.refreshed 事件被发布(参见 使用量 如何处理此事件)。 如果刷新失败, a TokenRefreshError 被抛出.

自动转动后退

当API呼叫收到HTTP 429(太多请求)响应后,连接器会自动等待并重复请求一次. 等待时间可通过 throttle_backoff 构造器选项( 默认值: 10秒 / 1000ms) .

let connector = new QboConnector({
  client_id: 'your_client_id',
  client_secret: 'your_client_secret',
  redirect_uri: 'your_redirect_uri',
  throttle_backoff: 60000
});

如果重试还收到HTTP 429回复,则 ApiThrottlingError 被抛出.

示例: 试图创建失败的字段

const {ApiError} = require('@apigrate/quickbooks');
try{
  let result = qbo.Item.create({
    "Name": "Body Armor",
    "Type": "Inventory"
    //This will fail because there are other fields required...
  });

} catch (err){
  if(err instanceof ApiError){
    err.message; //contains a readable, parsed error message,
    err.payload; //the object payload of the error, if one was returned
  }

}

err.payload 示例:

{
  "Fault": {
    "Error": [
      {
        "Message": "Object Not Found",
        "Detail": "Object Not Found : Something you're trying to use has been made inactive. Check the fields with accounts, customers, items, vendors or employees.",
        "code": "610",
        "element": ""
      }
    ],
    "type": "ValidationFault"
  },
  "time": "2018-11-13T15:21:29.433-08:00"
}

请注意: Fault.Error 是一个 数组,虽然大多数时候只有一个错误。 对于每个错误 Message 是该错误的高级解释.

OAuth 获得 IntuitAuthorization Url = 函数(状态)

连接器还为构建一个 客户端对因地制宜 启动用户 OAuth2 授权程序的 URL.

参数:

  1. 状态 (字符串) 提供任何可能对您收到答复后的申请有用的状态. Intuit 授权服务器绕行此参数, 因此您的应用程序收到它发送的值 。 建议在州内设置一个CSRF标志.

返回所有参数设置和编码的授权 URL 字符串. 你用这个来做你自己的电话, 典型的UI组件. 注意,当用户认证后重定向 uri被引用时,将包含以下查询参数:

  1. code (这是你们用来交换访问符和刷新符)
  2. realmId - 这代表QBO公司 普因图伊特的指示应该安全地储存起来.

版本与发布记录

@apigrate/quickbooks 共发布 19 个版本,首次发布于 2018/11/15;过去 12 个月发布了 2 个版本。

版本发布日期距今
4.6.0latest2026/03/038 个月前
4.5.02026/03/018 个月前
4.4.02025/11/041 年前
4.3.02023/07/123 年前
4.2.02022/03/094 年前
4.1.02021/12/094 年前

关于 @apigrate/quickbooks 的常见问题

@apigrate/quickbooks 是什么?

Intuit快取快取API的节点JS API连接器.

如何安装 @apigrate/quickbooks?

在项目目录运行 npm install @apigrate/quickbooks,或使用 pnpm add / yarn add / bun add。

@apigrate/quickbooks 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/apigrate__quickbooks 是否存在。

@apigrate/quickbooks 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@apigrate/quickbooks 可以商用吗?

@apigrate/quickbooks 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@apigrate/quickbooks 的下载量有多少?

根据 npm 官方下载统计,@apigrate/quickbooks 在 2026/10/06 – 2026/11/04 这 30 天内被下载 2,175 次,日均约 73 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@apigrate/quickbooks 还在维护吗?

最新版本 4.6.0 发布于 2026/03/03(8 个月前);至今共发布 19 个版本,其中过去 12 个月发布了 2 个;首次发布于 2018/11/15。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。