{"id":19281263,"url":"https://github.com/zouloux/crafter","last_synced_at":"2025-02-23T22:19:09.812Z","repository":{"id":53211805,"uuid":"521310228","full_name":"zouloux/crafter","owner":"zouloux","description":"Scaffold code quickly from CLI","archived":false,"fork":false,"pushed_at":"2022-08-05T09:20:38.000Z","size":547,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-06T03:03:51.902Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zouloux.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-04T15:01:43.000Z","updated_at":"2022-08-04T15:33:14.000Z","dependencies_parsed_at":"2022-08-28T05:40:52.610Z","dependency_job_id":null,"html_url":"https://github.com/zouloux/crafter","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/zouloux%2Fcrafter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fcrafter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fcrafter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zouloux%2Fcrafter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zouloux","download_url":"https://codeload.github.com/zouloux/crafter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240385725,"owners_count":19793062,"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-09T21:22:10.387Z","updated_at":"2025-02-23T22:19:09.770Z","avatar_url":"https://github.com/zouloux.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# crafter\n\nCrafter is configurable and powerful file scaffolder written in Node.\nIt can scaffold pretty much any ASCII file.\n\nCrafter is based on :\n- NodeJS\n- [@zouloux/cli](https://github/zouloux/cli) to ask questions\n- [@zouloux/files](https://github/zouloux/files) for file manipulations\n- [stach](https://github/zouloux/stach) for templating\n\n![](./crafter-screencap.gif)\n\n### Install\n\n`npm i -D @zouloux/crafter`\n\n### Usage\n\n```bash\ncraft $CRAFTER_PATH $APP_PATH\ncraft ./crafters/reflex/reflex-crafter.js ./src/my-app/\n```\n\n### In package scripts\n\n```json\n{\n  \"scripts\" : {\n\t\"craft-reflex\": \"craft ./crafters/reflex/reflex-crafter.js ./src/front/\",\n\t\"craft-route\": \"craft ./crafters/fastify/fastify-crafter.js ./src/back/\"\n  }\n}\n```\n\n### Crafter file\n\nA Crafter file is a JS file which create craft actions.\nCraft actions create a menu for the user. A craft action can ask user questions and scaffold files from those questions.\n\n`crafters/reflex-crafter.js`\n```tsx\nimport { askInput } from \"@zouloux/cli\"\n\n// createCraftAction( crafterID:string, menuEntry:string, async (crafterRoot?:string, appPath?:string, env?:TEnv) =\u003e { ... } )\ncreateCraftAction('symbol', 'Symbol (icons / logos ...)', async (craft, crafterRoot, appPath, env) =\u003e {\n\t// Ask user for category name\n\tconst category = await askInput(\n\t\t// Uses nicePrint to style text, @see https://github.com/zouloux/cli/blob/main/src/Output.ts#L67\n\t\t// {u} -\u003e underline\n\t\t// {/} -\u003e remove previous styling\n\t\t// {d} -\u003e dim\n\t\t`Symbol {u}c{/}ategory folder ? {d}(use plural) ex: icons, logos ...`,\n\t\t{ shortcuts: ['category', 'cat', 'c'], notEmpty: true }\n\t);\n\t// Ask user for symbol name\n\tconst name = await askInput(\n\t\t`Symbol {u}n{/}ame ? {d}(use CamelCase, with category as suffix) ex : HomeIcon, BrandLogo, ...`,\n\t\t{ shortcuts: ['name', 'n'], notEmpty: true }\n\t);\n\t// Scaffold with those parameters\n\t// craft \u003cGVars extends object\u003e( vars:GVars, steps:TStep\u003cGVars\u003e[] )\n\tcraft({\n\t\t// Those will be avaible in source template\n\t\tcategory: category.toLowerCase(),\n\t\tname: lowerCaseFirst( name ),\n\t\tName: upperCaseFirst( name ),\n\t}, [\n\t\tvars =\u003e [\n\t\t\t// Source is templated with vars given\n\t\t\t// relative to $CRAFTER_PATH from cli\n\t\t\t`1-symbols/Name.tsx.template`,\n\t\t\t// And templated file is written here\n\t\t\t// relative to $APP_PATH from cli\n\t\t\t`1-symbols/${vars.category}/${vars.Name}.tsx`\n\t\t],\n\t\t// Can have other steps (other files templated)\n\t\tvars =\u003e [\n\t\t\t// ...\n\t\t]\n\t])\n})\n```\n\nStep can also be a custom async function without auto-templating\n\n```tsx\ncreateCraftAction('app', 'App', async (craft, crafterRoot, appPath, env) =\u003e {\n\t// Ask user questions\n\t// ...\n\tcraft({\n\t\tname: lowerCaseFirst( name )\n\t}, [\n\t\t// A step can be custom if it does not return a tuple\n\t\t// Custom step ( no auto-templating, do anything you want using cli and files )\n\t\tasync (vars) =\u003e {\n\t\t\t// Check if app already exists\n\t\t\tif ( await FileFinder.exists( appPath ) )\n\t\t\t\tthrow new Error(`Reflex crafter, app ${vars.name} already exists`)\n\t\t\t// Clone app template with all directories\n\t\t\tconst appTemplate = new Directory( path.join(crafterPath, '_app') )\n\t\t\tconst children = await appTemplate.children('all', { dot: true })\n\t\t\tfor ( const child of children )\n\t\t\t\tawait child.copyTo( appPath )\n\t\t\t// Remove all gitkeeps\n\t\t\tconst gitKeeps = await FileFinder.find('file', `src/**/.gitkeep`, { dot: true })\n\t\t\tfor ( const gitKeep of gitKeeps )\n\t\t\t\tawait gitKeep.delete()\n\t\t}\n\t])\n})\n```\n\n### Templates\n\nThose files are templated with `vars` thanks to [stach](https://github.com/zouloux/stach).\nTemplate delimiters are `{{varName}}`\n\n`crafter/1-symbols/Name.tsx.template`\n\n```tsx\nimport { h, DefaultReflexProps } from \"@zouloux/reflex\";\n\ninterface Props extends DefaultReflexProps {\n\n}\n\nexport function {{Name}} ( props:Props ) {\n\treturn \u003csvg fill=\"currentColor\" viewBox=\"0 0 40 40\"\u003e\u003c/svg\u003e\n}\n```\n\n### Examples\n\nSee examples here : \n- [Simple crafter example](./examples/simple)\n\nTo test example :\n```\ngit clone https://github.com/zouloux/crafter\ncd examples/simple\nnpm i\nnpm run craft\n```\n\n### Legacy module loading\n\nIn case you have this error \n`(node:56647) Warning: To load an ES module, set \"type\": \"module\" in the package.json or use the .mjs extension.`\n\nAdd `\"type\": \"module\"` to your `package.json`\n\nIf this is not possible, use `craft-legacy` instead of `craft` in your `package.json` scripts.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzouloux%2Fcrafter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzouloux%2Fcrafter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzouloux%2Fcrafter/lists"}