@growstack/sdk

中文文档
0.4.0发布于 2026/11/01MITTypeScriptES Module零依赖

用于Growstack公共API的类型化、重试安全的客户端

中文使用文档
文档目录13 节
  1. 发送事务性消息
  2. 插入联系人
  3. 同步产品帐户
  4. 属性和字段历史
  5. 请求双重选择订阅
  6. 跟踪事件
  7. 上传品牌标志
  8. 打开客户计费页面
  9. 处理错误
  10. 呼叫、重试和取消
  11. 迭代记录页
  12. 开发和发行
  13. 管道和交易

@growstack / sdk

整个Growstack公共API的类型化客户端。MIT授权,ESM带有TypeScript声明,使用global fetch 在Node 20+, Bun, Vercel和edge运行时。

npm install @growstack/sdk
import { createGrowstack, GrowstackError } from '@growstack/sdk'

const growstack = createGrowstack({ apiKey: process.env.GROWSTACK_API_KEY! })
// For self-hosting: createGrowstack({ apiKey, baseUrl: 'https://marketing.example.com' })

每个实例都有自己的键、基URL和可选 fetch(request) 实现。在服务器上使用密钥。公钥只属于工作区跟踪策略所允许的浏览器操作。

在已登录的浏览器中,省略 apiKey 并使用应用程序的起源。SDK发送no 授权头并通过Fetch保存cookie credentials 选项, 默认为 same-origin. 集 credentials: 'include' 当你部署的时候 允许来自其他来源的cookie认证请求。

const personal = createGrowstack({ baseUrl: window.location.origin })
const accounts = await personal.connections.list()

连接和成员连接摘要需要会话。API密钥不能 访问它们。

发送事务性消息

需要 messages:send密钥上的授权发送方,以及经过验证的发送方域。这个 message 键是工作区发布的Simple消息模板。其他发布的模板键也以同样的方式工作。

const sent = await growstack.messages.create({
  body: {
    to: '[email protected]',
    from: { address: '[email protected]' },
    purpose: 'transactional',
    template: {
      key: 'message',
      variables: { subject: 'Your receipt', body: 'Thank you for your order.' },
    },
  },
}, { idempotencyKey: 'order:example-42:receipt' })
console.log(sent.id)

插入联系人

需要 people:write. 电子邮件或外部标识符查找或创建现有联系人。省略的字段保持不变;相互冲突的身份永远不会悄然合并。

const { person, created } = await growstack.people.upsert({
  body: {
    identifier: { email: '[email protected]' },
    name: 'Ana',
    country: 'ES',
    source: 'shop',
  },
})

同步产品帐户

需要 people:write. 品牌标识符和不可变账户标识符标识 帐户。使用一个计数器或时间戳保持其源版本增加 种类。相等或更旧的版本返回 ignored: true 并保持所有数据完整。

const { account, ignored } = await growstack.productAccounts.upsert({
  path: { brand: 'heralded', externalId: 'workspace-42' },
  body: {
    revision: 5,
    name: 'Example workspace',
    status: 'paying',
    plan: 'Growth',
    currency: 'EUR',
    mrr: '79.00',
    users: [{ identifier: { email: '[email protected]' }, role: 'owner' }],
  },
})

省略的字段保持不变。提供的用户替换成员。用户接受 contact-upsert标识符;外部标识符可以包括电子邮件。 冲突的用户保持未链接和 needsReview 是真的。回顾明确 与 productAccountUsers.review,选择 link 或者 keep_apart. 后者保留了产品标识,而不附加冲突的电子邮件。

属性和字段历史

properties 管理的定义 contact, company, deal, lead 和 product_account. personProperties 公开相同的联系人定义。 共享属性只有一个键和类型 appliesTo 对象。

const definitions = await growstack.properties.list({ path: { object: 'contact' } })
const plan = definitions.data.find(property => property.key === 'plan')
const growth = plan?.optionDefinitions?.find(option => option.label === 'Growth')
const contact = await growstack.people.get({ path: { id: person.id } })
console.log(contact.attributes.plan) // Current label, such as 'Growth'
console.log(contact.attributeOptions?.plan) // { id: '<option UUID>', label: 'Growth' }

