{"_id":"@airplaneglue/pacpacpac","_rev":"2-b0ccc17c089551af69ae0b388e113f26","name":"@airplaneglue/pacpacpac","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.1":{"name":"@airplaneglue/pacpacpac","version":"0.1.1","keywords":[],"author":{"name":"James Conkling","email":"james.lane.conkling@gmail.com"},"license":"ISC","_id":"@airplaneglue/pacpacpac@0.1.1","maintainers":[{"name":"james.lane.conkling","email":"james.lane.conkling@gmail.com"}],"dist":{"shasum":"5f17122b138118f9ae3399dd7b168a5ecc762fc2","tarball":"https://registry.npmjs.org/@airplaneglue/pacpacpac/-/pacpacpac-0.1.1.tgz","fileCount":14,"integrity":"sha512-f38A/Ev3aQWwf0V/dzlynGngU5mrOhObWsvNXMMhou57zLw/liMPNx5Omm7WzFQb7HlkHuTZVoeAIfXhqyoCtA==","signatures":[{"sig":"MEUCIQD8FVwBdtawQY/kcUDlNnvl2B9WuN3V5lb4o8bckuuXtwIgbt8EmSJ0yceayjFNa/5/sYgSS9qoK2VNQpVqXE5RGsE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31377},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","source":"./src/index.ts"}},"gitHead":"7b5ef553057671b93c5f9138f0debd4ba1855563","scripts":{"lint":"eslint .","perf":"tsx perf/benchmark.ts","test":"vitest run","build":"rm -rf dist && tsc -p tsconfig.build.json","lint:fix":"eslint . --fix","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"james.lane.conkling","email":"james.lane.conkling@gmail.com"},"_npmVersion":"11.6.2","description":"simple binary serialization library for the browser","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^5.7.2","@types/node":"^25.0.3"},"_npmOperationalInternal":{"tmp":"tmp/pacpacpac_0.1.1_1766698396871_0.9695156928323028","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@airplaneglue/pacpacpac","version":"0.1.2","type":"module","description":"simple binary serialization library for the browser","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts","source":"./src/index.ts"}},"scripts":{"typecheck":"tsc --noEmit","lint":"eslint .","lint:fix":"eslint . --fix","test":"vitest run","test:watch":"vitest","perf":"tsx perf/benchmark.ts","build":"rm -rf dist && tsc -p tsconfig.build.json"},"keywords":[],"author":{"name":"James Conkling","email":"james.lane.conkling@gmail.com"},"license":"ISC","devDependencies":{"@types/node":"^25.0.3","tsx":"^4.21.0","typescript":"^5.7.2"},"publishConfig":{"access":"public"},"gitHead":"01eb23e12838e2a2bdccf87cf5295fcdc3d61dda","_id":"@airplaneglue/pacpacpac@0.1.2","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-KKB/n/R5jDqVUk4+jbRNuLW/cAuD5hH+7pw6izgtePSZ/frtBl5Cd22jl/+tgkb+8jj2yCKhk8XFDRjxwnQ+6g==","shasum":"976503d86f9d5fa3bf0cc99054e533ade57615dd","tarball":"https://registry.npmjs.org/@airplaneglue/pacpacpac/-/pacpacpac-0.1.2.tgz","fileCount":14,"unpackedSize":30923,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDe6a+UbDOtaDAbv2GcqlczI4z+VkWXYIGhgzctZe6d0QIhAP1JH/+5XGCJK8n/UwGh+boCLHIGyo2nG2ejWlDgNFxZ"}]},"_npmUser":{"name":"james.lane.conkling","email":"james.lane.conkling@gmail.com"},"directories":{},"maintainers":[{"name":"james.lane.conkling","email":"james.lane.conkling@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pacpacpac_0.1.2_1766706553687_0.07104160990937225"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-25T21:33:16.806Z","modified":"2025-12-25T23:49:14.113Z","0.1.1":"2025-12-25T21:33:17.009Z","0.1.2":"2025-12-25T23:49:13.838Z"},"author":{"name":"James Conkling","email":"james.lane.conkling@gmail.com"},"license":"ISC","keywords":[],"description":"simple binary serialization library for the browser","maintainers":[{"name":"james.lane.conkling","email":"james.lane.conkling@gmail.com"}],"readme":"# PacPacPac\n\nLightweight binary encoding of JavaScript objects. PacPacPac is designed to be hard to say and easy to use.\n\nThe target use case is to serialize a small-to-medium-sized state object (< 100kb) in the following scenarios:\n* persisting local state to a browser URL so that it's shareable\n* persisting local state to session storage so that it persists on refresh\n* passing an object to any Browser or Node API that accepts binary data or a string but not an object reference\n\n\n## API\n```ts\ntype encode = <T>(schema: T, obj: TypeFromSchema<T>) => Uint8Array\ntype decode = <T>(schema: T, bytes: Uint8Array) => TypeFromSchema<T>\ntype compress = (bytes: Uint8Array) => Uint8Array\ntype decompress = (bytes: Uint8Array) => Uint8Array\ntype toBase64Url = (bytes: Uint8Array) => string\ntype fromBase64Url = (string: string) => Uint8Array\n\ntype S = {\n  /** 1-byte signed integer (-128 to 127) */\n  smallInt: SmallInt,\n  /** 4-byte signed integer (±2,147,483,647) */\n  int: Int,\n  /** 8-byte signed BigInt (±9,223,372,036,854,775,807) */\n  bigInt: BigInt,\n  /** 4-byte float (32-bit) */\n  float: Float,\n  /** 8-byte double (64-bit) */\n  double: Double,\n  /** Boolean (1 byte) */\n  bool: Boolean,\n  /** Single UTF-16 character (2 bytes) */\n  char: Char,\n  /** Variable-length UTF-8 string */\n  text: Text,\n  /** Enumeration of string values (varint index) */\n  enum: <T extends string[]>(value: T) => Enum<T>,\n  /** Fixed keys with typed values */\n  struct: <T extends Record<string, Schema>>(value: T) => Struct<T>,\n  /** Variable-length homogeneous array */\n  list: <T extends Schema>(value: T) => List<T>,\n}\n```\n\n## Usage\n\nThis example models a Kibana-like analytics dashboard where each panel has a visualization type, query configuration, and layout. Enums are used heavily—they encode as single-byte indices instead of full strings, dramatically reducing payload size.\n\n```ts\nimport { S, encode, decode, compress, decompress, toBase64Url, fromBase64Url } from 'pacpacpac'\n\n// Define the dashboard schema\nconst dashboardSchema = S.struct({\n  id: S.int,\n  title: S.text,\n  timeRange: S.enum(['last15m', 'last1h', 'last6h', 'last24h', 'last7d', 'last30d']),\n  panels: S.list(S.struct({\n    vizType: S.enum(['line', 'bar', 'area', 'pie', 'table', 'metric', 'heatmap']),\n    title: S.text,\n    query: S.struct({\n      index: S.text,\n      aggregation: S.enum(['count', 'sum', 'avg', 'min', 'max', 'median', 'cardinality']),\n      field: S.text,\n      bucketBy: S.enum(['dateHistogram', 'terms', 'histogram', 'range']),\n      interval: S.enum(['auto', '1m', '5m', '15m', '1h', '1d', '1w']),\n    }),\n    style: S.struct({\n      palette: S.enum(['default', 'cool', 'warm', 'status', 'grayscale']),\n      legend: S.enum(['top', 'right', 'bottom', 'left', 'hidden']),\n      showGrid: S.bool,\n    }),\n    layout: S.struct({ x: S.smallInt, y: S.smallInt, w: S.smallInt, h: S.smallInt }),\n  }))\n})\n\n// Example data\nconst dashboard = {\n  id: 42,\n  title: 'System Metrics',\n  timeRange: 'last24h',\n  panels: [{\n    vizType: 'line',\n    title: 'CPU Usage',\n    query: { index: 'metrics-*', aggregation: 'avg', field: 'system.cpu.percent', bucketBy: 'dateHistogram', interval: '5m' },\n    style: { palette: 'cool', legend: 'right', showGrid: true },\n    layout: { x: 0, y: 0, w: 6, h: 4 },\n  }, {\n    vizType: 'area',\n    title: 'Memory Usage',\n    query: { index: 'metrics-*', aggregation: 'avg', field: 'system.memory.percent', bucketBy: 'dateHistogram', interval: '5m' },\n    style: { palette: 'warm', legend: 'right', showGrid: true },\n    layout: { x: 6, y: 0, w: 6, h: 4 },\n  }, {\n    vizType: 'bar',\n    title: 'Top Hosts by Traffic',\n    query: { index: 'logs-*', aggregation: 'sum', field: 'network.bytes', bucketBy: 'terms', interval: 'auto' },\n    style: { palette: 'default', legend: 'hidden', showGrid: false },\n    layout: { x: 0, y: 4, w: 12, h: 3 },\n  }]\n}\n\n// Encode as compressed base64url string\nconst encoded = toBase64Url(await compress(encode(dashboardSchema, dashboard)))\n// Result: 192 chars vs 843 chars for JSON.stringify\n\n// Persist to URL hash\nwindow.location.hash = `state=${encoded}`\n\n// Decode from URL\nconst hash = new URLSearchParams(window.location.hash.slice(1)).get('state')\nconst decoded = decode(dashboardSchema, await decompress(fromBase64Url(hash!)))\n```\n","readmeFilename":"README.md"}