{"id":21043396,"url":"https://github.com/crystallizeapi/import-utilities","last_synced_at":"2025-07-26T21:12:30.656Z","repository":{"id":37093080,"uuid":"330771015","full_name":"CrystallizeAPI/import-utilities","owner":"CrystallizeAPI","description":"Utils to help with importing data into Crystallize","archived":false,"fork":false,"pushed_at":"2024-07-03T14:40:26.000Z","size":3318,"stargazers_count":8,"open_issues_count":2,"forks_count":5,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-03T12:51:18.330Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CrystallizeAPI.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-18T19:49:22.000Z","updated_at":"2024-07-29T21:15:35.000Z","dependencies_parsed_at":"2024-02-09T02:08:40.903Z","dependency_job_id":"28577411-addd-4c1c-ade8-b962a88a0cbc","html_url":"https://github.com/CrystallizeAPI/import-utilities","commit_stats":{"total_commits":772,"total_committers":10,"mean_commits":77.2,"dds":"0.35492227979274615","last_synced_commit":"b42070cbb5c4e68e50b5238086c204a34b2d37b9"},"previous_names":[],"tags_count":328,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fimport-utilities","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fimport-utilities/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fimport-utilities/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fimport-utilities/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CrystallizeAPI","download_url":"https://codeload.github.com/CrystallizeAPI/import-utilities/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254388145,"owners_count":22062994,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T14:12:41.182Z","updated_at":"2025-05-15T17:31:46.279Z","avatar_url":"https://github.com/CrystallizeAPI.png","language":"TypeScript","readme":"# @crystallize/import-utilities\n\nThis repository contains a collection of types and functions that can be used\nto:\n\n- [Import data to a tenant](https://github.com/CrystallizeAPI/examples/tree/main/products-import)\n- [Backup a tenant](https://github.com/CrystallizeAPI/examples/tree/main/backup-tenant)\n- [Transfer data from one tenant to another tenant](https://github.com/CrystallizeAPI/examples/tree/main/duplicate-tenant)\n\n[Examples](https://github.com/CrystallizeAPI/examples)\n---\n\n```typescript\nconst myBurgerShop = {\n  shapes: [\n    {\n      name: 'Ingredient',\n      identifier: 'ingredient',\n      type: 'product',\n    },\n  ],\n  items: [\n    {\n      name: 'Burger Bun',\n      shape: 'ingredient',\n      vatType: 'No Tax',\n      variants: [\n        {\n          name: 'Regular burger bun',\n          sku: 'burger-bun-regular',\n          attributes: {\n            size: 'medium',\n          },\n          isDefault: true,\n        },\n      ],\n    },\n    {\n      name: 'Burger patty',\n      shape: 'ingredient',\n      vatType: 'No Tax',\n      variants: [\n        {\n          name: 'Beef burger patty',\n          sku: 'burger-patty-beef',\n          isDefault: true,\n          price: {\n            eur: 5,\n          },\n        },\n        {\n          name: 'Vegan burger patty',\n          sku: 'burger-patty-vegan',\n          isDefault: false,\n          price: {\n            eur: 6,\n          },\n        },\n      ],\n    },\n    {\n      name: 'Cheddar cheese',\n      shape: 'ingredient',\n      vatType: 'No Tax',\n      variants: [\n        {\n          name: 'Standard cheddar cheese',\n          sku: 'cheddar-cheese-standard',\n          isDefault: true,\n          price: {\n            eur: 1,\n          },\n        },\n        {\n          name: 'Vegan cheddar cheese',\n          sku: 'cheddar-cheese-vegan',\n          isDefault: false,\n          price: {\n            eur: 1.5,\n          },\n        },\n      ],\n    },\n  ],\n}\n```\n\n## Creating a tenant specification\n\nThe tenant specification describes how the tenant is configured, and can contain\ninformation on:\n\n- [Languages](https://crystallize.com/learn/concepts/pim/multilingual)\n- [VAT types](https://crystallize.com/learn/concepts/ecommerce/tax)\n- [Price variants](https://crystallize.com/learn/concepts/ecommerce/price-variant)\n- [Shapes](https://crystallize.com/learn/concepts/pim/shape)\n- [Topics](https://crystallize.com/learn/concepts/pim/topic-map)\n- [Grids](https://crystallize.com/learn/concepts/pim/grid-organizer)\n- [Products](https://crystallize.com/learn/concepts/pim/product),\n  [Documents](https://crystallize.com/learn/concepts/pim/document) and\n  [Folders](https://crystallize.com/learn/concepts/pim/folder)\n\nIt is described in a `.json` file, like such:\n\n```json\n{\n  \"languages\": [],\n  \"vatTypes\": [],\n  \"priceVariants\": [],\n  \"shapes\": [],\n  \"topicMaps\": [],\n  \"grids\": [],\n  \"items\": []\n}\n```\n\n### Create the specification manually\n\nYou can create the tenant specification manually, with the help of the\n`JSONSpec` type exported from the package:\n\n```typescript\nimport { JSONSpec } from '@crystallize/import-utilities'\n\nconst mySpec: JSONSpec = {\n  languages: [{}],\n}\n```\n\nSee a simple example of this in the\n[examples/component-numeric](https://github.com/CrystallizeAPI/examples/blob/main/component-numeric)\nfolder\n\n### Create the specification automatically\n\nYou can create the tenant specification automatically, with the help of the\n`Bootstrapper` class exported from the package:\n\n```typescript\nimport { Bootstrapper } from '@crystallize/import-utilities'\n\nconst mySpec: JSONSpec = await bootstrapper.createSpec({\n  ...\n});\n```\n\nSee a simple example of this in the\n[examples/backup-tenant](https://github.com/CrystallizeAPI/examples/tree/main/backup-tenant)\nfolder.\n\nSee more examples in our extensive\n[examples repository](https://github.com/CrystallizeAPI/examples)\n\n### Bootstrap a tenant\n\nYou can bootstrap a tenant using a specification with the help of the\n`Bootstrapper` class exported from the package:\n\n```typescript\nimport { Bootstrapper, JSONSpec } from '@crystallize/import-utilities'\n\nbootstrapper.start()\n```\n\nSee a simple example of this in the\n[examples/bootstrap-tenant](https://github.com/CrystallizeAPI/import-utilities/tree/main/examples/bootstrap-tenant)\nfolder.\n\nSee more examples in our extensive\n[examples repository](https://github.com/CrystallizeAPI/examples)\n\n## Creating single queries and mutations\n\nFor composing single queries and mutations, not using the JSON specification,\nthere are a collection of types and functions that help with that. Here's a\ncouple of examples.\n\n### Creating a Tenant\n\nYou can easily build the GraphQL mutation for creating a tenant.\n\n```typescript\nimport {\n  buildCreateTenantMutation,\n  TenantInput,\n} from '@crystallize/import-utilities'\n\n// Define the structure for the tenant\nconst input: TenantInput = {\n  identifier: 'my-cooking-blog',\n  name: 'My Cooking Blog',\n}\n\n// Build the mutation string\nconst mutation = buildCreateTenantMutation(input)\n```\n\nYou now have a mutation string that will create a new tenant. You can then\nsubmit this query to the [Core API][0] using your preferred GraphQL client\n(apollo, urql, etc) to actually create your tenant within Crystallize.\n\n### Creating Shapes\n\nIf you have an existing tenant you can also just create individual shapes by\ngenerating mutations from shape definitions.\n\n```typescript\nimport {\n  buildCreateShapeMutation,\n  ShapeInput,\n  shapeTypes,\n  componentTypes,\n} from '@crystallize/import-utilities'\n\n// Define the structure for the shape\nconst input: ShapeInput = {\n  identifier: 'my-shape',\n  tenantId: '\u003cyour tenant id\u003e',\n  name: 'My Custom Product Shape',\n  type: shapeTypes.product,\n  components: [\n    {\n      id: 'images',\n      name: 'Images',\n      type: componentTypes.images,\n    },\n    {\n      id: 'description',\n      name: 'Description',\n      type: componentTypes.richText,\n    },\n  ],\n}\n\n// Build the mutation string\nconst mutation = buildCreateShapeMutation(input)\n```\n\nYou now have a mutation string that will create a new product shape with your\nown custom component structure. You can then submit this query to the [Core\nAPI][0] using your preferred GraphQL client (apollo, urql, etc) to create the\nshapes for your tenant.\n\n### Creating Items\n\nYou can easily build mutations to create items by extending the shapes to\nprovide a schema for different items types. This is kind of a two-step process.\n\n#### 1. Define the structure for the shape (as per the examples above)\n\n```typescript\nimport {\n  buildCreateShapeMutation,\n  ShapeInput,\n  shapeTypes,\n  componentTypes,\n} from '@crystallize/import-utilities'\n\n// Define the structure for the shape\nconst recipeShape: ShapeInput = {\n  identifier: 'recipe',\n  tenantId: '\u003cyour tenant id\u003e',\n  name: 'Recipe',\n  type: shapeTypes.document,\n  components: [\n    {\n      id: 'ingredients',\n      name: 'Ingredients',\n      type: componentTypes.propertiesTable,\n    },\n    {\n      id: 'instructions',\n      name: 'Intructions',\n      type: componentTypes.richText,\n    },\n  ],\n}\n\n// Build the mutation string\nconst createShapeMutation = buildCreateShapeMutation(recipeShape)\n```\n\nYou can also create this shape manually via the PIM UI, if you prefer.\n\n#### 3. Importing a single item\n\n```typescript\nimport {\n  buildCreateItemMutation,\n  CreateItemInput,\n} from '@crystallize/import-utilities'\n\nconst itemData: CreateItemInput = {\n  name: 'Cookies Recipe',\n  shapeIdentifier: 'recipe',\n  tenantId: '\u003cyour tenant id\u003e',\n  components: {\n    ingredients: {\n      sections: {\n        title: 'Ingredients',\n        properties: [\n          {\n            key: 'Flour',\n            value: '1 Cup',\n          },\n          {\n            key: 'Chocolate Chips',\n            value: '1 Cup',\n          },\n        ],\n      },\n    },\n    instructions: {\n      richText: {\n        plainText: 'Start by adding the flour, brown sugar...',\n      },\n    },\n  },\n}\n\nconst createItemMutation = buildCreateItemMutation(itemData)\n```\n\n[0]: https://crystallize.com/learn/developer-guides/api-overview/api-endpoints\n\n## Tenant specification and bootstrap\n\nThe specification/bootstrap of tenant is broken down into two separate\noperations\n\n1. Create a backup of a tenant, storing it as a `.json` specification\n2. Bootstrapping a tenant, using a `.json` specification\n\n### Create a tenant specification\n\nThe tenant specification describes how the tenant is configured, and can contain\ninformation on:\n\n- [Languages](https://crystallize.com/learn/concepts/pim/multilingual)\n- [VAT types](https://crystallize.com/learn/concepts/ecommerce/tax)\n- [Price variants](https://crystallize.com/learn/concepts/ecommerce/price-variant)\n- [Stock locations](https://crystallize.com/learn/concepts/ecommerce/stock-location)\n- [Shapes](https://crystallize.com/learn/concepts/pim/shape)\n- [Topics](https://crystallize.com/learn/concepts/pim/topic-map)\n- [Grids](https://crystallize.com/learn/concepts/pim/grid-organizer)\n- [Products](https://crystallize.com/learn/concepts/pim/product),\n  [Documents](https://crystallize.com/learn/concepts/pim/document) and\n  [Folders](https://crystallize.com/learn/concepts/pim/folder)\n\nIt is described in a `.json` file, like such:\n\n```json\n{\n  \"languages\": [],\n  \"vatTypes\": [],\n  \"priceVariants\": [],\n  \"shapes\": [],\n  \"topicMaps\": [],\n  \"grids\": [],\n  \"items\": []\n}\n```\n\n## Long running processes\n\nMost examples of using import-utilities library assume that you're using it as a CLI tool. In that case the execution of `.kill()` method is optional. However, if you want to use import-utilities in a long running process (for example in a web server) then you have to use this method like in the following example:\n\n```typescript\n...\npublic async importProductsAsync(spec: JsonSpec): Promise\u003cvoid\u003e {\n  const bootstrapper = new Bootstrapper();\n\n  bootstrapper.setAccessToken(\"\u003caccess_token_id\u003e\", \"\u003caccess_token_secret\u003e\");\n  bootstrapper.setTenantIdentifier(\"\u003ccrystallize_tenant_identifier\u003e\");\n  bootstrapper.setFallbackFolderId(\"\u003ccrystallize_fallback_folder_id\u003e\");\n\n  bootstrapper.setSpec(spec);\n\n  await bootstrapper.start();\n  await bootstrapper.kill();\n}\n...\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrystallizeapi%2Fimport-utilities","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrystallizeapi%2Fimport-utilities","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrystallizeapi%2Fimport-utilities/lists"}