选择写入接受标签或选项id in attributes. 多选 接受一个有序的标签或id数组。读取保存标签 attributes 和公开 {id, label} 值 attributeOptions,为a使用数组 按其存储顺序多选。不匹配的值保持写入和 省略了 attributeOptions; invalidProperties 命名他们的字段。 重命名选项将保留其id,并将保存的引用解析为旧的 标签。 optionDefinitions 按id更新选项,并可以存档或合并它们。

peopleChanges.list 和 companiesChanges.list 返回字段随 他们的新旧价值观,演员和时间。重写相同的值会产生no 改变。租户导出包括定义和历史记录。

请求双重选择订阅

需要 consent:write. 创建具有双重选择的主题,或使用以这种方式配置的现有主题。

await growstack.topics.create({
  body: { key: 'product-updates', name: 'Product updates', doubleOptIn: true },
})
await growstack.subscriptions.create({
  body: { address: '[email protected]', topic: 'product-updates', source: 'shop' },
})

这将创建一个挂起的订阅。收件人通过电子邮件托管链接确认;SDK本身从不确认用户的同意。同意证据字段 details 和 occurredAt 需要一个密钥。公钥和已登录会话无法提交它们。

跟踪事件

需要 events:write 在秘钥上。浏览器跟踪使用公钥及其工作区的事件允许列表。

await growstack.track({
  body: { event: 'order.completed', email: '[email protected]', data: { order: 'example-42' } },
}, { idempotencyKey: 'order:example-42:completed' })

需要 brands:manage. 传递PNG, JPEG或WebP Blob 或者 File,最高可达200kib; 它的MIME类型。客户端发送原始字节和内容类型。

await growstack.brandsLogo.update({
  path: { id: brand.id },
  body: new Blob([imageBytes], { type: 'image/webp' }),
})

打开客户计费页面

需要一个密钥 billing:write. 该公司必须是帐单客户 而且品牌必须指定给发行公司。客户不需要 发票;然后页面显示一个空列表。测试模式被拒绝。使用HTTPS 返回的URL。返回的链接在五分钟内工作一次;创建它时 客户选择打开账单。

const portal = await growstack.billingPortalSessions.create({
  body: {
    companyId: customer.companyId,
    brandId: brand.id,
    returnUrl: 'https://app.example.com/account',
    locale: 'en',
  },
})
// Redirect your customer to portal.url.

该页面支持英语和罗马尼亚语,显示发票和报价pdf,并接受 发票支付。它不能接受引号。12个空闲小时后结束访问 或者当它的颁发密钥被移除或丢失时 billing:write.

处理错误

try {
  await growstack.people.upsert({
    body: { identifier: { email: '[email protected]' }, source: 'shop' },
  })
} catch (error) {
  if (error instanceof GrowstackError) {
    console.error(error.status, error.type, error.code, error.message, error.requestId)
    // error.issues contains field paths and messages when supplied by the API.
  } else {
    throw error // Network failures and cancellation retain their original errors.
  }
}

API信封之外的错误响应(例如网关的HTML 502)抛出 GrowstackError HTTP状态, type: 'internal', code: 'unexpected_response' 和 requestId: null.

呼叫、重试和取消

方法接受生成的 { path, query, body } 输入后跟可选 { idempotencyKey, signal },并返回解码后的成功消息体。操作使用Growstack的显式操作映射中的资源和操作,例如 growstack.campaigns.send 和 growstack.peopleEmailAddresses.list. growstack.raw 公开每个操作id,例如 raw.peopleUpsert 和 raw.trackCreate,投入和运输方式相同。

每个POST都接收一个自动UUID等幂键,除非您提供一个。生成的密钥保护一次调用内的重试。在表示相同操作的不同调用之间传递您自己的稳定密钥,如收据示例中所示。API的重放窗口是24小时。

