{"id":25420051,"url":"https://github.com/frlow/brine","last_synced_at":"2026-04-11T00:03:23.661Z","repository":{"id":64460292,"uuid":"512838407","full_name":"frlow/brine","owner":"frlow","description":null,"archived":false,"fork":false,"pushed_at":"2023-05-31T19:17:18.000Z","size":2158,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"next","last_synced_at":"2025-04-21T20:06:47.879Z","etag":null,"topics":["build-tools","component-library","custom-elements","javascript","react","svelte","typescript","vue3","web-components"],"latest_commit_sha":null,"homepage":"","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/frlow.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}},"created_at":"2022-07-11T16:51:23.000Z","updated_at":"2024-01-12T18:33:08.000Z","dependencies_parsed_at":"2023-02-14T17:15:20.564Z","dependency_job_id":null,"html_url":"https://github.com/frlow/brine","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/frlow%2Fbrine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Fbrine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Fbrine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frlow%2Fbrine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frlow","download_url":"https://codeload.github.com/frlow/brine/tar.gz/refs/heads/next","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253850767,"owners_count":21973666,"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":["build-tools","component-library","custom-elements","javascript","react","svelte","typescript","vue3","web-components"],"created_at":"2025-02-16T19:22:43.967Z","updated_at":"2025-12-30T22:38:19.332Z","avatar_url":"https://github.com/frlow.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# brine\n\nBrine is a set of tools for creating web components by wrapping applications written in popular frameworks.\n\nIt enables developers to write components in their favourite framework and use them in any other project, regardless of\nwhat framework is used there.\n\nMore on the power of web components [here](https://www.webcomponents.org/introduction)\n\nCurrently, brine supports the following frameworks\n\n- \u003cimg src=\"https://static.cdnlogo.com/logos/r/63/react.svg\" alt=\"react\" width=\"15\"/\u003e React\n- \u003cimg src=\"https://static.cdnlogo.com/logos/v/69/vue.svg\" alt=\"vue\" width=\"15\"/\u003e Vue\n- \u003cimg src=\"https://static.cdnlogo.com/logos/s/6/svelte.svg\" alt=\"svelte\" width=\"15\"/\u003e Svelte\n- \u003cimg src=\"https://www.solidjs.com/img/logo/without-wordmark/logo.png\" alt=\"solid\" width=\"15\"/\u003e Solid\n\n## Install\n\n```\nnpm install --save brinejs\n```\n\n## Usage\n\nbrine consists of 2 separate layers and a meta object\n\n- the wrapper, this is th web component that wraps around the framework code\n- the options object, the internals that contain the framework specific code\n- the meta object, contains metadata required to create thw component\n\n### Examples\n\n***react***\n\n```typescript\nimport { define } from 'brinejs/react'\nimport App from './App'\n\ndefine(App, {\n    emits: [\"change\"],\n    attributes: [\"text\", \"header\"],\n    style: `.dummy-style{}`,\n    tag: 'my-react-app',\n})\n\n```\n\n***vue***\n\n```typescript\nimport {createOptions} from 'brinejs/vue'\nimport App from './App.vue'\n```\n\n***svelte***\n\n```typescript\nimport {createOptions} from 'brinejs/svelte'\nimport App from './App.svelte'\n```\n\n***solid js***\n\n```typescript\nimport {createOptions} from 'brinejs/solid'\nimport App from './App'\n```\n\n## Build tools\n\nBrine contains some helper functions that makes building and bundling\nsimpler.\n\n***hot component transplant***\n\nHot component transplant server is a websocket server that allows developers\nto automatically transplant components during development or debugging. \n\n```typescript\n// build script\nimport {startHotComponentTransplantServer} from 'brinejs/build'\n\nconst hotTransplant = startHotComponentTransplantServer()\nconst build = () =\u003e {\n    // ... some build code\n    hotTransplant(['path/to/some/file/that/changed.js'])\n}\n```\n\n```typescript\n// in browser\nnew WebSocket('ws://localhost:8080').onmessage = \n    async (ev) =\u003e {import(ev.data+'?t='+Date.now())}\n```\n\n***boilerplate generation***\n\nBrine has two code generation methods, 'writeMetaFile' and 'writeIndexFile'.\nThey can be used to generate boilerplate code, specifically the meta\nobject that describes the component.\n\n#### meta file\n\n```typescript\n// Generate meta file\nimport {writeMetaFile} from '/brine'\n\nawait writeMetaFile('App.tsx', 'my') // (filePath, prefix or filename)\n```\n\n```typescript\n// output\n// App.meta.ts\nexport const meta = {\n    emits: [\"my-click\"],\n    attributes: [\"count\", \"text\", \"obj\"],\n    style: `.dummy-style{}`,\n    tag: 'my-app',\n}\n```\n\n#### index file\n\n```typescript\n// Generate meta file\nimport {writeIndexFile} from '/brine'\n\nawait writeIndexFile('App.tsx', 'my') // (filePath, prefix or filename)\n```\n\n```typescript\n// output\n// index.ts\nimport { define } from 'brinejs/react'\nimport App from './SolidApp.js'\n\ndefine(App, {\n    emits: [] as string[],\n    attributes: [\"count\"] as string[],\n    style: `.dummy-style{}` as string,\n    tag: 'my-solid-app' as string,\n})\n\n```\n\n***css injection***\n\nMost builders produce separate js and css files as build output.\nSince the styling needs to be in the code, this styling must be injected into\nthe code somehow.\n\nBrine has a helper method that can modify a bundled js file and inject css\ninto it. It also updates and adjusts the source map to match the\nnew content.\n\n```typescript\nimport {writeJsMapCssGroup, groupJsMapCssFiles} from '/brine'\n\nconst groupedFiles = groupJsMapCssFiles(['./dist/App.js'])\nawait writeJsMapCssGroup(groupedFiles)\n```\n\n***type documentation***\n\nType documentation can be extracted and generated for the components\n\n```typescript\nimport {\n  generateTypes,\n  writeTypesFile,\n  writeVsCodeTypes,\n  writeWebTypes\n} from 'brine'\n\nconst types = await generateTypes(['src/App.tsx'], 'my')\n// json file with serialized typing\nawait writeTypesFile(types, 'dist')\n\n// vscode.html-custom-data.json (VsCode)\nawait writeVsCodeTypes(types, 'dist')\n\n// web-types.json (JetBrains, IntelliJ/WebStorm)\nawait writeWebTypes(types, 'dist', {\n  name: 'example',\n  version: '1.0.0',\n})\n\n// react wrappers\nawait writeReactWrappersFile(types, 'dist/wrapper')\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrlow%2Fbrine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrlow%2Fbrine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrlow%2Fbrine/lists"}