@ebay-dt/bonfire-node 0.1.0-alpha.0 → 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +77 -4
  2. package/dist/agent-service.d.ts +42 -0
  3. package/dist/agent-service.d.ts.map +1 -0
  4. package/dist/agent-service.js +116 -0
  5. package/dist/agent-service.js.map +1 -0
  6. package/dist/claude.d.ts +50 -0
  7. package/dist/claude.d.ts.map +1 -0
  8. package/dist/claude.js +119 -0
  9. package/dist/claude.js.map +1 -0
  10. package/dist/cursor.d.ts +30 -0
  11. package/dist/cursor.d.ts.map +1 -0
  12. package/dist/cursor.js +57 -0
  13. package/dist/cursor.js.map +1 -0
  14. package/dist/deployment-provider.d.ts +32 -0
  15. package/dist/deployment-provider.d.ts.map +1 -0
  16. package/dist/deployment-provider.js +167 -0
  17. package/dist/deployment-provider.js.map +1 -0
  18. package/dist/duplicate.d.ts +3 -2
  19. package/dist/duplicate.d.ts.map +1 -1
  20. package/dist/duplicate.js +18 -18
  21. package/dist/duplicate.js.map +1 -1
  22. package/dist/executable.d.ts +16 -0
  23. package/dist/executable.d.ts.map +1 -0
  24. package/dist/executable.js +65 -0
  25. package/dist/executable.js.map +1 -0
  26. package/dist/git-repository.d.ts.map +1 -1
  27. package/dist/git-repository.js.map +1 -1
  28. package/dist/github-cli.d.ts.map +1 -1
  29. package/dist/github-cli.js +23 -3
  30. package/dist/github-cli.js.map +1 -1
  31. package/dist/index.d.ts +7 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +7 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal/owned-destination.d.ts +2 -2
  36. package/dist/internal/owned-destination.d.ts.map +1 -1
  37. package/dist/internal/owned-destination.js +2 -2
  38. package/dist/internal/owned-destination.js.map +1 -1
  39. package/dist/internal/prototype-templates.d.ts +3 -2
  40. package/dist/internal/prototype-templates.d.ts.map +1 -1
  41. package/dist/internal/prototype-templates.js +13 -8
  42. package/dist/internal/prototype-templates.js.map +1 -1
  43. package/dist/internal/utils.d.ts +2 -0
  44. package/dist/internal/utils.d.ts.map +1 -1
  45. package/dist/internal/utils.js +6 -0
  46. package/dist/internal/utils.js.map +1 -1
  47. package/dist/lifecycle/dirty-state.d.ts.map +1 -1
  48. package/dist/lifecycle/dirty-state.js.map +1 -1
  49. package/dist/lifecycle/local-prototype-lifecycle.d.ts +22 -10
  50. package/dist/lifecycle/local-prototype-lifecycle.d.ts.map +1 -1
  51. package/dist/lifecycle/local-prototype-lifecycle.js +255 -6
  52. package/dist/lifecycle/local-prototype-lifecycle.js.map +1 -1
  53. package/dist/lifecycle/operation-gate.d.ts.map +1 -1
  54. package/dist/lifecycle/operation-gate.js.map +1 -1
  55. package/dist/lifecycle/runtime-context.d.ts.map +1 -1
  56. package/dist/lifecycle/runtime-context.js.map +1 -1
  57. package/dist/preferences.d.ts +19 -0
  58. package/dist/preferences.d.ts.map +1 -0
  59. package/dist/preferences.js +182 -0
  60. package/dist/preferences.js.map +1 -0
  61. package/dist/prepare-prototype-files.d.ts.map +1 -1
  62. package/dist/prepare-prototype-files.js.map +1 -1
  63. package/dist/process-runner.d.ts.map +1 -1
  64. package/dist/process-runner.js.map +1 -1
  65. package/dist/prototype-catalog.d.ts.map +1 -1
  66. package/dist/prototype-catalog.js +18 -7
  67. package/dist/prototype-catalog.js.map +1 -1
  68. package/dist/prototype-paths.d.ts +2 -0
  69. package/dist/prototype-paths.d.ts.map +1 -1
  70. package/dist/prototype-paths.js.map +1 -1
  71. package/dist/scaffold.d.ts +4 -2
  72. package/dist/scaffold.d.ts.map +1 -1
  73. package/dist/scaffold.js +7 -12
  74. package/dist/scaffold.js.map +1 -1
  75. package/dist/watcher.d.ts.map +1 -1
  76. package/dist/watcher.js.map +1 -1
  77. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"prototype-paths.d.ts","sourceRoot":"","sources":["../src/prototype-paths.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAIxC;CACF;AAuID,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,uBAAuB,GAC/B,6BAA6B,CAqB/B"}
