{"id":21310149,"url":"https://github.com/samhinton88/code-fold","last_synced_at":"2025-07-11T23:31:17.955Z","repository":{"id":46187178,"uuid":"417514455","full_name":"samhinton88/code-fold","owner":"samhinton88","description":"Write the pattern, then let your code write itself.","archived":false,"fork":false,"pushed_at":"2021-11-08T16:55:21.000Z","size":105,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2023-03-02T18:35:43.811Z","etag":null,"topics":["cli","code-generation","devtools","javascript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/samhinton88.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-15T13:44:28.000Z","updated_at":"2023-01-23T05:51:25.000Z","dependencies_parsed_at":"2022-08-26T19:50:35.322Z","dependency_job_id":null,"html_url":"https://github.com/samhinton88/code-fold","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samhinton88%2Fcode-fold","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samhinton88%2Fcode-fold/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samhinton88%2Fcode-fold/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samhinton88%2Fcode-fold/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samhinton88","download_url":"https://codeload.github.com/samhinton88/code-fold/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225769370,"owners_count":17521258,"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","code-generation","devtools","javascript"],"created_at":"2024-11-21T17:12:34.357Z","updated_at":"2024-11-21T17:12:35.174Z","avatar_url":"https://github.com/samhinton88.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Code Fold\n\nTurn your codebase into an event-driven system.\n\n```\nyarn global add code-fold\n```\nHave you ever thought:\n\n\u003e I just wish that every time I wrote a function in this file, it would just magically write all the boilerplate for a test and an export, and then import it where I want it to be.\n\n`code-fold` could be just the thing you need to explore.\n\nWriting code is often about deciding on a __pattern__ and the time spent __implementing it__ is a function of that pattern, `code-fold` allows you to focus on the pattern, wire your codebase up in the shape of that pattern and let the code write itself.\n\n`code-fold` transforms a codebase into a reactive, event driven system - it sees a change made to code as an event, a message that is emitted to all other parts of the codebase.\n\nA developer can then decide which other parts of the code should change as a result, and `code-fold` will make those changes automatically.\n\n\n## Usage\n### Initialisation\nOnce installed, navigate in your terminal to the top of your codebase and then run:\n```\nunfold\n```\n\n### Syntax\n\n`code-fold` commands currently live with your code and use a JSX-like syntax, placed inside inline comments.\n\n#### Listeners\nListener folds listen for changes to particular types of syntax in locations you point them at:\n```js\n// ./some-file.js\n// \u003cmyFirstFold downstream exported_function /\u003e\n```\nThis fold will listen for any __new__ exported functions in its local directory and any lower directories, and emit an event when this occurs.\n\n`code-fold` runs queries on the ASTs for the files in your codebase, and so can distinguish between, e.g. a new function being written and a function being exported. \n\nThe util recognises all AST types that are recognised by `acorn` and `babel`, lowercased. I heartily recommend [AST Explorer](https://astexplorer.net/) for playing around and getting to know the different types.\n\nTypes in singular form will return the first match in the ast, but they also support simple pluralisation - add an `'s'` to the end of a given type to return all results which match the query. \n\nThere are also a number of aliased types, e.g. `exported_function`, which are layered on top of the exisiting types. These aliases are an ongoing peice of work.\n\nCurrent aliases (add an 's' to the end for the plural verion):\n```\nexported_function\narrow_function_assignment\nexported_async_function\n```\n\nThe `downstream` prop instructs the fold to watch all files in the local directory and any lower directories.\n\nUsing a non-self-closing fold instructs it to listen to only what is between its opening and closing tags.\n```js\n// \u003cmyFirstFold exported_function \u003e\n// Just watch the JavaScript in here!\nexport const foo = () =\u003e {} // \u003c-- this will trigger\n// \u003c/myFirstFold\u003e\nexport const bar = () =\u003e {} // \u003c-- this will not trigger\n```\n\n#### Consumers\nConsumer folds listen for those emitted events and make modifications to the codebase based on those events:\n```js \n// ./some-other-dir/some-other-file.js\n// \u003c*myFirstFold overwrite snippet=\"{{ name }}\"\u003e\n\n// \u003c/*myFirstFold\u003e\n```\nThis fold will fire when `myFirstFold` emits an event, it will then write the names of the downstream exported functions between its opening and closing tags.\n\nThe `snippet` prop allows a developer to write an inline template for whatever new code they want to be added. These templates use HandlebarsJS and are called with data coming through on the event.\n\nSo in the above example, were I to create a new function like this:\n```js\nconst myFilter = (data, predicate) =\u003e data.filter(predicate) \n```\n\nThe consumer would write:\n```js\nmyFilter\n```\n\nConsumers also accept a `where` prop, which allows us to get greater control over when a consumer should do its work.\n\n`where` accepts JavaScript as a string, and will execute it in the context of the data coming through on the event.\n\n```js\n// \u003c*myFirstFold overwrite snippet=\"{{ name }}\" where=\"name.startsWith('user')\"\u003e\n\n// \u003c/*myFirstFold\u003e\n```\n\nThis consumer fold is listening to the same event, but will only write the names of functions that start with the token `user`.\n\nConsumer folds take a number of commands when deciding how to make modifications:\n- `overwrite` \n  - used non-self-closing folds and will overwrite anything between its opening and closing tags.\n- `overwrite_below`\n  - used in self-closing folds and will overwrite everything below\n\n### Tiny Example\nWire up your code:\n```js\n// ./my-math.js\n// \u003cnewFunction arrow_function\u003e\n// \u003c/newFunction\u003e\n\nexport {\n// \u003c*newFunction overwrite snippet={\"{{name}},\"}\u003e\n// \u003c/*newFunction\n}\n```\nMake a change:\n```js\n// ./my-math.js\n// \u003cnewFunction arrow_function\u003e\nconst add = () =\u003e {}\nconst subtract = () =\u003e {}\nconst divide = () =\u003e {}\nconst multiply = () =\u003e {}\n// \u003c/newFunction\u003e\n\nexport {\n// \u003c*newFunction overwrite snippet={\"{{name}},\"}\u003e\n// \u003c/*newFunction\n}\n```\nSave and let `code-fold` write the rest of your code:\n```js\n// ./my-math.js\n// \u003cnewFunction arrow_function\u003e\nconst add = () =\u003e {}\nconst subtract = () =\u003e {}\nconst divide = () =\u003e {}\nconst multiply = () =\u003e {}\n// \u003c/newFunction\u003e\n\nexport {\n// \u003c*newFunction overwrite_below snippet={\"  {{name}},\"}\u003e\n    add,\n    subtract,\n    divide,\n    multiply,\n// \u003c/*newFunction\n}\n```\n## Case Study: index file\n\nOften we'll want to organise functions into directories and then for ease of use export them all from an index file at a higher level.\n\nCopy this into your index file:\n\n```js\n// utils/index.js\n\n// \u003cnewFunctionExportedBelowThis downstream exported_function /\u003e\n// \u003c*newFunctionExportedBelowThis overwrite_below snippet=\"export { {{ name }} } from './{{ relativePath }}'\"/\u003e\n```\n\nAnd `code-fold` will magically find any exported functions below or at the same level as that index, and export them.\n## Case Study: Redux\n\nRedux is a popular, powerful state management system for front-end applications; as developers we enumerate a number of actions which describe the behaviour of the application, and we write types, reducers and action creators as the boilerplate to allow our views to access it.\n\n`code-fold` allows us to declare up front \"for each of my types I need this code\", write the types, and let the code write itself.\n\n```js\n// ./types.js\n// \u003cnewType named_exports\u003e\n// \u003c/newType\u003e\n\n// ./actions/user.js\nimport {\n// \u003c*newType overwrite snippet='  {{name}},' where=\"data.name.startsWith('user')\"\u003e\n// \u003c/*newType\u003e \n} from './types'\n\n// \u003c*newType where=\"data.name.startsWith('user')\" snippet=\"export const {{ name }}Action = (data) =\u003e ({ type: {{ name }}, data })\"\u003e\n// \u003c/*newType\u003e\n\n// ./actions/auth.js\nimport {\n// \u003c*newType overwrite snippet='  {{name}},' where=\"data.name.startsWith('auth')\"\u003e\n// \u003c/*newType\u003e \n} from './types'\n// \u003c*newType where=\"data.name.startsWith('auth')\" snippet=\"export const {{ name }}Action = (data) =\u003e ({ type: {{ name }}, data })\u003e\n// \u003c/*newType\u003e\n```\n\nMake a change.\n\n```js\n// ./types.js\n// \u003cnewType named_exports \u003e\nexport const userCreate = 'userCreate';\nexport const authLogin = 'authLogin';\n// \u003c/newType\u003e\n```\n\nHit save and `code-fold` writes the rest of the code for you in the way you've described it.\n\n```js\n// ./actions/user.js\nimport {\n// \u003c*newType overwrite snippet='  {{name}},' where=\"data.name.startsWith('user')\"\u003e\n    userCreate\n// \u003c/*newType\u003e \n} from './types'\n// \u003c*newType where=\"data.name.startsWith('user')\" snippet=\"export const {{ name }}Action = (data) =\u003e ({ type: {{ name }}, data })\"\u003e\nexport const userCreateAction = (data) =\u003e ({ type: userCreate, data });\n// \u003c/*newType\u003e\n\n// ./actions/auth.js\nimport {\n// \u003c*newType overwrite snippet='  {{name}},' where=\"data.name.startsWith('user')\"\u003e\n    authLogin\n// \u003c/*newType\u003e \n} from './types'\n// \u003c*newType where=\"data.name.startsWith('auth')\" snippet=\"export const {{ name }}Action = (data) =\u003e ({ type: {{ name }}, data })\u003e\nexport const authLoginAction = (data) =\u003e ({ type: authLogin, data });\n// \u003c/*newType\u003e\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamhinton88%2Fcode-fold","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamhinton88%2Fcode-fold","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamhinton88%2Fcode-fold/lists"}