由于网络故障,get和键控post在第一次尝试后最多重试三次,分别是429、5xx和409 idempotency_key_in_use. 每次重试都会保留确切的密钥和主体。延迟使用全抖动over min(8000, 500 × 2^retryIndex) 毫秒,或更长的有效时间 Retry-After 以秒为单位或作为HTTP日期。其他4xx,其他409和取消呼叫永远不会重试。PUT、PATCH和DELETE永远不会重试。

const controller = new AbortController()
const result = growstack.people.list({ query: { limit: 100 } }, { signal: controller.signal })
// controller.abort() cancels the request or a retry delay.
await result

迭代记录页

每个返回记录页的操作都有 .all(input, options),包括POST查询和嵌套列表。它每次产生一条记录,保留过滤器和父参数,并在 hasMore 是假的。

for await (const person of growstack.people.list.all({ query: { limit: 100 } })) {
  console.log(person.id)
}
for await (const row of growstack.people.query.all({
  body: { filter: { person: 'country', op: 'eq', value: 'ES' }, limit: 100 },
})) {
  console.log(row.person.id)
}

每个POST页都有自己的键,可用于该页的重试。如果迭代器接收到调用方键,则应用于第一页;后面的页面生成新的键,因为它们的请求体不同。发件箱迭代器 growstack.events.list.all 发送检查点 after 当被追上时就会停止,即使最后一个检查点仍然可用。使用 events.list 直接为以后的投票保存检查点。

开发和发行

服务器拥有MIT公共文档。导出没有工人,连接或凭证,然后生成与固定 @hey-api/openapi-ts 获取客户端:

bun run --cwd apps/server openapi:export
bun run --cwd packages/sdk generate
bun run --cwd packages/sdk build
bun run verify

提交 openapi.json, src/generated 和 src/bindings.gen.ts. 根验证重新导出和重新生成它们,在漂移时失败,然后构建和类型检查SDK。TypeScript 6.0.3是一个本地开发依赖,因为生成器使用了它的编译器API;存储库的TypeScript 7仍然运行根类型检查。

组件创作用途 growstack.components.preview 和 growstack.components.generate. 存储库发布通过创建一个版本 growstack.library.create 或者 growstack.libraryVersions.create,然后呼叫 growstack.libraryVersions.publish. 结果的 approvalId 确定所需的工作空间评审; publishedAt 在获得批准之前保持为空。 存储库的 bun run components CLI使用Bun构建脚本依赖项并使用它们 相同的操作。看到 packages/components/README.md.

bun run version:sdk patch|minor|major|<x.y.z> 更新版本和变更日志。这个 sdk-v<version> 标记通过OIDC触发npm可信发布的发布工作流。监督器配置受信任的发布者并推送初始的 sdk-v0.1.0 标签。如果源存储库是私有的,则省略出处,当它变为公共时必须启用出处。该软件包包含已构建的SDK、MIT源代码和文档,没有生成脚本、服务器代码或测试。源代码支持存储库的 @growstack/source 出口条件。

管道和交易

growstack.deals 创建,读取,查询,编辑,重新打开和删除交易。 growstack.pipelines 和 growstack.pipelineStages 管理管道和阶段; 这些写操作需要所有者或管理会话。舞台剪辑保留了胜利和胜利 失去的类别。交易更新可以提供所需的字段以及 stageId; expectedStageId 拒绝陈腐的举动。查询响应包括开放和加权 工作区中的汇总报告货币,并确定不可用的汇率。 growstack.dealSettings 读取和更新报告币种和丢失原因。

版本与发布记录

@growstack/sdk 共发布 5 个版本,首次发布于 2026/10/20;过去 12 个月发布了 5 个版本。

版本发布日期距今
0.4.0latest2026/11/012 天前
0.3.02026/10/313 天前
0.2.02026/10/286 天前
0.1.02026/10/2014 天前
0.0.0-stage2026/10/2014 天前

关于 @growstack/sdk 的常见问题

@growstack/sdk 是什么?

用于Growstack公共API的类型化、重试安全的客户端

如何安装 @growstack/sdk?

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

@growstack/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@growstack/sdk 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@growstack/sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@growstack/sdk 可以商用吗?

@growstack/sdk 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@growstack/sdk 还在维护吗?

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