@tradingcards-dev/setup
v1.0.0
Published
Shared one-time CRM setup runner for Trading Cards serverless functions
Readme
@tradingcards-dev/setup
Shared one-time CRM setup runner for Trading Cards serverless functions.
A template lists the CRM resources it needs in the setup block of its tc-config.json. The runner
checks which already exist in the portal and creates the rest, using the app's own access token
(PRIVATE_APP_ACCESS_TOKEN). Running it again is safe: anything that already exists is skipped.
Usage
const { getSetupStatus, runSetup, formatSetupFailures } = require('@tradingcards-dev/setup');
const templateConfig = require('../../../tc-config.json');
const status = await getSetupStatus(templateConfig); // what exists, what is missing
const result = await runSetup(templateConfig); // create what is missing
if (result.failed.length > 0) console.error(formatSetupFailures(result.failed));Add the package to the functions package.json and mark it external when bundling
(--external:@tradingcards-dev/setup), the same way as @tradingcards-dev/config.
Config
"setup": {
"enabled": true,
"crmChangesSummary": [{ "objectType": "deals", "title": "...", "description": "..." }],
"steps": [
{ "kind": "propertyGroup", "objectType": "deals", "name": "my_group", "label": "My Group" },
{
"kind": "property",
"objectType": "deals",
"groupName": "my_group",
"name": "my_property",
"label": "My Property",
"type": "string",
"fieldType": "text"
},
{
"kind": "pipeline",
"objectType": "deals",
"name": "my_pipeline",
"label": "My Pipeline",
"stages": [
{ "label": "Open", "metadata": { "probability": "0.2" } },
{ "label": "Won", "metadata": { "probability": "1.0" } },
{ "label": "Lost", "metadata": { "probability": "0.0" } }
]
}
]
}Steps run in the order listed, so declare a property group before the properties that use it.
| Kind | Matched in the portal by | Notes |
|------|--------------------------|-------|
| propertyGroup | objectType + name | |
| property | objectType + name | Fails if its groupName does not exist. |
| pipeline | objectType + label (case-insensitive) | An existing pipeline is left untouched. Stage metadata follows the Pipelines API: probability for deals, ticketState for tickets. stageId and displayOrder are optional. |
The step discriminator is kind, not type, because a property step already uses type for the
HubSpot property type.
Legacy lists
setup.propertyGroups and setup.properties are still read. They run before steps, groups first,
and can be mixed with steps in the same config.
Results
getSetupStatus resolves to docsUrl, crmChangesSummary, scopeStatus, steps (one entry per
step with exists) and resourceStatus (complete, missingItems, existingItems, plus the
group and property counts the settings pages read).
runSetup resolves to created, skipped, failed, summary and steps (one entry per step in
run order with status). Created entries carry what HubSpot assigned, such as a pipeline's id and
stage ids. A failed step is recorded with HubSpot's error and the run continues.
Scopes
The template's app needs the scopes for what it creates, for example crm.schemas.deals.write for
deal property groups and properties. A pipeline step needs a scope that allows pipeline writes for
its object; check the Pipelines API reference when adding one.
Tests
npm test