1
+ {"version":3,"file":"prototype-paths.d.ts","sourceRoot":"","sources":["../src/prototype-paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAIxC;CACF;AAuID,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,uBAAuB,GAC/B,6BAA6B,CAqB/B","sourcesContent":["import { lstatSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport type { ThemeRegistry } from \"@ebay-dt/bonfire-core\";\n\nconst CONVENTIONAL_PROTOTYPE_ROOT = join(\"src\", \"app\", \"(prototypes)\");\n\nexport type PrototypeCatalogOptions = {\n repositoryRoot: string;\n prototypeRoot?: string;\n themeRegistry?: ThemeRegistry;\n};\n\nexport type ResolvedPrototypeCatalogPaths = {\n repositoryRoot: string;\n prototypeRoot: string;\n};\n\nexport class PrototypeCatalogPathError extends Error {\n readonly path: string;\n\n constructor(path: string, message: string) {\n super(`Invalid prototype catalog path at ${path}: ${message}`);\n this.name = \"PrototypeCatalogPathError\";\n this.path = path;\n }\n}\n\nfunction assertAbsoluteRepositoryRoot(repositoryRoot: unknown) {\n if (typeof repositoryRoot !== \"string\" || !isAbsolute(repositoryRoot)) {\n throw new PrototypeCatalogPathError(\n \"repositoryRoot\",\n \"must be an absolute path\",\n );\n }\n\n return resolve(repositoryRoot);\n}\n\nfunction resolvePrototypeRoot(repositoryRoot: string, prototypeRoot: unknown) {\n if (prototypeRoot === undefined) {\n return join(repositoryRoot, CONVENTIONAL_PROTOTYPE_ROOT);\n }\n if (typeof prototypeRoot !== \"string\" || prototypeRoot.length === 0) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"must be a nonempty path\",\n );\n }\n if (prototypeRoot.split(/[\\\\/]/u).some((segment) => segment === \"..\")) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"must not contain traversal segments\",\n );\n }\n\n return isAbsolute(prototypeRoot)\n ? resolve(prototypeRoot)\n : resolve(repositoryRoot, prototypeRoot);\n}\n\nfunction assertContained(repositoryRoot: string, prototypeRoot: string) {\n const relativePath = relative(repositoryRoot, prototypeRoot);\n if (\n relativePath.length === 0 ||\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath)\n ) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"must be contained within repositoryRoot\",\n );\n }\n}\n\nfunction assertDirectory(path: string, label: string) {\n let stats;\n try {\n stats = lstatSync(path);\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n throw new PrototypeCatalogPathError(label, \"does not exist\");\n }\n throw new PrototypeCatalogPathError(label, \"could not be inspected\");\n }\n\n if (stats.isSymbolicLink()) {\n throw new PrototypeCatalogPathError(label, \"must not be a symbolic link\");\n }\n if (!stats.isDirectory()) {\n throw new PrototypeCatalogPathError(label, \"must be a directory\");\n }\n\n return realpathSync(path);\n}\n\nfunction pathExists(path: string) {\n try {\n lstatSync(path);\n return true;\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"could not be inspected\",\n );\n }\n}\n\nfunction realPathForMissingTarget(path: string) {\n let current = path;\n const missingSegments: string[] = [];\n\n while (!pathExists(current)) {\n const parent = dirname(current);\n if (parent === current) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"could not resolve its existing parent\",\n );\n }\n missingSegments.unshift(current.slice(parent.length + 1));\n current = parent;\n }\n\n let realPath = realpathSync(current);\n for (const segment of missingSegments) realPath = join(realPath, segment);\n return realPath;\n}\n\nfunction assertRealContainment(\n repositoryRealPath: string,\n prototypeRealPath: string,\n) {\n const relativePath = relative(repositoryRealPath, prototypeRealPath);\n if (\n relativePath.length === 0 ||\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath)\n ) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"escapes repositoryRoot through a symbolic link\",\n );\n }\n}\n\nexport function resolvePrototypeCatalogPaths(\n options: PrototypeCatalogOptions,\n): ResolvedPrototypeCatalogPaths {\n const repositoryRoot = assertAbsoluteRepositoryRoot(options?.repositoryRoot);\n const prototypeRoot = resolvePrototypeRoot(\n repositoryRoot,\n options?.prototypeRoot,\n );\n assertContained(repositoryRoot, prototypeRoot);\n\n const repositoryRealPath = assertDirectory(repositoryRoot, \"repositoryRoot\");\n let prototypeRealPath: string;\n\n if (pathExists(prototypeRoot)) {\n prototypeRealPath = assertDirectory(prototypeRoot, \"prototypeRoot\");\n } else if (options?.prototypeRoot !== undefined) {\n throw new PrototypeCatalogPathError(\"prototypeRoot\", \"does not exist\");\n } else {\n prototypeRealPath = realPathForMissingTarget(prototypeRoot);\n }\n\n assertRealContainment(repositoryRealPath, prototypeRealPath);\n return { repositoryRoot, prototypeRoot };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"prototype-paths.js","sourceRoot":"","sources":["../src/prototype-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE9E,MAAM,2BAA2B,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;AAYvE,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,CAAS;IAEtB,YAAY,IAAY,EAAE,OAAe;QACvC,KAAK,CAAC,qCAAqC,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,SAAS,4BAA4B,CAAC,cAAuB;IAC3D,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,yBAAyB,CACjC,gBAAgB,EAChB,0BAA0B,CAC3B,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,cAAc,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,oBAAoB,CAAC,cAAsB,EAAE,aAAsB;IAC1E,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,cAAc,EAAE,2BAA2B,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,yBAAyB,CACjC,eAAe,EACf,yBAAyB,CAC1B,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,yBAAyB,CACjC,eAAe,EACf,qCAAqC,CACtC,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC,aAAa,CAAC;QAC9B,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;QACxB,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,eAAe,CAAC,cAAsB,EAAE,aAAqB;IACpE,MAAM,YAAY,GAAG,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAC7D,IACE,YAAY,CAAC,MAAM,KAAK,CAAC;QACzB,YAAY,KAAK,IAAI;QACrB,YAAY,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;QACnC,UAAU,CAAC,YAAY,CAAC,EACxB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,eAAe,EACf,yCAAyC,CAC1C,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,KAAa;IAClD,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACH,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,KAAK,CAAC,IAAI,KAAK,QAAQ,EACvB,CAAC;YACD,MAAM,IAAI,yBAAyB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,yBAAyB,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,yBAAyB,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,yBAAyB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK;YACL,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,KAAK,CAAC,IAAI,KAAK,QAAQ,EACvB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,eAAe,EACf,wBAAwB,CACzB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,yBAAyB,CACjC,eAAe,EACf,uCAAuC,CACxC,CAAC;QACJ,CAAC;QACD,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1D,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,IAAI,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,KAAK,MAAM,OAAO,IAAI,eAAe;QAAE,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,qBAAqB,CAC5B,kBAA0B,EAC1B,iBAAyB;IAEzB,MAAM,YAAY,GAAG,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;IACrE,IACE,YAAY,CAAC,MAAM,KAAK,CAAC;QACzB,YAAY,KAAK,IAAI;QACrB,YAAY,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC;QACnC,UAAU,CAAC,YAAY,CAAC,EACxB,CAAC;QACD,MAAM,IAAI,yBAAyB,CACjC,eAAe,EACf,gDAAgD,CACjD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,OAAgC;IAEhC,MAAM,cAAc,GAAG,4BAA4B,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,oBAAoB,CACxC,cAAc,EACd,OAAO,EAAE,aAAa,CACvB,CAAC;IACF,eAAe,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAE/C,MAAM,kBAAkB,GAAG,eAAe,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;IAC7E,IAAI,iBAAyB,CAAC;IAE9B,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,iBAAiB,GAAG,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IACtE,CAAC;SAAM,IAAI,OAAO,EAAE,aAAa,KAAK,SAAS,EAAE,CAAC;QAChD,MAAM,IAAI,yBAAyB,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,iBAAiB,GAAG,wBAAwB,CAAC,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,qBAAqB,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;IAC7D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"prototype-paths.js","sourceRoot":"","sources":["../src/prototype-paths.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstatSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport type { ThemeRegistry } from \"@ebay-dt/bonfire-core\";\n\nconst CONVENTIONAL_PROTOTYPE_ROOT = join(\"src\", \"app\", \"(prototypes)\");\n\nexport type PrototypeCatalogOptions = {\n repositoryRoot: string;\n prototypeRoot?: string;\n themeRegistry?: ThemeRegistry;\n};\n\nexport type ResolvedPrototypeCatalogPaths = {\n repositoryRoot: string;\n prototypeRoot: string;\n};\n\nexport class PrototypeCatalogPathError extends Error {\n readonly path: string;\n\n constructor(path: string, message: string) {\n super(`Invalid prototype catalog path at ${path}: ${message}`);\n this.name = \"PrototypeCatalogPathError\";\n this.path = path;\n }\n}\n\nfunction assertAbsoluteRepositoryRoot(repositoryRoot: unknown) {\n if (typeof repositoryRoot !== \"string\" || !isAbsolute(repositoryRoot)) {\n throw new PrototypeCatalogPathError(\n \"repositoryRoot\",\n \"must be an absolute path\",\n );\n }\n\n return resolve(repositoryRoot);\n}\n\nfunction resolvePrototypeRoot(repositoryRoot: string, prototypeRoot: unknown) {\n if (prototypeRoot === undefined) {\n return join(repositoryRoot, CONVENTIONAL_PROTOTYPE_ROOT);\n }\n if (typeof prototypeRoot !== \"string\" || prototypeRoot.length === 0) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"must be a nonempty path\",\n );\n }\n if (prototypeRoot.split(/[\\\\/]/u).some((segment) => segment === \"..\")) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"must not contain traversal segments\",\n );\n }\n\n return isAbsolute(prototypeRoot)\n ? resolve(prototypeRoot)\n : resolve(repositoryRoot, prototypeRoot);\n}\n\nfunction assertContained(repositoryRoot: string, prototypeRoot: string) {\n const relativePath = relative(repositoryRoot, prototypeRoot);\n if (\n relativePath.length === 0 ||\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath)\n ) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"must be contained within repositoryRoot\",\n );\n }\n}\n\nfunction assertDirectory(path: string, label: string) {\n let stats;\n try {\n stats = lstatSync(path);\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n throw new PrototypeCatalogPathError(label, \"does not exist\");\n }\n throw new PrototypeCatalogPathError(label, \"could not be inspected\");\n }\n\n if (stats.isSymbolicLink()) {\n throw new PrototypeCatalogPathError(label, \"must not be a symbolic link\");\n }\n if (!stats.isDirectory()) {\n throw new PrototypeCatalogPathError(label, \"must be a directory\");\n }\n\n return realpathSync(path);\n}\n\nfunction pathExists(path: string) {\n try {\n lstatSync(path);\n return true;\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return false;\n }\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"could not be inspected\",\n );\n }\n}\n\nfunction realPathForMissingTarget(path: string) {\n let current = path;\n const missingSegments: string[] = [];\n\n while (!pathExists(current)) {\n const parent = dirname(current);\n if (parent === current) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"could not resolve its existing parent\",\n );\n }\n missingSegments.unshift(current.slice(parent.length + 1));\n current = parent;\n }\n\n let realPath = realpathSync(current);\n for (const segment of missingSegments) realPath = join(realPath, segment);\n return realPath;\n}\n\nfunction assertRealContainment(\n repositoryRealPath: string,\n prototypeRealPath: string,\n) {\n const relativePath = relative(repositoryRealPath, prototypeRealPath);\n if (\n relativePath.length === 0 ||\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath)\n ) {\n throw new PrototypeCatalogPathError(\n \"prototypeRoot\",\n \"escapes repositoryRoot through a symbolic link\",\n );\n }\n}\n\nexport function resolvePrototypeCatalogPaths(\n options: PrototypeCatalogOptions,\n): ResolvedPrototypeCatalogPaths {\n const repositoryRoot = assertAbsoluteRepositoryRoot(options?.repositoryRoot);\n const prototypeRoot = resolvePrototypeRoot(\n repositoryRoot,\n options?.prototypeRoot,\n );\n assertContained(repositoryRoot, prototypeRoot);\n\n const repositoryRealPath = assertDirectory(repositoryRoot, \"repositoryRoot\");\n let prototypeRealPath: string;\n\n if (pathExists(prototypeRoot)) {\n prototypeRealPath = assertDirectory(prototypeRoot, \"prototypeRoot\");\n } else if (options?.prototypeRoot !== undefined) {\n throw new PrototypeCatalogPathError(\"prototypeRoot\", \"does not exist\");\n } else {\n prototypeRealPath = realPathForMissingTarget(prototypeRoot);\n }\n\n assertRealContainment(repositoryRealPath, prototypeRealPath);\n return { repositoryRoot, prototypeRoot };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type PrototypeRef } from "@ebay-dt/bonfire-core";
1
+ import { type PrototypeRef, type PrototypeTheme, type ThemeRegistry } from "@ebay-dt/bonfire-core";
2
2
  import type { ResolvedPrototypeCatalogPaths } from "./prototype-paths.js";
3
3
  import { type OwnedDestinationResult } from "./internal/owned-destination.js";
4
4
  type SafeWriteFile = (path: string, content: string, options: {
@@ -11,6 +11,8 @@ export type PrototypeScaffoldOptions = {
11
11
  title: string;
12
12
  description: string | null;
13
13
  authorName: string | null;
14
+ theme?: PrototypeTheme;
15
+ themeRegistry?: ThemeRegistry;
14
16
  clock?: () => Date;
15
17
  writeFile?: SafeWriteFile;
16
18
  };
@@ -19,6 +21,6 @@ export declare class PrototypeScaffoldError extends Error {
19
21
  readonly kind: PrototypeScaffoldErrorKind;
20
22
  constructor(kind: PrototypeScaffoldErrorKind);
21
23
  }
22
- export declare function scaffoldPrototype({ paths, ref, title, description, authorName, clock, writeFile, }: PrototypeScaffoldOptions): Promise<OwnedDestinationResult>;
24
+ export declare function scaffoldPrototype({ paths, ref, title, description, authorName, theme, themeRegistry, clock, writeFile, }: PrototypeScaffoldOptions): Promise<OwnedDestinationResult>;
23
25
  export { GENERATED_FILES } from "./internal/prototype-templates.js";
24
26
  //# sourceMappingURL=scaffold.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAC;AAWzC,KAAK,aAAa,GAAG,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,KACtC,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,IAAI,CACT,6BAA6B,EAC7B,gBAAgB,GAAG,eAAe,CACnC,CAAC;IACF,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,0BAA0B,GACpC,WAAW,GAAG,YAAY,GAAG,eAAe,CAAC;AAE/C,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAE1C,YAAY,IAAI,EAAE,0BAA0B,EAI3C;CACF;AAuJD,wBAAsB,iBAAiB,CAAC,EACtC,KAAK,EACL,GAAG,EACH,KAAK,EACL,WAAW,EACX,UAAU,EACV,KAAwB,EACxB,SAA0B,GAC3B,EAAE,wBAAwB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA2F5D;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,iCAAiC,CAAC;AAYzC,KAAK,aAAa,GAAG,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,KACtC,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,IAAI,CACT,6BAA6B,EAC7B,gBAAgB,GAAG,eAAe,CACnC,CAAC;IACF,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,0BAA0B,GACpC,WAAW,GAAG,YAAY,GAAG,eAAe,CAAC;AAE/C,qBAAa,sBAAuB,SAAQ,KAAK;IAC/C,QAAQ,CAAC,IAAI,EAAE,0BAA0B,CAAC;IAE1C,YAAY,IAAI,EAAE,0BAA0B,EAI3C;CACF;AA8ID,wBAAsB,iBAAiB,CAAC,EACtC,KAAK,EACL,GAAG,EACH,KAAK,EACL,WAAW,EACX,UAAU,EACV,KAAK,EACL,aAAa,EACb,KAAwB,EACxB,SAA0B,GAC3B,EAAE,wBAAwB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA4F5D;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["import { constants } from \"node:fs\";\nimport {\n lstat,\n mkdir,\n open,\n rm,\n rmdir,\n writeFile as writeFileAsync,\n} from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport {\n definePrototypeRef,\n parsePrototypeMetadata,\n type PrototypeRef,\n type PrototypeTheme,\n type ThemeRegistry,\n} from \"@ebay-dt/bonfire-core\";\nimport type { ResolvedPrototypeCatalogPaths } from \"./prototype-paths.js\";\nimport {\n captureOwnedDestination,\n type OwnedDestinationResult,\n} from \"./internal/owned-destination.js\";\nimport {\n buildAppCss,\n buildAppTsx,\n buildCssModulesDeclaration,\n buildMetadataJson,\n buildPageTsx,\n buildTsConfig,\n GENERATED_FILES,\n} from \"./internal/prototype-templates.js\";\nimport { isFileNotFound } from \"./internal/utils.js\";\n\ntype SafeWriteFile = (\n path: string,\n content: string,\n options: { encoding: \"utf8\"; flag: \"wx\" },\n) => Promise<void>;\n\nexport type PrototypeScaffoldOptions = {\n paths: Pick<\n ResolvedPrototypeCatalogPaths,\n \"repositoryRoot\" | \"prototypeRoot\"\n >;\n ref: PrototypeRef;\n title: string;\n description: string | null;\n authorName: string | null;\n theme?: PrototypeTheme;\n themeRegistry?: ThemeRegistry;\n clock?: () => Date;\n writeFile?: SafeWriteFile;\n};\n\nexport type PrototypeScaffoldErrorKind =\n \"collision\" | \"filesystem\" | \"invalid-input\";\n\nexport class PrototypeScaffoldError extends Error {\n readonly kind: PrototypeScaffoldErrorKind;\n\n constructor(kind: PrototypeScaffoldErrorKind) {\n super(`Prototype scaffold failed: ${kind}`);\n this.name = \"PrototypeScaffoldError\";\n this.kind = kind;\n }\n}\n\nfunction destinationFor(prototypeRoot: string, ref: PrototypeRef) {\n const normalizedRef = definePrototypeRef(ref);\n return join(prototypeRoot, normalizedRef.login, normalizedRef.slug);\n}\n\nasync function assertDirectory(path: string) {\n try {\n const stats = await lstat(path);\n if (stats.isSymbolicLink() || !stats.isDirectory()) {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n } catch (error) {\n if (error instanceof PrototypeScaffoldError) throw error;\n if (isFileNotFound(error)) return;\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nasync function ensureDirectory(path: string) {\n try {\n await mkdir(path, { recursive: true });\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n await assertDirectory(path);\n}\n\ntype OwnedPath = {\n path: string;\n device: number;\n inode: number;\n};\n\nasync function ownedPath(path: string): Promise<OwnedPath> {\n const stats = await lstat(path);\n return { path, device: stats.dev, inode: stats.ino };\n}\n\nasync function reserveDestination(\n path: string,\n paths: Pick<\n ResolvedPrototypeCatalogPaths,\n \"repositoryRoot\" | \"prototypeRoot\"\n >,\n) {\n try {\n await mkdir(path);\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"EEXIST\"\n ) {\n throw new PrototypeScaffoldError(\"collision\");\n }\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n\n try {\n return await captureOwnedDestination({\n path,\n repositoryRoot: paths.repositoryRoot,\n prototypeRoot: paths.prototypeRoot,\n });\n } catch {\n // The newly created path is retained because ownership was not proven.\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nasync function createDirectory(path: string) {\n try {\n await mkdir(path);\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n await assertDirectory(path);\n return ownedPath(path);\n}\n\nasync function writeNewFile(\n path: string,\n content: string,\n writeFile: SafeWriteFile,\n) {\n try {\n await writeFile(path, content, { encoding: \"utf8\", flag: \"wx\" });\n return await ownedPath(path);\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nasync function readWrittenMetadata(path: string) {\n const file = await open(\n path,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),\n );\n try {\n return await file.readFile(\"utf8\");\n } finally {\n await file.close();\n }\n}\n\nasync function removeIncompleteDestination(\n files: readonly OwnedPath[],\n directories: readonly OwnedPath[],\n) {\n try {\n for (const owned of [...files].reverse()) {\n const current = await lstat(owned.path).catch(() => null);\n if (\n current !== null &&\n !current.isSymbolicLink() &&\n current.dev === owned.device &&\n current.ino === owned.inode\n ) {\n await rm(owned.path, { force: true });\n }\n }\n\n for (const owned of [...directories].reverse()) {\n const current = await lstat(owned.path).catch(() => null);\n if (\n current !== null &&\n current.isDirectory() &&\n !current.isSymbolicLink() &&\n current.dev === owned.device &&\n current.ino === owned.inode\n ) {\n await rmdir(owned.path);\n }\n }\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nexport async function scaffoldPrototype({\n paths,\n ref,\n title,\n description,\n authorName,\n theme,\n themeRegistry,\n clock = () => new Date(),\n writeFile = writeFileAsync,\n}: PrototypeScaffoldOptions): Promise<OwnedDestinationResult> {\n const normalizedRef = definePrototypeRef(ref);\n const destination = destinationFor(paths.prototypeRoot, normalizedRef);\n const timestamp = clock().toISOString();\n const metadata = buildMetadataJson(\n title,\n description,\n normalizedRef.login,\n authorName,\n timestamp,\n theme,\n );\n\n parsePrototypeMetadata(JSON.parse(metadata), { themeRegistry });\n await ensureDirectory(paths.prototypeRoot);\n await ensureDirectory(dirname(destination));\n const ownedFiles: OwnedPath[] = [];\n const receipt = await reserveDestination(destination, paths);\n const ownedDirectories: OwnedPath[] = [receipt];\n\n try {\n ownedDirectories.push(\n await createDirectory(join(destination, \"components\")),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"page.tsx\"),\n buildPageTsx(),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"app.tsx\"),\n buildAppTsx(title, description, ref),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"app.module.css\"),\n buildAppCss(),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"components/.gitkeep\"),\n \"\",\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"metadata.json\"),\n metadata,\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"tsconfig.json\"),\n buildTsConfig(paths.repositoryRoot, destination),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"css-modules.d.ts\"),\n buildCssModulesDeclaration(),\n writeFile,\n ),\n );\n\n const writtenMetadata = await readWrittenMetadata(\n join(destination, \"metadata.json\"),\n );\n parsePrototypeMetadata(JSON.parse(writtenMetadata), { themeRegistry });\n return {\n destination,\n receipt,\n expectedFiles: Object.freeze([...GENERATED_FILES]),\n };\n } catch (error) {\n try {\n await removeIncompleteDestination(ownedFiles, ownedDirectories);\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n if (error instanceof PrototypeScaffoldError) throw error;\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nexport { GENERATED_FILES } from \"./internal/prototype-templates.js\";\n"]}
package/dist/scaffold.js CHANGED
@@ -4,6 +4,7 @@ import { dirname, join } from "node:path";
4
4
  import { definePrototypeRef, parsePrototypeMetadata, } from "@ebay-dt/bonfire-core";
5
5
  import { captureOwnedDestination, } from "./internal/owned-destination.js";
6
6
  import { buildAppCss, buildAppTsx, buildCssModulesDeclaration, buildMetadataJson, buildPageTsx, buildTsConfig, GENERATED_FILES, } from "./internal/prototype-templates.js";
7
+ import { isFileNotFound } from "./internal/utils.js";
7
8
  export class PrototypeScaffoldError extends Error {
8
9
  kind;
9
10
  constructor(kind) {
@@ -26,17 +27,11 @@ async function assertDirectory(path) {
26
27
  catch (error) {
27
28
  if (error instanceof PrototypeScaffoldError)
28
29
  throw error;
29
- if (isMissing(error))
30
+ if (isFileNotFound(error))
30
31
  return;
31
32
  throw new PrototypeScaffoldError("filesystem");
32
33
  }
33
34
  }
34
- function isMissing(error) {
35
- return (error !== null &&
36
- typeof error === "object" &&
37
- "code" in error &&
38
- error.code === "ENOENT");
39
- }
40
35
  async function ensureDirectory(path) {
41
36
  try {
42
37
  await mkdir(path, { recursive: true });
@@ -129,12 +124,12 @@ async function removeIncompleteDestination(files, directories) {
129
124
  throw new PrototypeScaffoldError("filesystem");
130
125
  }
131
126
  }
132
- export async function scaffoldPrototype({ paths, ref, title, description, authorName, clock = () => new Date(), writeFile = writeFileAsync, }) {
127
+ export async function scaffoldPrototype({ paths, ref, title, description, authorName, theme, themeRegistry, clock = () => new Date(), writeFile = writeFileAsync, }) {
133
128
  const normalizedRef = definePrototypeRef(ref);
134
129
  const destination = destinationFor(paths.prototypeRoot, normalizedRef);
135
130
  const timestamp = clock().toISOString();
136
- const metadata = buildMetadataJson(title, description, normalizedRef.login, authorName, timestamp);
137
- parsePrototypeMetadata(JSON.parse(metadata));
131
+ const metadata = buildMetadataJson(title, description, normalizedRef.login, authorName, timestamp, theme);
132
+ parsePrototypeMetadata(JSON.parse(metadata), { themeRegistry });
138
133
  await ensureDirectory(paths.prototypeRoot);
139
134
  await ensureDirectory(dirname(destination));
140
135
  const ownedFiles = [];
@@ -143,14 +138,14 @@ export async function scaffoldPrototype({ paths, ref, title, description, author
143
138
  try {
144
139
  ownedDirectories.push(await createDirectory(join(destination, "components")));
145
140
  ownedFiles.push(await writeNewFile(join(destination, "page.tsx"), buildPageTsx(), writeFile));
146
- ownedFiles.push(await writeNewFile(join(destination, "app.tsx"), buildAppTsx(title, description), writeFile));
141
+ ownedFiles.push(await writeNewFile(join(destination, "app.tsx"), buildAppTsx(title, description, ref), writeFile));
147
142
  ownedFiles.push(await writeNewFile(join(destination, "app.module.css"), buildAppCss(), writeFile));
148
143
  ownedFiles.push(await writeNewFile(join(destination, "components/.gitkeep"), "", writeFile));
149
144
  ownedFiles.push(await writeNewFile(join(destination, "metadata.json"), metadata, writeFile));
150
145
  ownedFiles.push(await writeNewFile(join(destination, "tsconfig.json"), buildTsConfig(paths.repositoryRoot, destination), writeFile));
151
146
  ownedFiles.push(await writeNewFile(join(destination, "css-modules.d.ts"), buildCssModulesDeclaration(), writeFile));
152
147
  const writtenMetadata = await readWrittenMetadata(join(destination, "metadata.json"));
153
- parsePrototypeMetadata(JSON.parse(writtenMetadata));
148
+ parsePrototypeMetadata(JSON.parse(writtenMetadata), { themeRegistry });
154
149
  return {
155
150
  destination,
156
151
  receipt,
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EACL,KAAK,EACL,KAAK,EACL,IAAI,EACJ,EAAE,EACF,KAAK,EACL,SAAS,IAAI,cAAc,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GAIvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,uBAAuB,GAExB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,WAAW,EACX,WAAW,EACX,0BAA0B,EAC1B,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AA0BrD,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACtC,IAAI,CAA6B;IAE1C,YAAY,IAAgC;QAC1C,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,SAAS,cAAc,CAAC,aAAqB,EAAE,GAAiB;IAC9D,MAAM,aAAa,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACnD,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,sBAAsB;YAAE,MAAM,KAAK,CAAC;QACzD,IAAI,cAAc,CAAC,KAAK,CAAC;YAAE,OAAO;QAClC,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAQD,KAAK,UAAU,SAAS,CAAC,IAAY;IACnC,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;AACvD,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,IAAY,EACZ,KAGC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK,KAAK,IAAI;YACd,OAAO,KAAK,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK;YACf,KAAK,CAAC,IAAI,KAAK,QAAQ,EACvB,CAAC;YACD,MAAM,IAAI,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,uBAAuB,CAAC;YACnC,IAAI;YACJ,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,aAAa,EAAE,KAAK,CAAC,aAAa;SACnC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,IAAY,EACZ,OAAe,EACf,SAAwB;IAExB,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,OAAO,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,IAAY;IAC7C,MAAM,IAAI,GAAG,MAAM,IAAI,CACrB,IAAI,EACJ,SAAS,CAAC,QAAQ,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC,CACjD,CAAC;IACF,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;YAAS,CAAC;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,2BAA2B,CACxC,KAA2B,EAC3B,WAAiC;IAEjC,IAAI,CAAC;QACH,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC1D,IACE,OAAO,KAAK,IAAI;gBAChB,CAAC,OAAO,CAAC,cAAc,EAAE;gBACzB,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,MAAM;gBAC5B,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,KAAK,EAC3B,CAAC;gBACD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAC1D,IACE,OAAO,KAAK,IAAI;gBAChB,OAAO,CAAC,WAAW,EAAE;gBACrB,CAAC,OAAO,CAAC,cAAc,EAAE;gBACzB,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,MAAM;gBAC5B,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,KAAK,EAC3B,CAAC;gBACD,MAAM,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,KAAK,EACL,GAAG,EACH,KAAK,EACL,WAAW,EACX,UAAU,EACV,KAAK,EACL,aAAa,EACb,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EACxB,SAAS,GAAG,cAAc,GACD;IACzB,MAAM,aAAa,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,QAAQ,GAAG,iBAAiB,CAChC,KAAK,EACL,WAAW,EACX,aAAa,CAAC,KAAK,EACnB,UAAU,EACV,SAAS,EACT,KAAK,CACN,CAAC;IAEF,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;IAChE,MAAM,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,eAAe,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC7D,MAAM,gBAAgB,GAAgB,CAAC,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC;QACH,gBAAgB,CAAC,IAAI,CACnB,MAAM,eAAe,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CACvD,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EAC7B,YAAY,EAAE,EACd,SAAS,CACV,CACF,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,EAC5B,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,EACpC,SAAS,CACV,CACF,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,EACnC,WAAW,EAAE,EACb,SAAS,CACV,CACF,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,EACxC,EAAE,EACF,SAAS,CACV,CACF,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAClC,QAAQ,EACR,SAAS,CACV,CACF,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAClC,aAAa,CAAC,KAAK,CAAC,cAAc,EAAE,WAAW,CAAC,EAChD,SAAS,CACV,CACF,CAAC;QACF,UAAU,CAAC,IAAI,CACb,MAAM,YAAY,CAChB,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,EACrC,0BAA0B,EAAE,EAC5B,SAAS,CACV,CACF,CAAC;QAEF,MAAM,eAAe,GAAG,MAAM,mBAAmB,CAC/C,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CACnC,CAAC;QACF,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;QACvE,OAAO;YACL,WAAW;YACX,OAAO;YACP,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;SACnD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,2BAA2B,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,KAAK,YAAY,sBAAsB;YAAE,MAAM,KAAK,CAAC;QACzD,MAAM,IAAI,sBAAsB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC","sourcesContent":["import { constants } from \"node:fs\";\nimport {\n lstat,\n mkdir,\n open,\n rm,\n rmdir,\n writeFile as writeFileAsync,\n} from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport {\n definePrototypeRef,\n parsePrototypeMetadata,\n type PrototypeRef,\n type PrototypeTheme,\n type ThemeRegistry,\n} from \"@ebay-dt/bonfire-core\";\nimport type { ResolvedPrototypeCatalogPaths } from \"./prototype-paths.js\";\nimport {\n captureOwnedDestination,\n type OwnedDestinationResult,\n} from \"./internal/owned-destination.js\";\nimport {\n buildAppCss,\n buildAppTsx,\n buildCssModulesDeclaration,\n buildMetadataJson,\n buildPageTsx,\n buildTsConfig,\n GENERATED_FILES,\n} from \"./internal/prototype-templates.js\";\nimport { isFileNotFound } from \"./internal/utils.js\";\n\ntype SafeWriteFile = (\n path: string,\n content: string,\n options: { encoding: \"utf8\"; flag: \"wx\" },\n) => Promise<void>;\n\nexport type PrototypeScaffoldOptions = {\n paths: Pick<\n ResolvedPrototypeCatalogPaths,\n \"repositoryRoot\" | \"prototypeRoot\"\n >;\n ref: PrototypeRef;\n title: string;\n description: string | null;\n authorName: string | null;\n theme?: PrototypeTheme;\n themeRegistry?: ThemeRegistry;\n clock?: () => Date;\n writeFile?: SafeWriteFile;\n};\n\nexport type PrototypeScaffoldErrorKind =\n \"collision\" | \"filesystem\" | \"invalid-input\";\n\nexport class PrototypeScaffoldError extends Error {\n readonly kind: PrototypeScaffoldErrorKind;\n\n constructor(kind: PrototypeScaffoldErrorKind) {\n super(`Prototype scaffold failed: ${kind}`);\n this.name = \"PrototypeScaffoldError\";\n this.kind = kind;\n }\n}\n\nfunction destinationFor(prototypeRoot: string, ref: PrototypeRef) {\n const normalizedRef = definePrototypeRef(ref);\n return join(prototypeRoot, normalizedRef.login, normalizedRef.slug);\n}\n\nasync function assertDirectory(path: string) {\n try {\n const stats = await lstat(path);\n if (stats.isSymbolicLink() || !stats.isDirectory()) {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n } catch (error) {\n if (error instanceof PrototypeScaffoldError) throw error;\n if (isFileNotFound(error)) return;\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nasync function ensureDirectory(path: string) {\n try {\n await mkdir(path, { recursive: true });\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n await assertDirectory(path);\n}\n\ntype OwnedPath = {\n path: string;\n device: number;\n inode: number;\n};\n\nasync function ownedPath(path: string): Promise<OwnedPath> {\n const stats = await lstat(path);\n return { path, device: stats.dev, inode: stats.ino };\n}\n\nasync function reserveDestination(\n path: string,\n paths: Pick<\n ResolvedPrototypeCatalogPaths,\n \"repositoryRoot\" | \"prototypeRoot\"\n >,\n) {\n try {\n await mkdir(path);\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"EEXIST\"\n ) {\n throw new PrototypeScaffoldError(\"collision\");\n }\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n\n try {\n return await captureOwnedDestination({\n path,\n repositoryRoot: paths.repositoryRoot,\n prototypeRoot: paths.prototypeRoot,\n });\n } catch {\n // The newly created path is retained because ownership was not proven.\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nasync function createDirectory(path: string) {\n try {\n await mkdir(path);\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n await assertDirectory(path);\n return ownedPath(path);\n}\n\nasync function writeNewFile(\n path: string,\n content: string,\n writeFile: SafeWriteFile,\n) {\n try {\n await writeFile(path, content, { encoding: \"utf8\", flag: \"wx\" });\n return await ownedPath(path);\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nasync function readWrittenMetadata(path: string) {\n const file = await open(\n path,\n constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0),\n );\n try {\n return await file.readFile(\"utf8\");\n } finally {\n await file.close();\n }\n}\n\nasync function removeIncompleteDestination(\n files: readonly OwnedPath[],\n directories: readonly OwnedPath[],\n) {\n try {\n for (const owned of [...files].reverse()) {\n const current = await lstat(owned.path).catch(() => null);\n if (\n current !== null &&\n !current.isSymbolicLink() &&\n current.dev === owned.device &&\n current.ino === owned.inode\n ) {\n await rm(owned.path, { force: true });\n }\n }\n\n for (const owned of [...directories].reverse()) {\n const current = await lstat(owned.path).catch(() => null);\n if (\n current !== null &&\n current.isDirectory() &&\n !current.isSymbolicLink() &&\n current.dev === owned.device &&\n current.ino === owned.inode\n ) {\n await rmdir(owned.path);\n }\n }\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nexport async function scaffoldPrototype({\n paths,\n ref,\n title,\n description,\n authorName,\n theme,\n themeRegistry,\n clock = () => new Date(),\n writeFile = writeFileAsync,\n}: PrototypeScaffoldOptions): Promise<OwnedDestinationResult> {\n const normalizedRef = definePrototypeRef(ref);\n const destination = destinationFor(paths.prototypeRoot, normalizedRef);\n const timestamp = clock().toISOString();\n const metadata = buildMetadataJson(\n title,\n description,\n normalizedRef.login,\n authorName,\n timestamp,\n theme,\n );\n\n parsePrototypeMetadata(JSON.parse(metadata), { themeRegistry });\n await ensureDirectory(paths.prototypeRoot);\n await ensureDirectory(dirname(destination));\n const ownedFiles: OwnedPath[] = [];\n const receipt = await reserveDestination(destination, paths);\n const ownedDirectories: OwnedPath[] = [receipt];\n\n try {\n ownedDirectories.push(\n await createDirectory(join(destination, \"components\")),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"page.tsx\"),\n buildPageTsx(),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"app.tsx\"),\n buildAppTsx(title, description, ref),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"app.module.css\"),\n buildAppCss(),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"components/.gitkeep\"),\n \"\",\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"metadata.json\"),\n metadata,\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"tsconfig.json\"),\n buildTsConfig(paths.repositoryRoot, destination),\n writeFile,\n ),\n );\n ownedFiles.push(\n await writeNewFile(\n join(destination, \"css-modules.d.ts\"),\n buildCssModulesDeclaration(),\n writeFile,\n ),\n );\n\n const writtenMetadata = await readWrittenMetadata(\n join(destination, \"metadata.json\"),\n );\n parsePrototypeMetadata(JSON.parse(writtenMetadata), { themeRegistry });\n return {\n destination,\n receipt,\n expectedFiles: Object.freeze([...GENERATED_FILES]),\n };\n } catch (error) {\n try {\n await removeIncompleteDestination(ownedFiles, ownedDirectories);\n } catch {\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n if (error instanceof PrototypeScaffoldError) throw error;\n throw new PrototypeScaffoldError(\"filesystem\");\n }\n}\n\nexport { GENERATED_FILES } from \"./internal/prototype-templates.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,SAAS,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAa9E,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,YAAY,CAAC;IAClB,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,eAAe,KAAK,SAAS,CAAC;CAClE,CAAC;AAwLF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB,CAElB"}
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,SAAS,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAa9E,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,YAAY,CAAC;IAClB,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,eAAe,KAAK,SAAS,CAAC;CAClE,CAAC;AAwLF,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,gBAAgB,CAElB","sourcesContent":["import {\n watch as chokidarWatch,\n type ChokidarOptions,\n type FSWatcher,\n} from \"chokidar\";\nimport {\n definePrototypeRef,\n type DirtyObservationValue,\n type PrototypeRef,\n} from \"@ebay-dt/bonfire-core\";\nimport { join, relative, sep } from \"node:path\";\nimport { createGitRepository, type GitRepository } from \"./git-repository.js\";\nimport { applyDirtyObservation } from \"./lifecycle/dirty-state.js\";\n\nconst DEFAULT_DEBOUNCE_MS = 250;\nconst WATCH_EVENTS = [\n \"add\",\n \"addDir\",\n \"change\",\n \"unlink\",\n \"unlinkDir\",\n] as const;\nconst WATCH_PATHS = [\".git/HEAD\", \".git/index\", \".git/refs/heads\"] as const;\n\nexport type PrototypeWatchRequest = {\n ref: PrototypeRef;\n initial?: DirtyObservationValue;\n onChange(value: DirtyObservationValue): void;\n};\n\nexport type PrototypeWatcher = {\n subscribe(request: PrototypeWatchRequest): () => void;\n};\n\nexport type PrototypeWatcherOptions = {\n repositoryRoot: string;\n prototypeRoot: string;\n gitRepository?: GitRepository;\n debounceMs?: number;\n watch?: (paths: string[], options: ChokidarOptions) => FSWatcher;\n};\n\ntype Subscriber = PrototypeWatchRequest & { key: string };\n\ntype Watchable = Pick<FSWatcher, \"on\" | \"close\">;\n\nfunction keyFor(ref: PrototypeRef) {\n return `${ref.login}/${ref.slug}`;\n}\n\nfunction pathFor(\n repositoryRoot: string,\n prototypeRoot: string,\n ref: PrototypeRef,\n) {\n return relative(repositoryRoot, join(prototypeRoot, ref.login, ref.slug))\n .split(sep)\n .join(\"/\");\n}\n\nclass LocalPrototypeWatcher implements PrototypeWatcher {\n readonly #repositoryRoot: string;\n readonly #prototypeRoot: string;\n readonly #gitRepository: GitRepository;\n readonly #debounceMs: number;\n readonly #watch: NonNullable<PrototypeWatcherOptions[\"watch\"]>;\n readonly #subscribers = new Set<Subscriber>();\n readonly #stateCache = new Map<string, DirtyObservationValue>();\n #watcher: Watchable | null = null;\n #debounceTimer: NodeJS.Timeout | null = null;\n #ticking = false;\n #pendingRetick = false;\n\n constructor(options: PrototypeWatcherOptions) {\n this.#repositoryRoot = options.repositoryRoot;\n this.#prototypeRoot = options.prototypeRoot;\n this.#gitRepository =\n options.gitRepository ??\n createGitRepository({ repositoryRoot: options.repositoryRoot });\n this.#debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n this.#watch = options.watch ?? chokidarWatch;\n }\n\n subscribe(request: PrototypeWatchRequest) {\n const ref = Object.freeze(definePrototypeRef(request.ref));\n const subscriber: Subscriber = {\n ...request,\n ref,\n key: keyFor(ref),\n };\n this.#subscribers.add(subscriber);\n this.#ensureStarted();\n\n if (!this.#stateCache.has(subscriber.key)) {\n if (subscriber.initial !== undefined) {\n this.#stateCache.set(subscriber.key, subscriber.initial);\n } else {\n void this.#seed(subscriber);\n }\n }\n\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n this.#subscribers.delete(subscriber);\n if (this.#subscribers.size === 0) this.#stop();\n };\n }\n\n #ensureStarted() {\n if (this.#watcher) return;\n\n const paths = [\n this.#prototypeRoot,\n ...WATCH_PATHS.map((path) => join(this.#repositoryRoot, path)),\n ];\n const options: ChokidarOptions = {\n persistent: true,\n ignoreInitial: true,\n followSymlinks: false,\n ignored: [/\\.next/, /node_modules/],\n };\n const watcher = this.#watch(paths, options);\n for (const event of WATCH_EVENTS) {\n watcher.on(event, () => this.#scheduleTick());\n }\n watcher.on(\"error\", () => {\n console.error(\"[bonfire watcher] filesystem observation failed\");\n });\n this.#watcher = watcher;\n }\n\n #scheduleTick() {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#debounceTimer = setTimeout(() => {\n this.#debounceTimer = null;\n void this.#tick();\n }, this.#debounceMs);\n }\n\n async #read(ref: PrototypeRef) {\n const path = pathFor(this.#repositoryRoot, this.#prototypeRoot, ref);\n const status = await this.#gitRepository.status([path]);\n return {\n status: status.files.length > 0 ? \"dirty\" : \"clean\",\n } satisfies DirtyObservationValue;\n }\n\n async #seed(subscriber: Subscriber) {\n try {\n const value = await this.#read(subscriber.ref);\n if (\n this.#subscribers.has(subscriber) &&\n !this.#stateCache.has(subscriber.key)\n ) {\n this.#stateCache.set(subscriber.key, value);\n }\n } catch {\n console.error(\"[bonfire watcher] Git observation failed\");\n }\n }\n\n async #tick() {\n if (this.#ticking) {\n this.#pendingRetick = true;\n return;\n }\n this.#ticking = true;\n\n try {\n const seen = new Set<string>();\n for (const subscriber of this.#subscribers) {\n if (seen.has(subscriber.key)) continue;\n seen.add(subscriber.key);\n\n let current: DirtyObservationValue;\n try {\n current = await this.#read(subscriber.ref);\n } catch {\n console.error(\"[bonfire watcher] Git observation failed\");\n continue;\n }\n\n const previous = this.#stateCache.get(subscriber.key)?.status;\n const transition = applyDirtyObservation(\n previous,\n current.status === \"dirty\",\n );\n if (!transition.changed) continue;\n this.#stateCache.set(subscriber.key, transition.value);\n\n for (const candidate of this.#subscribers) {\n if (candidate.key !== subscriber.key) continue;\n try {\n candidate.onChange(transition.value);\n } catch {\n console.error(\"[bonfire watcher] subscriber callback failed\");\n }\n }\n }\n } finally {\n this.#ticking = false;\n if (this.#pendingRetick) {\n this.#pendingRetick = false;\n void this.#tick();\n }\n }\n }\n\n #stop() {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#debounceTimer = null;\n this.#stateCache.clear();\n const watcher = this.#watcher;\n this.#watcher = null;\n if (watcher) {\n void watcher.close().catch(() => {\n console.error(\"[bonfire watcher] filesystem cleanup failed\");\n });\n }\n }\n}\n\nexport function createPrototypeWatcher(\n options: PrototypeWatcherOptions,\n): PrototypeWatcher {\n return new LocalPrototypeWatcher(options);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n watch as chokidarWatch,\n type ChokidarOptions,\n type FSWatcher,\n} from \"chokidar\";\nimport {\n definePrototypeRef,\n type DirtyObservationValue,\n type PrototypeRef,\n} from \"@ebay-dt/bonfire-core\";\nimport { join, relative, sep } from \"node:path\";\nimport { createGitRepository, type GitRepository } from \"./git-repository.js\";\nimport { applyDirtyObservation } from \"./lifecycle/dirty-state.js\";\n\nconst DEFAULT_DEBOUNCE_MS = 250;\nconst WATCH_EVENTS = [\n \"add\",\n \"addDir\",\n \"change\",\n \"unlink\",\n \"unlinkDir\",\n] as const;\nconst WATCH_PATHS = [\".git/HEAD\", \".git/index\", \".git/refs/heads\"] as const;\n\nexport type PrototypeWatchRequest = {\n ref: PrototypeRef;\n initial?: DirtyObservationValue;\n onChange(value: DirtyObservationValue): void;\n};\n\nexport type PrototypeWatcher = {\n subscribe(request: PrototypeWatchRequest): () => void;\n};\n\nexport type PrototypeWatcherOptions = {\n repositoryRoot: string;\n prototypeRoot: string;\n gitRepository?: GitRepository;\n debounceMs?: number;\n watch?: (paths: string[], options: ChokidarOptions) => FSWatcher;\n};\n\ntype Subscriber = PrototypeWatchRequest & { key: string };\n\ntype Watchable = Pick<FSWatcher, \"on\" | \"close\">;\n\nfunction keyFor(ref: PrototypeRef) {\n return `${ref.login}/${ref.slug}`;\n}\n\nfunction pathFor(\n repositoryRoot: string,\n prototypeRoot: string,\n ref: PrototypeRef,\n) {\n return relative(repositoryRoot, join(prototypeRoot, ref.login, ref.slug))\n .split(sep)\n .join(\"/\");\n}\n\nclass LocalPrototypeWatcher implements PrototypeWatcher {\n readonly #repositoryRoot: string;\n readonly #prototypeRoot: string;\n readonly #gitRepository: GitRepository;\n readonly #debounceMs: number;\n readonly #watch: NonNullable<PrototypeWatcherOptions[\"watch\"]>;\n readonly #subscribers = new Set<Subscriber>();\n readonly #stateCache = new Map<string, DirtyObservationValue>();\n #watcher: Watchable | null = null;\n #debounceTimer: NodeJS.Timeout | null = null;\n #ticking = false;\n #pendingRetick = false;\n\n constructor(options: PrototypeWatcherOptions) {\n this.#repositoryRoot = options.repositoryRoot;\n this.#prototypeRoot = options.prototypeRoot;\n this.#gitRepository =\n options.gitRepository ??\n createGitRepository({ repositoryRoot: options.repositoryRoot });\n this.#debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n this.#watch = options.watch ?? chokidarWatch;\n }\n\n subscribe(request: PrototypeWatchRequest) {\n const ref = Object.freeze(definePrototypeRef(request.ref));\n const subscriber: Subscriber = {\n ...request,\n ref,\n key: keyFor(ref),\n };\n this.#subscribers.add(subscriber);\n this.#ensureStarted();\n\n if (!this.#stateCache.has(subscriber.key)) {\n if (subscriber.initial !== undefined) {\n this.#stateCache.set(subscriber.key, subscriber.initial);\n } else {\n void this.#seed(subscriber);\n }\n }\n\n let active = true;\n return () => {\n if (!active) return;\n active = false;\n this.#subscribers.delete(subscriber);\n if (this.#subscribers.size === 0) this.#stop();\n };\n }\n\n #ensureStarted() {\n if (this.#watcher) return;\n\n const paths = [\n this.#prototypeRoot,\n ...WATCH_PATHS.map((path) => join(this.#repositoryRoot, path)),\n ];\n const options: ChokidarOptions = {\n persistent: true,\n ignoreInitial: true,\n followSymlinks: false,\n ignored: [/\\.next/, /node_modules/],\n };\n const watcher = this.#watch(paths, options);\n for (const event of WATCH_EVENTS) {\n watcher.on(event, () => this.#scheduleTick());\n }\n watcher.on(\"error\", () => {\n console.error(\"[bonfire watcher] filesystem observation failed\");\n });\n this.#watcher = watcher;\n }\n\n #scheduleTick() {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#debounceTimer = setTimeout(() => {\n this.#debounceTimer = null;\n void this.#tick();\n }, this.#debounceMs);\n }\n\n async #read(ref: PrototypeRef) {\n const path = pathFor(this.#repositoryRoot, this.#prototypeRoot, ref);\n const status = await this.#gitRepository.status([path]);\n return {\n status: status.files.length > 0 ? \"dirty\" : \"clean\",\n } satisfies DirtyObservationValue;\n }\n\n async #seed(subscriber: Subscriber) {\n try {\n const value = await this.#read(subscriber.ref);\n if (\n this.#subscribers.has(subscriber) &&\n !this.#stateCache.has(subscriber.key)\n ) {\n this.#stateCache.set(subscriber.key, value);\n }\n } catch {\n console.error(\"[bonfire watcher] Git observation failed\");\n }\n }\n\n async #tick() {\n if (this.#ticking) {\n this.#pendingRetick = true;\n return;\n }\n this.#ticking = true;\n\n try {\n const seen = new Set<string>();\n for (const subscriber of this.#subscribers) {\n if (seen.has(subscriber.key)) continue;\n seen.add(subscriber.key);\n\n let current: DirtyObservationValue;\n try {\n current = await this.#read(subscriber.ref);\n } catch {\n console.error(\"[bonfire watcher] Git observation failed\");\n continue;\n }\n\n const previous = this.#stateCache.get(subscriber.key)?.status;\n const transition = applyDirtyObservation(\n previous,\n current.status === \"dirty\",\n );\n if (!transition.changed) continue;\n this.#stateCache.set(subscriber.key, transition.value);\n\n for (const candidate of this.#subscribers) {\n if (candidate.key !== subscriber.key) continue;\n try {\n candidate.onChange(transition.value);\n } catch {\n console.error(\"[bonfire watcher] subscriber callback failed\");\n }\n }\n }\n } finally {\n this.#ticking = false;\n if (this.#pendingRetick) {\n this.#pendingRetick = false;\n void this.#tick();\n }\n }\n }\n\n #stop() {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#debounceTimer = null;\n this.#stateCache.clear();\n const watcher = this.#watcher;\n this.#watcher = null;\n if (watcher) {\n void watcher.close().catch(() => {\n console.error(\"[bonfire watcher] filesystem cleanup failed\");\n });\n }\n }\n}\n\nexport function createPrototypeWatcher(\n options: PrototypeWatcherOptions,\n): PrototypeWatcher {\n return new LocalPrototypeWatcher(options);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ebay-dt/bonfire-node",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.1.0-alpha.2",
4
4
  "description": "Node.js adapters for Bonfire.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,7 +31,7 @@
31
31
  "access": "public"
32
32
  },
33
33
  "dependencies": {
34
- "@ebay-dt/bonfire-core": "0.1.0-alpha.0",
34
+ "@ebay-dt/bonfire-core": "0.1.0-alpha.2",
35
35
  "chokidar": "^5.0.0",
36
36
  "simple-git": "^3.36.0"
37
37
  },
@@ -44,7 +44,7 @@
44
44
  "vitest": "^5.0.0"
45
45
  },
46
46
  "scripts": {
47
- "build": "tsc -p tsconfig.build.json",
47
+ "build": "tsc -p tsconfig.build.json && node ../../scripts/embed-source-map-sources.mjs dist",
48
48
  "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
49
49
  "check": "tsc -p tsconfig.json --noEmit",
50
50
  "lint": "eslint .",