{"_id":"@dannalytics/tessellon","name":"@dannalytics/tessellon","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@dannalytics/tessellon","version":"1.0.0","license":"MIT","author":{"name":"Joshua","email":"developer@dannalytics.com","url":"JD"},"repository":{"type":"git","url":"git+https://gitlab.com/dannalytics/tessellon.git"},"bugs":{"url":"https://gitlab.com/dannalytics/tessellon/-/issues"},"type":"module","packageManager":"npm@11.9.0","description":"A tiny TypeScript loader for platform-specific modules.","keywords":["typescript","esm","commonjs","loader","platform"],"sideEffects":false,"main":"./dist/cjs/index.js","module":"./dist/esm/index.js","types":"./dist/esm/index.d.ts","exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js","default":"./dist/esm/index.js"}},"scripts":{"build":"ts-node --project tsconfig.scripts.json --esm scripts/build.ts","lint":"eslint src scripts test/runtime.test.ts test/types/shared.ts eslint.config.ts","test":"npm run build && npm run test:runtime && npm run test:types && npm run test:exports && npm run test:ts-node","prepack":"npm run build","prepublishOnly":"npm run lint && npm test","pack:dry-run":"npm pack --dry-run","publish:dry-run":"npm publish --dry-run","test:runtime":"vitest run","test:types":"ts-node --project tsconfig.scripts.json --esm scripts/run-type-tests.ts","test:exports":"ts-node --project tsconfig.scripts.json --esm scripts/test-package-exports.ts","test:ts-node":"ts-node --project tsconfig.scripts.json --esm scripts/test-ts-node-consumers.ts","verify:release-tag":"ts-node --project tsconfig.scripts.json --esm scripts/verify-release-tag.ts"},"devDependencies":{"@eslint/js":"^10.0.1","@types/node":"^24.13.3","eslint":"^10.6.0","jiti":"^2.7.0","ts-node":"^10.9.2","typescript":"^5.9.3","typescript-eslint":"^8.63.0","vitest":"^3.2.4"},"gitHead":"b5c0da782fc2f3f41bac33e3333aa95ff8df8d32","_id":"@dannalytics/tessellon@1.0.0","homepage":"https://gitlab.com/dannalytics/tessellon#readme","_nodeVersion":"24.18.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-HYBKIOLpncLXurgeMGvGD1PPPoNAaljg6GcbqFrRP4vcyAjaOYMD2EK1p31xpxgajNAvTAj7GqHtDpuHGjDOpg==","shasum":"6a0a37d5261cdcc5dba3471beeace9ab2c7ef787","tarball":"https://registry.npmjs.org/@dannalytics/tessellon/-/tessellon-1.0.0.tgz","fileCount":28,"unpackedSize":41278,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFtwIpiGa+U6f4GspEMO6qNjgWuoojvGSdboMk9Km2ciAiEAv/28ge+xQlbIvTP/W52RStfTqD3p/ZDDcEQ4oqyohr0="}]},"_npmUser":{"name":"jdannemann","email":"developer@dannalytics.com"},"directories":{},"maintainers":[{"name":"jdannemann","email":"developer@dannalytics.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tessellon_1.0.0_1783655684500_0.9286992693738616"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-10T03:54:44.305Z","1.0.0":"2026-07-10T03:54:44.641Z","modified":"2026-07-10T03:54:44.874Z"},"maintainers":[{"name":"jdannemann","email":"developer@dannalytics.com"}],"description":"A tiny TypeScript loader for platform-specific modules.","homepage":"https://gitlab.com/dannalytics/tessellon#readme","keywords":["typescript","esm","commonjs","loader","platform"],"repository":{"type":"git","url":"git+https://gitlab.com/dannalytics/tessellon.git"},"author":{"name":"Joshua","email":"developer@dannalytics.com","url":"JD"},"bugs":{"url":"https://gitlab.com/dannalytics/tessellon/-/issues"},"license":"MIT","readme":"# Tessellon\n\nA true tessellation only works when each shape fits the shapes around it.\nTessellon (pronounced _TES-uh-lon_) is a particle-sized metaphor for that kind of fit: a small unit of\ncompatibility between a platform's private shape and the shared surface an\napplication can rely on.\n\nTessellon is a tiny TypeScript loader for platform-specific modules.\n\nYou define the platform enum, module-kind enum, shared module shape, proxy, and\nloader table. Tessellon keeps those pieces wired together without requiring the\nshared surface to pretend every platform is the same.\n\nThe package publishes both ESM and CommonJS artifacts. Modern TypeScript and\nbundler consumers use the package `import` condition, while CommonJS consumers\nuse the package `require` condition.\nBoth artifacts target ES2015 and require native `Proxy`, `Reflect`, `Symbol`,\nand `Promise` support.\n\n## Installation\n\n```sh\nnpm install @dannalytics/tessellon\n```\n\n## Releasing\n\nReleases are published by the GitLab tag pipeline. A release tag must match the\npackage version exactly, such as `v1.0.0` for package version `1.0.0`.\n\nSee [docs/releasing.md](docs/releasing.md) for the GitLab and npm setup.\n\n## Core Concepts\n\nTessellon keeps a small relationship intact:\n\n- A platform enum is the runtime vocabulary your application accepts after\n  validating host input.\n- A module kind identifies one shared module shape, such as `NetworkModule` or\n  `PreferencesModule`.\n- A loader table maps each platform enum value to a loader for that module kind.\n- A stable proxy is the object dependent code imports. Loading initializes that\n  proxy with the selected platform implementation.\n- A `ResultShape` reports load success or failure as data instead of making\n  expected loader failures a throwing protocol.\n\nBrowser, device, or host detection belongs at the application boundary. Read the\nunknown host value once, validate it against your platform enum, then pass the\nvalidated platform value to Tessellon.\n\n## Example\n\nDefine the vocabulary your application owns:\n\n```ts\nimport {\n  createModuleProxy,\n  defineTessellon,\n} from \"@dannalytics/tessellon\";\n\nexport enum BrowserPlatform {\n  MicrosoftEdge = \"microsoft-edge\",\n  GoogleChrome = \"google-chrome\",\n}\n\nconst browserPlatforms = new Set<string>(Object.values(BrowserPlatform));\n\nexport const isBrowserPlatform = (\n  value: unknown,\n): value is BrowserPlatform => {\n  return typeof value === \"string\" && browserPlatforms.has(value);\n};\n\nexport enum ModuleKind {\n  Network = \"network\",\n  Preferences = \"preferences\",\n}\n\nexport interface NetworkModule {\n  readonly name: string,\n  requestText(url: string): Promise<string>,\n}\n\nexport interface PreferencesModule {\n  readonly name: string,\n  getPreference(key: string): Promise<string | undefined>,\n  setPreference(key: string, value: string): Promise<void>,\n}\n\nexport const network = createModuleProxy<NetworkModule>({\n  kind: ModuleKind.Network,\n});\n\nexport const preferences = createModuleProxy<PreferencesModule>({\n  kind: ModuleKind.Preferences,\n});\n```\n\nRegister a loader table for each module kind:\n\n```ts\nexport const networks = defineTessellon({\n  moduleKinds: ModuleKind,\n  kind: ModuleKind.Network,\n  platforms: BrowserPlatform,\n  proxy: network,\n})({\n  loaders: {\n    [BrowserPlatform.MicrosoftEdge]: async () => {\n      const module = await import(\"./platforms/microsoft-edge/network\");\n      return module.default;\n    },\n    [BrowserPlatform.GoogleChrome]: async () => {\n      const module = await import(\"./platforms/google-chrome/network\");\n      return module.default;\n    },\n  },\n});\n\nexport const preferenceStores = defineTessellon({\n  moduleKinds: ModuleKind,\n  kind: ModuleKind.Preferences,\n  platforms: BrowserPlatform,\n  proxy: preferences,\n})({\n  loaders: {\n    [BrowserPlatform.MicrosoftEdge]: async () => {\n      const module = await import(\n        \"./platforms/microsoft-edge/preferences\"\n      );\n      return module.default;\n    },\n    [BrowserPlatform.GoogleChrome]: async () => {\n      const module = await import(\n        \"./platforms/google-chrome/preferences\"\n      );\n      return module.default;\n    },\n  },\n});\n```\n\nLoad multiple module kinds from a validated runtime platform value:\n\n```ts\nconst platform = window.__TESSELLON_PLATFORM__;\n\nif (!isBrowserPlatform(platform)) {\n  reportUnsupportedPlatform(platform);\n  return;\n}\n\nconst [networkLoad, preferencesLoad] = await Promise.all([\n  networks.load(platform),\n  preferenceStores.load(platform),\n]);\n\nif (!networkLoad.success) {\n  reportLoadFailure(networkLoad.error);\n  return;\n}\n\nif (!preferencesLoad.success) {\n  reportLoadFailure(preferencesLoad.error);\n  return;\n}\n\nconsole.log(\n  `Loaded ${network.name} and ${preferences.name}.`,\n);\n\nawait network.requestText(\"/status\");\nawait preferences.setPreference(\"theme\", \"dark\");\n```\n\nDependent code imports the stable proxy for the module kind. Platform\nimplementations can be plain objects, instances, or class/static-side objects as\nlong as they fit the registered module shape. Extra platform-specific members\nstay outside Tessellon's shared contract unless you put them in the registered\nshape yourself.\n\nThe default proxy helper returns `undefined` for module members before\ninitialization. Load the module kind before using its proxy.\n\nHotloading is disabled by default. After a successful load, calling `load` again\nwith the same platform returns the existing proxy without running the loader\nagain. Calling `load` for a different platform returns a `hotload-disabled`\nfailure unless the module kind was configured with `hotloadEnabled: true`.\n\n## ts-node\n\nTessellon works through normal package exports in `ts-node`. Use the same import\npath as a bundled TypeScript application:\n\n```ts\nimport {\n  createModuleProxy,\n  defineTessellon,\n} from \"@dannalytics/tessellon\";\n```\n\nFor CommonJS-style `ts-node` consumers:\n\n```ts\nimport tessellon = require(\"@dannalytics/tessellon\");\n```\n\n## License\n\nMIT. Copyright (c) 2026 Joshua (JD) Dannemann.\n","readmeFilename":"README.md","_rev":"1-7185b803f46afd583906ee2b6d5710f0"}