{"id":13618775,"url":"https://github.com/mitya33/cfimp","last_synced_at":"2025-04-12T03:25:44.854Z","repository":{"id":44578089,"uuid":"412569001","full_name":"mitya33/cfimp","owner":"mitya33","description":"A simple but powerful spreadsheet-derived (CSV, TSV) data importer for the Contentful headless CMS. In so doing, it can also link items to references, assets or tags, and even publish items. It can also be used to update existing items rather than import new ones.","archived":false,"fork":false,"pushed_at":"2024-05-14T14:57:46.000Z","size":112,"stargazers_count":23,"open_issues_count":3,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-10T17:54:33.017Z","etag":null,"topics":["cli","contentful","headless-cms","javascript","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/mitya33.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-10-01T17:58:57.000Z","updated_at":"2025-03-25T12:10:59.000Z","dependencies_parsed_at":"2024-06-11T21:44:51.343Z","dependency_job_id":"f8f40a41-636b-48e5-94f6-de2bf37bcfdb","html_url":"https://github.com/mitya33/cfimp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitya33%2Fcfimp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitya33%2Fcfimp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitya33%2Fcfimp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitya33%2Fcfimp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mitya33","download_url":"https://codeload.github.com/mitya33/cfimp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248511282,"owners_count":21116383,"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":["cli","contentful","headless-cms","javascript","nodejs"],"created_at":"2024-08-01T21:00:30.377Z","updated_at":"2025-04-12T03:25:44.825Z","avatar_url":"https://github.com/mitya33.png","language":"JavaScript","funding_links":["https://ko-fi.com/mitya"],"categories":[":star: Awesome Utilities"],"sub_categories":[],"readme":"# cfimp\n\ncfimp is a simple but powerful CLI tool for importing/updating CSV data in the Contentful headless CMS. The default delimiter is **tab**.\n\nIn the process of importing/updating, entries can optionally be linked to (existing) assets, tags or references (foreign items).\n\ncfimp cannot be used to create new assets, tags, models or anything other than entries.\n\n## Why\n\nContentful doesn't make it super easy to import data. There's no GUI; instead the `contentful-cli` tool has an import command, but it's [sparsely documented](https://www.contentful.com/developers/docs/tutorials/cli/import-and-export), and you first have to munge your data into JSON. There's no easy way to import spreadsheet-derived data. Further, Contentful doesn't make explicit what the structure of the JSON should be. \n\n## Examples\n\n```\n#Import comma-separated data from import.csv to space \"12345\" / content type (model) \"authors\" / locale \"en-GB\"\ncfimp -space:12345 -model:authors -locale:en-GB \n\n#Also specify some tags (for all rows)\ncfimp -space:12345 -model:authors -locale:en-GB -tags:foo,bar\n\n#Specify a fallback (default) value \"bar\" for the \"foo\" field\ncfimp -space:12345 -model:authors -locale:en-GB -dfltvals:foo=bar\n\n#Preview the generated JSON of the first entry - no actual import takes place\ncfimp -space:12345 -model:authors -locale:en-GB -preview\n```\n\n## Prerequisites\n\n1. Install [`contentful-cli`](https://www.npmjs.com/package/contentful-cli) globally.\n\n```\nnpm install -g contentful-cli\n```\n\n2. Authenticate with Contentful (optional).\n\n```\ncontentful login\n```\n\nAuthenticating this way will save the credentials in your environment so you don't have to authenticate manually each time you use cfimp. If you'd rather do that instead, though, see the `mtoken` argument.\n\n3. Install cfimp globally\n\n```\nnpm i -g cfimp\n```\n\n## Usage\n\n\u003e Note: the default delimiter is **tab**. This can be changed via the `delim` arg.\n\n\u003e It's strongly recommended to preview the generated data before running the write. See the `preview` arg.\n\n```\ncfimp \u003cargs\u003e\n```\n\nArguments are specified in the format `-arg:val` or, where the argument doesn't accept a value (denoted `*` below), simply `-arg`. Where `val` contains spaces, use `-arg:\"one two\"`.\n\nValid arguments are as follows.\n\n- `input` - path to the input file (optional; default: \"import.csv\")\n- `space` - the ID of the Contentful space to write to (required)\n- `model` - the ID of the Contentful model (content type) to write to (required)\n- `locale` - the locale, as defined in Contentful, e.g. \"[en-GB]\". See [Writing to multiple locales](#user-content-multiple-locales) (required)\n- `preview*` - if passed, shows a preview of the data that will be written to Contentful; no write is performed. See [Troubleshooting](#user-content-troubleshooting) (optional)\n- `previewfile*` - if passed, quits after generating the Contentfil JSON file, so you can inspect it. See [Troubleshooting](#user-content-troubleshooting) (optional)\n- `env` - the ID of the Contentful environment to use (optional; default: \"master\")\n- `publish*` - sets the imported/updated entries to \"published\" status rather than \"draft\" (optional)\n- `mergevals` - a com-sep list of `field=value` pairs - to merge into all rows. See [Merge and default values](#user-content-merged-and-default-values) (optional)\n- `dfltvals` - a com-sep list of `field=value` defaults to be used anywhere a row has empty cells. See [Merge and default values](#user-content-merged-and-default-vaues) (optional)\n- `delim` - the delimiter separating columns (for multi-column files) - one of \"tab\", \"com\" (comma) or any other string (optional; default: \"tab\")\n- `fields` - the fields to import into. If omitted, cfimp will assume the first row of the input data denotes the fields (optional)\n- `enc` - the file encoding for your data (you shouldn't need to change this) - one of \"utf8\", \"ascii\" or \"base64\" (optional; default: \"utf8\")\n- `offset` - a 1-index offset (row) to begin reading data from in your input file (optional)\n- `limit` - a limit as to the number of rows to process (optional)\n- `skiprows` - a com-sep list of strings which, if any is found in a row (any column), will cause that row to be skipped. The logic can be inverted. See [Filtering rows](#user-content-filtering-rows) (optional)\n- `skipfields` - a com-sep list of field IDs to ignore from the input. Useful if your spreadsheet export contains columns you don't want to include (optional)\n- `nocast` - ordinarily, numbers, true and false will be cast to their integer/boolean equivalents when data is passed to Contentful. Pass true to prevent this (i.e. if you literally want to pass \"true\" not `true`) (optional)\n- `tagall` - a com-sep list of (existing) tags to tag all entries with. You can also specify row-specific tags. See [Tagging items](#user-content-tagging-items) (optional)\n- `listdelim` - the delimiter used within list values e.g. default values, tags (optional; default: \",\"). See [Delimiter overrides](#user-content-delimiter-overrides)\n- `mtoken` - a management token to authenticate with Contentful. You can omit this if you've already authenticated via `contentful login` (optional)\n\n## Reference and asset links\n\nIt's possible to link to **existing** assets or references (i.e. foreign items in other content types) via the `ref-` (reference) and `refa-` (asset) prefixes.\n\nIn both cases, you'll need to know the ID of the item you're linking to.\n\nSuppose you had a content type of authors and had a field, `authorPhoto` which was an asset field. We'd link authors to their photos like so:\n\n```\nforename\tsurname\tauthorPhoto\nPhilippa\tGregory\trefa-12345\nDesdemona\tJohnson\trefa-67890\n```\n\nIf for some reason all our authors have the same face and photo, we can even specify this at runtime with a merge value (ee [Merge and default values](#user-content-merged-and-default-values)):\n\n```\ncfimp -space:12345 -model:authors -locale:en-GB -mergevals:authoBioPhoto=refa-12345\n```\n\n## Merged and default values\n\nIt's possible to specify default fallback values for your data, which will take effect if the cell is empty for that field.\n\nIt's also possible to merge extra data into all rows.\n\nLet's say you have a field in your data, \"popular\", with some rows having \"yes\" as a value. For all others, with no value, you want to insert \"no\". We can accomplish this via the `dfltvals` [argument](#user-content-usage):\n\n```\ncfimp -space:12345 -model:authors -locale:en-GB -dfltvals:popular=no\n```\n\nOr let's say you want to add an extra field to all rows. Perhaps you meant (but forgot) to add an \"age\" column to your spreadsheet data before exporting it, and it so happens that, surprisingly, all the authors in your data are 51. We can accomplish this via the `mergevals` [argument](#user-content-usage):\n\n```\ncfimp -space:12345 -model:authors -locale:en-GB -mergevals:age=51\n```\n\n## Updating existing items\n\n\u003e **Be careful** when updating existing items; be sure to specify values for all fields, because Contentful's import service doesn't retain values for omitted fields.\n\ncfimp can be used to update existing items in Contentful rather than import (create) new ones. To do this, include an `_id` column in your data. This will be inferred as the internal Contentful ID of the item, and will update it.\n\n```\nforename\tsurname\t_id\nPhilippa\tGregory\t12345\n```\n\n## Multiple locales\n\nAll data in Contentful is stored against locales, created by you in Contentful. This allows you to have multiple versions of each piece of data, for different locales. By default, cfimp will import/update data using the locale specified in the `locale` arg.\n\nHowever you can import/update multiple locales at once. To do so, specify the field as many times as you have locales, with each additional one appended with a locale flag.\n\nSo if your data was:\n\n```\nLondon\tLondres\nBerlin\tBerlina\n```\n\nYou can spefify locales either in the data itself, if the first row of data represents your field IDs:\n\n```\ncity\tcity[es-SP]\nLondon\tLondres\nBerlin\tBerlina\n```\n\n...or via the `fields` argument, if you're specifying field IDs at runtime.\n\n```\ncfimp -space:12345 -model:cities -locale:en-GB -fields:city,city[es-SP]\n```\n\n## Tagging items\n\nIt's possible to tag items to (existing) tags when importing or updating items. There are two ways to do this.\n\nYou can specify item-specific tags in your data, via the `_tags` field.\n\n```\nforename\tsurname\t_tags\nPhilippa\tGregory\tfoo,bar\n```\n\nYou can also tag *all* items at runtime via the `tagall` argument.\n\n```\ncfimp -space:12345 -model:authors -tagall:foo,bar\n```\n\nNote: tags specified in this way are subject to the `listdelim` [argument](#user-content-usage).\n\n## Importing geopositional data\n\nWhen importing geopositional data, specify coordinates in the format\n\n```\nlat,lng\n```\n\ni.e.\n\n```\n51.467283887530094,-0.24193970047025806\n```\n\ncfimp will convert this into an object before writing to Contentful. Note also that this means you'll need to use a non-comma value for `delim`, since the geoposition data itself contains a comma.\n\n## Filtering rows\n\nIt's possible to stipulate which rows you do, or do not, want to be imported/updated from your input file, via the `skiprows` argument.\n\nThis argument is used to whitelist or blacklist certain rows, and accepts a com-sep list of values to blacklist or, if the entire argument value is prefixed with `!`, to allow.\n\nThe following will blacklist (skip) any rows that contain, in any column, \"foo\" OR \"bar\"\n\n```\ncfimp ... -skiprows:foo,bar\n```\n\nThe following will whitelist (include) any rows that contain \"foo\" OR \"bar\"; all other rows will be skipped.\n\n```\ncfimp ... -skiprows:!foo,bar\n```\n\n## Publishing entries\n\ncfimp can publish entries when importing or updating them. To stipulate this, pass the `publish` [argument](#user-content-usage). If this is omitted, the entry will end up in draft status or, for updated entries, whatever its current status is.\n\nNote that, when importing *and* publishing new items, cfimp will generate item IDs itself, rather than leave it to Contentful. This is a requirement of Contentful's import tool; in order to publish items, it requires an ID to be generated by the client.\n\nSuch IDs will be formed of 11 randomly alphanumeric characters.\n\n## Delimiter overrides\n\nDelimiters are factors in two areas of cfimp:\n\n- the delimiter used to separate the values in your input file\n- the delimiter used to separate any (normally) comma-separated pairings in arguments or `_tag` field values\n\nBoth of these can be overriden - the former via the `delim` arg and the latter via the `listdelim` arg. Note that `listdelim` will apply to **all** occasions where cfimp is attempting to decipher something that it normally expects to be in com-sep format - so for example `_tags` fields, the `mergevals` [argument](#user-content-usage), and so on.\n\n## Troubleshooting\n\nIt's HIGHLY recommended to **preview the generated data** before running the actual import/data. This shows you what cfimp intends to send to Contentful for import/update.\n\nThis can be done in two ways:\n\n- Via the `preview` argument: this should be considered preview 'lite', and will spit out in the console the data cfimp has compiled, before converting to the JSON format Contentful requires\n- Via the `previewfile` argument: this goes a step further, and actually creates the JSON file Contentful requires that effects the import/update. Once created, you can inspect this file.\n\n(Note: Neither argument expects a value.)\n\nAdditionally, a limit is handy in order to avoid numerous terminal screens of data.\n\nIf you find cfimp is deriving or malformed bad data, **check the `delim` and `listdelim`** args.\n\n## Like this?\n\nIf I've helped you, consider being amazing and [buying me a coffee](https://ko-fi.com/mitya) - thank you!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitya33%2Fcfimp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmitya33%2Fcfimp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitya33%2Fcfimp/lists"}