nitrostack 1.0.0

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 (290) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/CONTRIBUTING.md +182 -0
  3. package/LICENSE +201 -0
  4. package/LICENSE_URLS_UPDATE_COMPLETE.md +388 -0
  5. package/NOTICE +153 -0
  6. package/README.md +571 -0
  7. package/dist/auth/api-key.d.ts +118 -0
  8. package/dist/auth/api-key.d.ts.map +1 -0
  9. package/dist/auth/api-key.js +168 -0
  10. package/dist/auth/api-key.js.map +1 -0
  11. package/dist/auth/client.d.ts +151 -0
  12. package/dist/auth/client.d.ts.map +1 -0
  13. package/dist/auth/client.js +330 -0
  14. package/dist/auth/client.js.map +1 -0
  15. package/dist/auth/index.d.ts +30 -0
  16. package/dist/auth/index.d.ts.map +1 -0
  17. package/dist/auth/index.js +43 -0
  18. package/dist/auth/index.js.map +1 -0
  19. package/dist/auth/middleware.d.ts +95 -0
  20. package/dist/auth/middleware.d.ts.map +1 -0
  21. package/dist/auth/middleware.js +260 -0
  22. package/dist/auth/middleware.js.map +1 -0
  23. package/dist/auth/pkce.d.ts +53 -0
  24. package/dist/auth/pkce.d.ts.map +1 -0
  25. package/dist/auth/pkce.js +105 -0
  26. package/dist/auth/pkce.js.map +1 -0
  27. package/dist/auth/quick-setup.d.ts +94 -0
  28. package/dist/auth/quick-setup.d.ts.map +1 -0
  29. package/dist/auth/quick-setup.js +210 -0
  30. package/dist/auth/quick-setup.js.map +1 -0
  31. package/dist/auth/server-integration.d.ts +97 -0
  32. package/dist/auth/server-integration.d.ts.map +1 -0
  33. package/dist/auth/server-integration.js +182 -0
  34. package/dist/auth/server-integration.js.map +1 -0
  35. package/dist/auth/server-metadata.d.ts +51 -0
  36. package/dist/auth/server-metadata.d.ts.map +1 -0
  37. package/dist/auth/server-metadata.js +106 -0
  38. package/dist/auth/server-metadata.js.map +1 -0
  39. package/dist/auth/simple-jwt.d.ts +88 -0
  40. package/dist/auth/simple-jwt.d.ts.map +1 -0
  41. package/dist/auth/simple-jwt.js +152 -0
  42. package/dist/auth/simple-jwt.js.map +1 -0
  43. package/dist/auth/token-store.d.ts +104 -0
  44. package/dist/auth/token-store.d.ts.map +1 -0
  45. package/dist/auth/token-store.js +205 -0
  46. package/dist/auth/token-store.js.map +1 -0
  47. package/dist/auth/token-validation.d.ts +47 -0
  48. package/dist/auth/token-validation.d.ts.map +1 -0
  49. package/dist/auth/token-validation.js +237 -0
  50. package/dist/auth/token-validation.js.map +1 -0
  51. package/dist/auth/types.d.ts +215 -0
  52. package/dist/auth/types.d.ts.map +1 -0
  53. package/dist/auth/types.js +6 -0
  54. package/dist/auth/types.js.map +1 -0
  55. package/dist/cli/commands/build.d.ts +6 -0
  56. package/dist/cli/commands/build.d.ts.map +1 -0
  57. package/dist/cli/commands/build.js +104 -0
  58. package/dist/cli/commands/build.js.map +1 -0
  59. package/dist/cli/commands/dev.d.ts +7 -0
  60. package/dist/cli/commands/dev.d.ts.map +1 -0
  61. package/dist/cli/commands/dev.js +312 -0
  62. package/dist/cli/commands/dev.js.map +1 -0
  63. package/dist/cli/commands/generate-types.d.ts +8 -0
  64. package/dist/cli/commands/generate-types.d.ts.map +1 -0
  65. package/dist/cli/commands/generate-types.js +220 -0
  66. package/dist/cli/commands/generate-types.js.map +1 -0
  67. package/dist/cli/commands/generate.d.ts +5 -0
  68. package/dist/cli/commands/generate.d.ts.map +1 -0
  69. package/dist/cli/commands/generate.js +365 -0
  70. package/dist/cli/commands/generate.js.map +1 -0
  71. package/dist/cli/commands/init.d.ts +7 -0
  72. package/dist/cli/commands/init.d.ts.map +1 -0
  73. package/dist/cli/commands/init.js +365 -0
  74. package/dist/cli/commands/init.js.map +1 -0
  75. package/dist/cli/commands/start.d.ts +6 -0
  76. package/dist/cli/commands/start.d.ts.map +1 -0
  77. package/dist/cli/commands/start.js +61 -0
  78. package/dist/cli/commands/start.js.map +1 -0
  79. package/dist/cli/index.d.ts +3 -0
  80. package/dist/cli/index.d.ts.map +1 -0
  81. package/dist/cli/index.js +47 -0
  82. package/dist/cli/index.js.map +1 -0
  83. package/dist/cli/mcp-dev-wrapper.d.ts +3 -0
  84. package/dist/cli/mcp-dev-wrapper.d.ts.map +1 -0
  85. package/dist/cli/mcp-dev-wrapper.js +116 -0
  86. package/dist/cli/mcp-dev-wrapper.js.map +1 -0
  87. package/dist/core/apikey-module.d.ts +69 -0
  88. package/dist/core/apikey-module.d.ts.map +1 -0
  89. package/dist/core/apikey-module.js +114 -0
  90. package/dist/core/apikey-module.js.map +1 -0
  91. package/dist/core/app-decorator.d.ts +58 -0
  92. package/dist/core/app-decorator.d.ts.map +1 -0
  93. package/dist/core/app-decorator.js +261 -0
  94. package/dist/core/app-decorator.js.map +1 -0
  95. package/dist/core/builders.d.ts +38 -0
  96. package/dist/core/builders.d.ts.map +1 -0
  97. package/dist/core/builders.js +129 -0
  98. package/dist/core/builders.js.map +1 -0
  99. package/dist/core/component.d.ts +105 -0
  100. package/dist/core/component.d.ts.map +1 -0
  101. package/dist/core/component.js +182 -0
  102. package/dist/core/component.js.map +1 -0
  103. package/dist/core/config-module.d.ts +55 -0
  104. package/dist/core/config-module.d.ts.map +1 -0
  105. package/dist/core/config-module.js +94 -0
  106. package/dist/core/config-module.js.map +1 -0
  107. package/dist/core/decorators/cache.decorator.d.ts +61 -0
  108. package/dist/core/decorators/cache.decorator.d.ts.map +1 -0
  109. package/dist/core/decorators/cache.decorator.js +115 -0
  110. package/dist/core/decorators/cache.decorator.js.map +1 -0
  111. package/dist/core/decorators/health-check.decorator.d.ts +80 -0
  112. package/dist/core/decorators/health-check.decorator.d.ts.map +1 -0
  113. package/dist/core/decorators/health-check.decorator.js +153 -0
  114. package/dist/core/decorators/health-check.decorator.js.map +1 -0
  115. package/dist/core/decorators/rate-limit.decorator.d.ts +62 -0
  116. package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -0
  117. package/dist/core/decorators/rate-limit.decorator.js +129 -0
  118. package/dist/core/decorators/rate-limit.decorator.js.map +1 -0
  119. package/dist/core/decorators.d.ts +151 -0
  120. package/dist/core/decorators.d.ts.map +1 -0
  121. package/dist/core/decorators.js +142 -0
  122. package/dist/core/decorators.js.map +1 -0
  123. package/dist/core/di/container.d.ts +42 -0
  124. package/dist/core/di/container.d.ts.map +1 -0
  125. package/dist/core/di/container.js +76 -0
  126. package/dist/core/di/container.js.map +1 -0
  127. package/dist/core/di/injectable.decorator.d.ts +35 -0
  128. package/dist/core/di/injectable.decorator.d.ts.map +1 -0
  129. package/dist/core/di/injectable.decorator.js +57 -0
  130. package/dist/core/di/injectable.decorator.js.map +1 -0
  131. package/dist/core/errors.d.ts +54 -0
  132. package/dist/core/errors.d.ts.map +1 -0
  133. package/dist/core/errors.js +87 -0
  134. package/dist/core/errors.js.map +1 -0
  135. package/dist/core/events/event-emitter.d.ts +50 -0
  136. package/dist/core/events/event-emitter.d.ts.map +1 -0
  137. package/dist/core/events/event-emitter.js +94 -0
  138. package/dist/core/events/event-emitter.js.map +1 -0
  139. package/dist/core/events/event.decorator.d.ts +48 -0
  140. package/dist/core/events/event.decorator.d.ts.map +1 -0
  141. package/dist/core/events/event.decorator.js +68 -0
  142. package/dist/core/events/event.decorator.js.map +1 -0
  143. package/dist/core/filters/exception-filter.decorator.d.ts +40 -0
  144. package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -0
  145. package/dist/core/filters/exception-filter.decorator.js +54 -0
  146. package/dist/core/filters/exception-filter.decorator.js.map +1 -0
  147. package/dist/core/filters/exception-filter.interface.d.ts +30 -0
  148. package/dist/core/filters/exception-filter.interface.d.ts.map +1 -0
  149. package/dist/core/filters/exception-filter.interface.js +2 -0
  150. package/dist/core/filters/exception-filter.interface.js.map +1 -0
  151. package/dist/core/guards/apikey.guard.d.ts +22 -0
  152. package/dist/core/guards/apikey.guard.d.ts.map +1 -0
  153. package/dist/core/guards/apikey.guard.js +11 -0
  154. package/dist/core/guards/apikey.guard.js.map +1 -0
  155. package/dist/core/guards/guard.interface.d.ts +18 -0
  156. package/dist/core/guards/guard.interface.d.ts.map +1 -0
  157. package/dist/core/guards/guard.interface.js +2 -0
  158. package/dist/core/guards/guard.interface.js.map +1 -0
  159. package/dist/core/guards/jwt.guard.d.ts +18 -0
  160. package/dist/core/guards/jwt.guard.d.ts.map +1 -0
  161. package/dist/core/guards/jwt.guard.js +2 -0
  162. package/dist/core/guards/jwt.guard.js.map +1 -0
  163. package/dist/core/guards/oauth.guard.d.ts +35 -0
  164. package/dist/core/guards/oauth.guard.d.ts.map +1 -0
  165. package/dist/core/guards/oauth.guard.js +2 -0
  166. package/dist/core/guards/oauth.guard.js.map +1 -0
  167. package/dist/core/guards/use-guards.decorator.d.ts +25 -0
  168. package/dist/core/guards/use-guards.decorator.d.ts.map +1 -0
  169. package/dist/core/guards/use-guards.decorator.js +32 -0
  170. package/dist/core/guards/use-guards.decorator.js.map +1 -0
  171. package/dist/core/health/health-checks.resource.d.ts +14 -0
  172. package/dist/core/health/health-checks.resource.d.ts.map +1 -0
  173. package/dist/core/health/health-checks.resource.js +29 -0
  174. package/dist/core/health/health-checks.resource.js.map +1 -0
  175. package/dist/core/index.d.ts +55 -0
  176. package/dist/core/index.d.ts.map +1 -0
  177. package/dist/core/index.js +57 -0
  178. package/dist/core/index.js.map +1 -0
  179. package/dist/core/interceptors/interceptor.decorator.d.ts +37 -0
  180. package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -0
  181. package/dist/core/interceptors/interceptor.decorator.js +51 -0
  182. package/dist/core/interceptors/interceptor.decorator.js.map +1 -0
  183. package/dist/core/interceptors/interceptor.interface.d.ts +31 -0
  184. package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -0
  185. package/dist/core/interceptors/interceptor.interface.js +2 -0
  186. package/dist/core/interceptors/interceptor.interface.js.map +1 -0
  187. package/dist/core/jwt-module.d.ts +51 -0
  188. package/dist/core/jwt-module.d.ts.map +1 -0
  189. package/dist/core/jwt-module.js +52 -0
  190. package/dist/core/jwt-module.js.map +1 -0
  191. package/dist/core/logger.d.ts +18 -0
  192. package/dist/core/logger.d.ts.map +1 -0
  193. package/dist/core/logger.js +51 -0
  194. package/dist/core/logger.js.map +1 -0
  195. package/dist/core/middleware/middleware.decorator.d.ts +39 -0
  196. package/dist/core/middleware/middleware.decorator.d.ts.map +1 -0
  197. package/dist/core/middleware/middleware.decorator.js +53 -0
  198. package/dist/core/middleware/middleware.decorator.js.map +1 -0
  199. package/dist/core/middleware/middleware.interface.d.ts +29 -0
  200. package/dist/core/middleware/middleware.interface.d.ts.map +1 -0
  201. package/dist/core/middleware/middleware.interface.js +2 -0
  202. package/dist/core/middleware/middleware.interface.js.map +1 -0
  203. package/dist/core/module.d.ts +74 -0
  204. package/dist/core/module.d.ts.map +1 -0
  205. package/dist/core/module.js +82 -0
  206. package/dist/core/module.js.map +1 -0
  207. package/dist/core/oauth-module.d.ts +144 -0
  208. package/dist/core/oauth-module.d.ts.map +1 -0
  209. package/dist/core/oauth-module.js +190 -0
  210. package/dist/core/oauth-module.js.map +1 -0
  211. package/dist/core/pipes/pipe.decorator.d.ts +55 -0
  212. package/dist/core/pipes/pipe.decorator.d.ts.map +1 -0
  213. package/dist/core/pipes/pipe.decorator.js +85 -0
  214. package/dist/core/pipes/pipe.decorator.js.map +1 -0
  215. package/dist/core/pipes/pipe.interface.d.ts +36 -0
  216. package/dist/core/pipes/pipe.interface.d.ts.map +1 -0
  217. package/dist/core/pipes/pipe.interface.js +2 -0
  218. package/dist/core/pipes/pipe.interface.js.map +1 -0
  219. package/dist/core/prompt.d.ts +37 -0
  220. package/dist/core/prompt.d.ts.map +1 -0
  221. package/dist/core/prompt.js +76 -0
  222. package/dist/core/prompt.js.map +1 -0
  223. package/dist/core/resource.d.ts +42 -0
  224. package/dist/core/resource.d.ts.map +1 -0
  225. package/dist/core/resource.js +90 -0
  226. package/dist/core/resource.js.map +1 -0
  227. package/dist/core/server.d.ts +72 -0
  228. package/dist/core/server.d.ts.map +1 -0
  229. package/dist/core/server.js +406 -0
  230. package/dist/core/server.js.map +1 -0
  231. package/dist/core/tool.d.ts +78 -0
  232. package/dist/core/tool.d.ts.map +1 -0
  233. package/dist/core/tool.js +190 -0
  234. package/dist/core/tool.js.map +1 -0
  235. package/dist/core/transports/http-server.d.ts +102 -0
  236. package/dist/core/transports/http-server.d.ts.map +1 -0
  237. package/dist/core/transports/http-server.js +265 -0
  238. package/dist/core/transports/http-server.js.map +1 -0
  239. package/dist/core/types.d.ts +123 -0
  240. package/dist/core/types.d.ts.map +1 -0
  241. package/dist/core/types.js +2 -0
  242. package/dist/core/types.js.map +1 -0
  243. package/dist/core/widgets/widget-examples.resource.d.ts +17 -0
  244. package/dist/core/widgets/widget-examples.resource.d.ts.map +1 -0
  245. package/dist/core/widgets/widget-examples.resource.js +28 -0
  246. package/dist/core/widgets/widget-examples.resource.js.map +1 -0
  247. package/dist/core/widgets/widget-registry.d.ts +56 -0
  248. package/dist/core/widgets/widget-registry.d.ts.map +1 -0
  249. package/dist/core/widgets/widget-registry.js +75 -0
  250. package/dist/core/widgets/widget-registry.js.map +1 -0
  251. package/dist/testing/index.d.ts +82 -0
  252. package/dist/testing/index.d.ts.map +1 -0
  253. package/dist/testing/index.js +164 -0
  254. package/dist/testing/index.js.map +1 -0
  255. package/dist/ui-next/index.d.ts +31 -0
  256. package/dist/ui-next/index.d.ts.map +1 -0
  257. package/dist/ui-next/index.js +687 -0
  258. package/dist/ui-next/index.js.map +1 -0
  259. package/dist/widgets/index.d.ts +9 -0
  260. package/dist/widgets/index.d.ts.map +1 -0
  261. package/dist/widgets/index.js +9 -0
  262. package/dist/widgets/index.js.map +1 -0
  263. package/dist/widgets/metadata.d.ts +53 -0
  264. package/dist/widgets/metadata.d.ts.map +1 -0
  265. package/dist/widgets/metadata.js +29 -0
  266. package/dist/widgets/metadata.js.map +1 -0
  267. package/dist/widgets/withToolData.d.ts +19 -0
  268. package/dist/widgets/withToolData.d.ts.map +1 -0
  269. package/dist/widgets/withToolData.js +240 -0
  270. package/dist/widgets/withToolData.js.map +1 -0
  271. package/jest.config.js +21 -0
  272. package/package.json +108 -0
  273. package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +702 -0
  274. package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +1260 -0
  275. package/templates/typescript-auth/README.md +400 -0
  276. package/templates/typescript-auth/package.json +44 -0
  277. package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +701 -0
  278. package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +1260 -0
  279. package/templates/typescript-auth-api-key/README.md +483 -0
  280. package/templates/typescript-auth-api-key/package-lock.json +124 -0
  281. package/templates/typescript-auth-api-key/package.json +29 -0
  282. package/templates/typescript-oauth/AI_AGENT_CLI_REFERENCE.md +701 -0
  283. package/templates/typescript-oauth/AI_AGENT_SDK_REFERENCE.md +1260 -0
  284. package/templates/typescript-oauth/OAUTH_SETUP.md +406 -0
  285. package/templates/typescript-oauth/README.md +350 -0
  286. package/templates/typescript-oauth/package.json +30 -0
  287. package/templates/typescript-starter/AI_AGENT_CLI_REFERENCE.md +701 -0
  288. package/templates/typescript-starter/AI_AGENT_SDK_REFERENCE.md +1260 -0
  289. package/templates/typescript-starter/README.md +312 -0
  290. package/templates/typescript-starter/package.json +32 -0
@@ -0,0 +1,687 @@
1
+ import { execSync } from 'node:child_process';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { createComponent } from '../core/component.js';
5
+ function inlineHtmlWithAssets(htmlPath, outDir) {
6
+ let html = fs.readFileSync(htmlPath, 'utf8');
7
+ // Inline <link rel="stylesheet" href="...">
8
+ html = html.replace(/<link[^>]*rel=["']stylesheet["'][^>]*href=["']([^"']+)["'][^>]*>/g, (_m, href) => {
9
+ try {
10
+ // Remove leading slash for absolute paths
11
+ const cleanHref = href.startsWith('/') ? href.slice(1) : href;
12
+ const cssPath = path.join(outDir, cleanHref);
13
+ const css = fs.readFileSync(cssPath, 'utf8');
14
+ return `<style>${css}</style>`;
15
+ }
16
+ catch (err) {
17
+ // CSS file not found - remove the link tag
18
+ return '';
19
+ }
20
+ });
21
+ // Inline <script src="...">
22
+ html = html.replace(/<script[^>]*src=["']([^"']+)["'][^>]*><\/script>/g, (_m, src) => {
23
+ try {
24
+ // Remove leading slash for absolute paths
25
+ const cleanSrc = src.startsWith('/') ? src.slice(1) : src;
26
+ const jsPath = path.join(outDir, cleanSrc);
27
+ const js = fs.readFileSync(jsPath, 'utf8');
28
+ // Return inlined script without type="module" to avoid issues with Next.js code
29
+ return `<script>${js}</script>`;
30
+ }
31
+ catch (err) {
32
+ // JS file not found - remove the script tag
33
+ return '';
34
+ }
35
+ });
36
+ // Remove preload links for assets we couldn't inline (prevents 404s and warnings)
37
+ html = html.replace(/<link[^>]*rel=["']preload["'][^>]*>/g, '');
38
+ return html;
39
+ }
40
+ function scaffoldAppRoute(projectDir, routePath) {
41
+ const appDir = path.join(projectDir, 'app');
42
+ const created = !fs.existsSync(appDir);
43
+ if (!fs.existsSync(appDir))
44
+ fs.mkdirSync(appDir, { recursive: true });
45
+ const routeDir = path.join(appDir, routePath);
46
+ if (!fs.existsSync(routeDir))
47
+ fs.mkdirSync(routeDir, { recursive: true });
48
+ const target = path.join(routeDir, 'page.tsx');
49
+ // Create a re-export shim pointing to widgets/<route>/page.tsx
50
+ const shim = `export { default } from '../../${routePath}/page';\n`;
51
+ fs.writeFileSync(target, shim, 'utf8');
52
+ return { created };
53
+ }
54
+ function cleanupAppRoute(projectDir, routePath, removeAppDir) {
55
+ try {
56
+ const appDir = path.join(projectDir, 'app');
57
+ const routeDir = path.join(appDir, routePath);
58
+ if (fs.existsSync(routeDir))
59
+ fs.rmSync(routeDir, { recursive: true, force: true });
60
+ if (removeAppDir && fs.existsSync(appDir))
61
+ fs.rmSync(appDir, { recursive: true, force: true });
62
+ }
63
+ catch { }
64
+ }
65
+ /**
66
+ * Build a Next.js widget and create a NitroStack Component from the exported HTML.
67
+ * Produces a single-file HTML bundle compatible with OpenAI Apps SDK widgets.
68
+ */
69
+ export function createComponentFromNext(opts) {
70
+ const { id, name, projectDir, entryHtml = 'out/index.html', description, prefersBorder, csp, transformer, build = true, buildScript, } = opts;
71
+ if (!fs.existsSync(projectDir)) {
72
+ throw new Error(`Next widget project not found: ${projectDir}`);
73
+ }
74
+ if (build) {
75
+ const cmd = buildScript || 'npm run build';
76
+ execSync(cmd, { stdio: 'inherit', cwd: projectDir });
77
+ }
78
+ const outPath = path.resolve(projectDir, entryHtml);
79
+ const outDir = path.dirname(outPath);
80
+ if (!fs.existsSync(outPath)) {
81
+ throw new Error(`Exported HTML not found at ${outPath}. Ensure next.config.js has output: 'export'.`);
82
+ }
83
+ const inlined = inlineHtmlWithAssets(outPath, outDir);
84
+ return createComponent({
85
+ id,
86
+ name,
87
+ description,
88
+ html: inlined,
89
+ prefersBorder,
90
+ csp,
91
+ transformer,
92
+ });
93
+ }
94
+ export const uiNext = { createComponentFromNext };
95
+ // ------- Multi-route support (single Next project with multiple routes) -------
96
+ const buildCache = new Map();
97
+ export function createComponentFromNextRoute(arg1, arg2) {
98
+ const isString = typeof arg1 === 'string';
99
+ const routePath = isString ? arg1 : arg1.routePath;
100
+ const provided = (isString ? (arg2 || {}) : arg1);
101
+ // Check if we're in widget dev mode
102
+ const widgetsDevMode = process.env.WIDGETS_DEV_MODE === 'true';
103
+ const widgetsDevPort = process.env.WIDGETS_DEV_PORT || '3001';
104
+ // In dev mode, return a component with a dev URL instead of static HTML
105
+ if (widgetsDevMode) {
106
+ const id = provided.id || `next-${routePath}`;
107
+ const name = provided.name || routePath
108
+ .split('-')
109
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
110
+ .join(' ');
111
+ // Return a special dev component that uses live URL
112
+ return createComponent({
113
+ id,
114
+ name,
115
+ description: provided.description,
116
+ // Empty HTML - will be loaded from dev server
117
+ html: `<!-- Widget loaded from dev server: /widgets/${routePath} -->`,
118
+ css: '',
119
+ js: '',
120
+ prefersBorder: provided.prefersBorder,
121
+ csp: provided.csp,
122
+ transformer: provided.transformer,
123
+ // Store dev URL as metadata for inspector to use
124
+ _meta: {
125
+ devUrl: `/widgets/${routePath}`,
126
+ devMode: true,
127
+ },
128
+ });
129
+ }
130
+ // Defaults - look in src/widgets (for dev) or dist/widgets (for built)
131
+ const srcWidgetsRoot = path.resolve(process.cwd(), 'src', 'widgets');
132
+ const distWidgetsRoot = path.resolve(process.cwd(), 'dist', 'widgets');
133
+ const defaultDir = fs.existsSync(srcWidgetsRoot) ? srcWidgetsRoot : distWidgetsRoot;
134
+ const id = provided.id || `next-${routePath}`;
135
+ const name = provided.name || routePath
136
+ .split('-')
137
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
138
+ .join(' ');
139
+ const projectDir = provided.projectDir || defaultDir;
140
+ const description = provided.description;
141
+ const prefersBorder = provided.prefersBorder;
142
+ const csp = provided.csp;
143
+ const transformer = provided.transformer;
144
+ // Default build to FALSE - widgets should be pre-built by npm run build
145
+ const build = provided.build !== undefined ? provided.build : false;
146
+ const buildScript = provided.buildScript;
147
+ if (build) {
148
+ const { created } = scaffoldAppRoute(projectDir, routePath);
149
+ const last = buildCache.get(projectDir) || 0;
150
+ const now = Date.now();
151
+ // simple debounce to avoid rebuilding multiple times in a row
152
+ if (now - last > 2000) {
153
+ const cmd = buildScript || 'npm run build';
154
+ execSync(cmd, { stdio: 'inherit', cwd: projectDir });
155
+ buildCache.set(projectDir, now);
156
+ }
157
+ cleanupAppRoute(projectDir, routePath, created);
158
+ }
159
+ // Try both possible Next.js export locations
160
+ let outPath = path.resolve(projectDir, 'out', routePath, 'index.html');
161
+ if (!fs.existsSync(outPath)) {
162
+ // Try flat structure (route-name.html)
163
+ outPath = path.resolve(projectDir, 'out', `${routePath}.html`);
164
+ if (!fs.existsSync(outPath)) {
165
+ throw new Error(`Exported HTML for route '${routePath}' not found. Tried:\n` +
166
+ ` - ${path.resolve(projectDir, 'out', routePath, 'index.html')}\n` +
167
+ ` - ${path.resolve(projectDir, 'out', `${routePath}.html`)}`);
168
+ }
169
+ }
170
+ // For Next.js widgets, we need to create a simple renderer that works with data
171
+ // Instead of using complex Next.js hydration, generate simple HTML dynamically
172
+ const widgetHtml = generateSimpleWidgetHtml(routePath, id);
173
+ return createComponent({
174
+ id,
175
+ name,
176
+ description,
177
+ html: widgetHtml,
178
+ prefersBorder,
179
+ csp,
180
+ transformer,
181
+ });
182
+ }
183
+ /**
184
+ * Generate simple, dynamic widget HTML that reads window.openai.toolOutput
185
+ */
186
+ function generateSimpleWidgetHtml(routePath, widgetId) {
187
+ // Base template that all widgets use
188
+ const baseTemplate = `<!DOCTYPE html>
189
+ <html>
190
+ <head>
191
+ <meta charset="UTF-8">
192
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
193
+ <style>
194
+ * { box-sizing: border-box; }
195
+ body {
196
+ margin: 16px;
197
+ padding: 0;
198
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
199
+ background: #ffffff;
200
+ color: #1a1a1a;
201
+ min-height: 100px;
202
+ }
203
+ .widget-container {
204
+ background: #ffffff;
205
+ border: 1px solid #e5e7eb;
206
+ border-radius: 12px;
207
+ padding: 0;
208
+ overflow: hidden;
209
+ max-width: 100%;
210
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
211
+ }
212
+ .widget-header {
213
+ padding: 20px;
214
+ background: linear-gradient(135deg, #D4AF37 0%, #F5C842 100%);
215
+ color: #000;
216
+ font-weight: 700;
217
+ font-size: 18px;
218
+ }
219
+ .widget-body {
220
+ padding: 20px;
221
+ }
222
+ .success {
223
+ color: #D4AF37;
224
+ font-weight: 700;
225
+ margin-bottom: 16px;
226
+ font-size: 18px;
227
+ display: flex;
228
+ align-items: center;
229
+ gap: 8px;
230
+ }
231
+ .error {
232
+ color: #ef4444;
233
+ font-weight: 700;
234
+ margin-bottom: 16px;
235
+ font-size: 18px;
236
+ }
237
+ .profile-img {
238
+ width: 100px;
239
+ height: 100px;
240
+ border-radius: 50%;
241
+ object-fit: cover;
242
+ border: 4px solid #D4AF37;
243
+ margin-bottom: 16px;
244
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
245
+ }
246
+ .product-img {
247
+ width: 100%;
248
+ height: 200px;
249
+ object-fit: cover;
250
+ border-radius: 8px;
251
+ margin-bottom: 12px;
252
+ }
253
+ .card {
254
+ border: 1px solid #e5e7eb;
255
+ padding: 16px;
256
+ border-radius: 12px;
257
+ background: #f9fafb;
258
+ margin-bottom: 12px;
259
+ transition: all 0.2s ease;
260
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
261
+ }
262
+ .card:hover {
263
+ border-color: #D4AF37;
264
+ box-shadow: 0 4px 6px rgba(212, 175, 55, 0.2);
265
+ transform: translateY(-2px);
266
+ }
267
+ .field { margin: 10px 0; font-size: 14px; color: #374151; }
268
+ .label { color: #6b7280; font-size: 13px; margin-right: 8px; font-weight: 500; }
269
+ .token {
270
+ margin-top: 12px;
271
+ padding: 12px;
272
+ background: #f3f4f6;
273
+ border-radius: 8px;
274
+ font-size: 12px;
275
+ word-break: break-all;
276
+ font-family: monospace;
277
+ border: 1px solid #D4AF37;
278
+ color: #D4AF37;
279
+ }
280
+ .grid {
281
+ display: grid;
282
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
283
+ gap: 16px;
284
+ }
285
+ .product-card {
286
+ border: 1px solid #e5e7eb;
287
+ border-radius: 12px;
288
+ background: #ffffff;
289
+ transition: all 0.3s ease;
290
+ cursor: pointer;
291
+ overflow: hidden;
292
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
293
+ }
294
+ .product-card:hover {
295
+ border-color: #D4AF37;
296
+ box-shadow: 0 8px 16px rgba(212, 175, 55, 0.3);
297
+ transform: translateY(-4px);
298
+ }
299
+ .product-card-img {
300
+ width: 100%;
301
+ height: 200px;
302
+ object-fit: cover;
303
+ background: #f9fafb;
304
+ }
305
+ .product-card-body {
306
+ padding: 16px;
307
+ }
308
+ .product-name {
309
+ font-weight: 700;
310
+ font-size: 16px;
311
+ margin-bottom: 8px;
312
+ line-height: 1.3;
313
+ color: #1a1a1a;
314
+ }
315
+ .product-desc {
316
+ font-size: 13px;
317
+ color: #6b7280;
318
+ margin-bottom: 12px;
319
+ line-height: 1.5;
320
+ }
321
+ .empty {
322
+ color: #9ca3af;
323
+ text-align: center;
324
+ padding: 60px 20px;
325
+ font-size: 15px;
326
+ }
327
+ .price {
328
+ color: #D4AF37;
329
+ font-weight: 700;
330
+ font-size: 20px;
331
+ }
332
+ .stock-badge {
333
+ display: inline-block;
334
+ padding: 6px 12px;
335
+ border-radius: 6px;
336
+ font-size: 12px;
337
+ font-weight: 600;
338
+ background: rgba(212, 175, 55, 0.1);
339
+ color: #D4AF37;
340
+ border: 1px solid rgba(212, 175, 55, 0.3);
341
+ margin-top: 8px;
342
+ }
343
+ </style>
344
+ </head>
345
+ <body>
346
+ <div id="root">Loading...</div>
347
+ <script>
348
+ (function() {
349
+ function render() {
350
+ const data = (window.openai && window.openai.toolOutput) || {};
351
+ const root = document.getElementById('root');
352
+
353
+ ${getWidgetRenderFunction(routePath)}
354
+
355
+ root.innerHTML = html;
356
+ }
357
+
358
+ // Render immediately if data available
359
+ if (window.openai && window.openai.toolOutput) {
360
+ render();
361
+ } else {
362
+ // Wait for data to be injected
363
+ setTimeout(render, 50);
364
+ }
365
+ })();
366
+ </script>
367
+ </body>
368
+ </html>`;
369
+ return baseTemplate;
370
+ }
371
+ /**
372
+ * Get widget-specific render function
373
+ */
374
+ function getWidgetRenderFunction(routePath) {
375
+ switch (routePath) {
376
+ case 'login-result':
377
+ return `
378
+ const user = data.user;
379
+ const html = '<div class="widget-container">' + (user
380
+ ? '<div class="widget-header">✅ Login Successful</div>' +
381
+ '<div class="widget-body">' +
382
+ (user.profile_picture ? '<div style="text-align:center;margin-bottom:16px;"><img src="' + user.profile_picture + '" class="profile-img" alt="' + user.name + '"></div>' : '') +
383
+ '<div class="card">' +
384
+ '<div class="field"><span class="label">Name:</span> ' + user.name + '</div>' +
385
+ '<div class="field"><span class="label">Email:</span> ' + user.email + '</div>' +
386
+ '</div>' +
387
+ (data.token ? '<div class="token"><div style="color:#6b7280;margin-bottom:6px;font-size:11px;">Authentication Token:</div>' + data.token.substring(0, 60) + '...</div>' : '') +
388
+ '</div>'
389
+ : '<div class="widget-body"><div class="error">⚠️ Unable to log in</div></div>') + '</div>';
390
+ `;
391
+ case 'whoami':
392
+ return `
393
+ const user = data.user;
394
+ const html = '<div class="widget-container">' + (user
395
+ ? '<div class="widget-header">👤 User Profile</div>' +
396
+ '<div class="widget-body" style="text-align:center;">' +
397
+ (user.profile_picture ? '<img src="' + user.profile_picture + '" class="profile-img" alt="Profile">' : '') +
398
+ '<div class="card" style="text-align:left;">' +
399
+ '<div class="field"><span class="label">Name:</span> ' + user.name + '</div>' +
400
+ '<div class="field"><span class="label">Email:</span> ' + user.email + '</div>' +
401
+ (user.memberSince ? '<div class="field"><span class="label">Member Since:</span> ' + new Date(user.memberSince).toLocaleDateString() + '</div>' : '') +
402
+ '</div></div>'
403
+ : '<div class="widget-body"><div class="error">⚠️ Not authenticated</div></div>') + '</div>';
404
+ `;
405
+ case 'products-grid':
406
+ return `
407
+ const products = data.products || [];
408
+ const html = '<div class="widget-container">' + (products.length > 0
409
+ ? '<div class="widget-header">🛍️ ' + products.length + ' Products Available</div>' +
410
+ '<div class="widget-body"><div class="grid">' + products.map(p =>
411
+ '<div class="product-card">' +
412
+ (p.image_url ? '<img src="' + p.image_url + '" class="product-card-img" alt="' + p.name + '">' : '') +
413
+ '<div class="product-card-body">' +
414
+ '<div class="product-name">' + p.name + '</div>' +
415
+ '<div class="product-desc">' + p.description.substring(0, 70) + '...</div>' +
416
+ '<div class="price">$' + p.price.toFixed(2) + '</div>' +
417
+ '<div class="stock-badge">' + p.stock + ' in stock</div>' +
418
+ '</div>' +
419
+ '</div>'
420
+ ).join('') + '</div></div>'
421
+ : '<div class="widget-body"><div class="empty">No products found</div></div>') + '</div>';
422
+ `;
423
+ case 'shopping-cart':
424
+ return `
425
+ const items = data.items || [];
426
+ const total = data.total || 0;
427
+ const html = '<div class="widget-container">' + (items.length > 0
428
+ ? '<div class="widget-header">🛒 Shopping Cart (' + items.length + ' items)</div>' +
429
+ '<div class="widget-body">' +
430
+ items.map(item =>
431
+ '<div class="card">' +
432
+ '<div style="display:flex;gap:12px;align-items:flex-start;">' +
433
+ (item.image_url ? '<img src="' + item.image_url + '" style="width:60px;height:60px;border-radius:8px;object-fit:cover;" alt="' + item.name + '">' : '') +
434
+ '<div style="flex:1;">' +
435
+ '<div style="font-weight:600;color:#1a1a1a;margin-bottom:4px;">' + item.name + '</div>' +
436
+ '<div class="label">Qty: ' + item.quantity + ' × $' + item.price.toFixed(2) + '</div>' +
437
+ '</div>' +
438
+ '<div class="price">$' + (item.price * item.quantity).toFixed(2) + '</div>' +
439
+ '</div>' +
440
+ '</div>'
441
+ ).join('') +
442
+ '<div class="card" style="border-color:#D4AF37;background:#fffbf0;"><strong style="color:#D4AF37;font-size:18px;">Total: $' + total.toFixed(2) + '</strong></div>' +
443
+ '</div>'
444
+ : '<div class="widget-body"><div class="empty">🛒 Cart is empty</div></div>') + '</div>';
445
+ `;
446
+ case 'order-confirmation':
447
+ return `
448
+ const order = data.order;
449
+ const html = '<div class="widget-container">' + (order
450
+ ? '<div class="widget-header">✅ Order Confirmed</div>' +
451
+ '<div class="widget-body">' +
452
+ '<div class="card">' +
453
+ '<div class="field"><span class="label">Order ID:</span> #' + order.id.substring(0, 8).toUpperCase() + '</div>' +
454
+ '<div class="field"><span class="label">Status:</span> <span class="stock-badge">' + order.status + '</span></div>' +
455
+ '<div class="field"><span class="label">Items:</span> ' + (order.items ? order.items.length : 0) + ' products</div>' +
456
+ '</div>' +
457
+ (order.items && order.items.length > 0 ? order.items.map(item =>
458
+ '<div class="card">' +
459
+ '<div style="display:flex;gap:10px;">' +
460
+ (item.image_url ? '<img src="' + item.image_url + '" style="width:50px;height:50px;border-radius:6px;object-fit:cover;" alt="' + item.name + '">' : '') +
461
+ '<div><div style="font-weight:600;color:#1a1a1a;">' + item.name + '</div>' +
462
+ '<div class="label">Qty: ' + item.quantity + ' × $' + item.price.toFixed(2) + '</div></div>' +
463
+ '</div>' +
464
+ '</div>'
465
+ ).join('') : '') +
466
+ '<div class="card" style="border-color:#D4AF37;background:#fffbf0;text-align:center;"><strong class="price" style="font-size:22px;">Total: $' + order.total.toFixed(2) + '</strong></div>' +
467
+ '</div>'
468
+ : '<div class="widget-body"><div class="error">⚠️ No order data</div></div>') + '</div>';
469
+ `;
470
+ case 'product-card':
471
+ return `
472
+ const product = data.product;
473
+ const html = '<div class="widget-container">' + (product
474
+ ? '<div class="widget-header">📦 Product Details</div>' +
475
+ '<div class="widget-body">' +
476
+ (product.image_url ? '<img src="' + product.image_url + '" class="product-img" alt="' + product.name + '">' : '') +
477
+ '<div class="product-name" style="font-size:22px;margin-bottom:12px;">' + product.name + '</div>' +
478
+ '<div class="product-desc" style="color:#6b7280;font-size:14px;margin-bottom:16px;">' + product.description + '</div>' +
479
+ '<div class="card">' +
480
+ '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">' +
481
+ '<div class="price">$' + product.price.toFixed(2) + '</div>' +
482
+ '<div class="stock-badge">' + product.stock + ' in stock</div>' +
483
+ '</div>' +
484
+ '<div class="field"><span class="label">Category:</span> ' + product.category + '</div>' +
485
+ '</div>' +
486
+ '</div>'
487
+ : '<div class="widget-body"><div class="error">⚠️ Product not found</div></div>') + '</div>';
488
+ `;
489
+ case 'add-to-cart':
490
+ return `
491
+ const item = data.item;
492
+ const html = '<div class="widget-container">' + (item
493
+ ? '<div class="widget-header">✅ Added to Cart</div>' +
494
+ '<div class="widget-body">' +
495
+ '<div class="card">' +
496
+ '<div style="display:flex;gap:12px;align-items:center;">' +
497
+ (item.image_url ? '<img src="' + item.image_url + '" style="width:80px;height:80px;border-radius:8px;object-fit:cover;" alt="' + item.name + '">' : '') +
498
+ '<div style="flex:1;">' +
499
+ '<div style="font-weight:700;font-size:16px;color:#1a1a1a;margin-bottom:4px;">' + item.name + '</div>' +
500
+ '<div class="label">Quantity: ' + item.quantity + '</div>' +
501
+ '<div class="price" style="font-size:18px;margin-top:4px;">$' + item.price.toFixed(2) + '</div>' +
502
+ '</div>' +
503
+ '</div>' +
504
+ '</div>' +
505
+ '<div style="text-align:center;margin-top:16px;padding:12px;background:#f0fdf4;border-radius:8px;color:#16a34a;font-weight:600;">' +
506
+ '🛒 Cart Total: ' + data.cartItemCount + ' items' +
507
+ '</div>' +
508
+ '</div>'
509
+ : '<div class="widget-body"><div class="error">⚠️ Failed to add to cart</div></div>') + '</div>';
510
+ `;
511
+ case 'address-list':
512
+ return `
513
+ const addresses = data.addresses || [];
514
+ const html = '<div class="widget-container">' + (addresses.length > 0
515
+ ? '<div class="widget-header">📍 Delivery Addresses</div>' +
516
+ '<div class="widget-body">' +
517
+ addresses.map(addr =>
518
+ '<div class="card">' +
519
+ '<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:8px;">' +
520
+ '<div style="font-weight:700;color:#1a1a1a;">' + addr.full_name + '</div>' +
521
+ (addr.is_default ? '<div class="stock-badge">Default</div>' : '') +
522
+ '</div>' +
523
+ '<div class="field">' + addr.street + '</div>' +
524
+ '<div class="field">' + addr.city + ', ' + addr.state + ' ' + addr.zip_code + '</div>' +
525
+ '<div class="field"><span class="label">Phone:</span> ' + addr.phone + '</div>' +
526
+ '</div>'
527
+ ).join('') +
528
+ '</div>'
529
+ : '<div class="widget-body"><div class="empty">No saved addresses</div></div>') + '</div>';
530
+ `;
531
+ case 'order-history':
532
+ return `
533
+ const orders = data.orders || [];
534
+ const html = '<div class="widget-container">' + (orders.length > 0
535
+ ? '<div class="widget-header">📦 Order History</div>' +
536
+ '<div class="widget-body">' +
537
+ orders.map(order =>
538
+ '<div class="card">' +
539
+ '<div style="display:flex;justify-content:space-between;margin-bottom:12px;">' +
540
+ '<div><span class="label">Order #</span>' + order.id.substring(0, 8).toUpperCase() + '</div>' +
541
+ '<div class="stock-badge">' + order.status + '</div>' +
542
+ '</div>' +
543
+ '<div class="field"><span class="label">Items:</span> ' + order.itemCount + ' products</div>' +
544
+ '<div class="field"><span class="label">Date:</span> ' + new Date(order.created_at).toLocaleDateString() + '</div>' +
545
+ '<div class="price" style="margin-top:8px;">Total: $' + order.total.toFixed(2) + '</div>' +
546
+ '</div>'
547
+ ).join('') +
548
+ '</div>'
549
+ : '<div class="widget-body"><div class="empty">No orders yet</div></div>') + '</div>';
550
+ `;
551
+ case 'order-details':
552
+ return `
553
+ const order = data.order;
554
+ const html = '<div class="widget-container">' + (order
555
+ ? '<div class="widget-header">📦 Order #' + order.id.substring(0, 8).toUpperCase() + '</div>' +
556
+ '<div class="widget-body">' +
557
+ '<div class="card">' +
558
+ '<div class="field"><span class="label">Status:</span> <span class="stock-badge">' + order.status + '</span></div>' +
559
+ '<div class="field"><span class="label">Date:</span> ' + new Date(order.created_at).toLocaleDateString() + '</div>' +
560
+ '<div class="field"><span class="label">Payment:</span> ' + order.payment_method.replace('_', ' ') + '</div>' +
561
+ '</div>' +
562
+ '<div style="margin-top:16px;margin-bottom:8px;font-weight:700;color:#1a1a1a;">Order Items</div>' +
563
+ (order.items && order.items.length > 0 ? order.items.map(item =>
564
+ '<div class="card">' +
565
+ '<div style="display:flex;gap:10px;">' +
566
+ (item.image_url ? '<img src="' + item.image_url + '" style="width:50px;height:50px;border-radius:6px;object-fit:cover;" alt="' + item.name + '">' : '') +
567
+ '<div style="flex:1;"><div style="font-weight:600;color:#1a1a1a;">' + item.name + '</div>' +
568
+ '<div class="label">Qty: ' + item.quantity + ' × $' + item.price.toFixed(2) + '</div></div>' +
569
+ '</div>' +
570
+ '</div>'
571
+ ).join('') : '') +
572
+ '<div class="card" style="border-color:#D4AF37;background:#fffbf0;text-align:center;"><strong class="price" style="font-size:20px;">Total: $' + order.total.toFixed(2) + '</strong></div>' +
573
+ '</div>'
574
+ : '<div class="widget-body"><div class="error">⚠️ Order not found</div></div>') + '</div>';
575
+ `;
576
+ case 'categories':
577
+ return `
578
+ const categories = data.categories || [];
579
+ const html = '<div class="widget-container">' + (categories.length > 0
580
+ ? '<div class="widget-header">🏷️ Product Categories</div>' +
581
+ '<div class="widget-body"><div style="display:grid;grid-template-columns:repeat(2,1fr);gap:12px;">' +
582
+ categories.map(cat =>
583
+ '<div class="card" style="cursor:pointer;">' +
584
+ '<div style="display:flex;justify-content:space-between;align-items:center;">' +
585
+ '<div><div style="font-weight:600;color:#1a1a1a;">' + cat.name + '</div>' +
586
+ '<div class="label" style="margin-top:2px;">' + cat.productCount + ' products</div></div>' +
587
+ '<div style="font-size:24px;">📦</div>' +
588
+ '</div>' +
589
+ '</div>'
590
+ ).join('') + '</div></div>'
591
+ : '<div class="widget-body"><div class="empty">No categories available</div></div>') + '</div>';
592
+ `;
593
+ case 'cart-updated':
594
+ return `
595
+ const message = data.message;
596
+ const product = data.product;
597
+ const quantity = data.quantity;
598
+ const html = '<div class="widget-container">' +
599
+ '<div class="widget-header">✅ Cart Updated</div>' +
600
+ '<div class="widget-body" style="text-align:center;padding:32px 20px;">' +
601
+ '<div style="font-size:48px;margin-bottom:16px;">🛒</div>' +
602
+ '<div style="font-size:18px;font-weight:600;color:#1a1a1a;margin-bottom:12px;">' + message + '</div>' +
603
+ (product ? '<div class="card" style="margin-top:16px;text-align:left;">' +
604
+ '<div class="label" style="margin-bottom:4px;">Product Updated</div>' +
605
+ '<div style="font-weight:600;color:#1a1a1a;">' + product + '</div>' +
606
+ (quantity !== undefined ? '<div class="label" style="margin-top:4px;">New quantity: ' + quantity + '</div>' : '') +
607
+ '</div>' : '') +
608
+ '</div></div>';
609
+ `;
610
+ case 'cart-cleared':
611
+ return `
612
+ const message = data.message;
613
+ const itemsRemoved = data.itemsRemoved || 0;
614
+ const html = '<div class="widget-container">' +
615
+ '<div class="widget-header">🗑️ Cart Cleared</div>' +
616
+ '<div class="widget-body" style="text-align:center;padding:40px 20px;">' +
617
+ '<div style="font-size:56px;margin-bottom:16px;">🛒</div>' +
618
+ '<div style="font-size:20px;font-weight:700;color:#1a1a1a;margin-bottom:12px;">' + message + '</div>' +
619
+ '<div class="card" style="margin-top:24px;background:#f9fafb;">' +
620
+ '<div style="color:#6b7280;"><span style="font-weight:600;color:#1a1a1a;">' + itemsRemoved + '</span> item' + (itemsRemoved !== 1 ? 's were' : ' was') + ' removed from your cart</div>' +
621
+ '</div>' +
622
+ '<div style="margin-top:24px;font-size:14px;color:#9ca3af;">Your shopping cart is now empty</div>' +
623
+ '</div></div>';
624
+ `;
625
+ case 'address-added':
626
+ return `
627
+ const message = data.message;
628
+ const addressId = data.addressId || '';
629
+ const isDefault = data.isDefault;
630
+ const html = '<div class="widget-container">' +
631
+ '<div class="widget-header">✅ Address Added</div>' +
632
+ '<div class="widget-body" style="text-align:center;padding:32px 20px;">' +
633
+ '<div style="font-size:48px;margin-bottom:16px;">📍</div>' +
634
+ '<div style="font-size:18px;font-weight:600;color:#1a1a1a;margin-bottom:12px;">' + message + '</div>' +
635
+ '<div class="card" style="margin-top:16px;">' +
636
+ '<div class="label" style="margin-bottom:8px;">Address ID</div>' +
637
+ '<div style="font-family:monospace;font-size:11px;color:#6b7280;background:#f3f4f6;padding:8px 12px;border-radius:6px;">' + addressId.substring(0, 16) + '...</div>' +
638
+ (isDefault ? '<div style="margin-top:12px;"><span class="stock-badge">⭐ Default Address</span></div>' : '') +
639
+ '</div>' +
640
+ '<div style="margin-top:16px;font-size:14px;color:#9ca3af;">You can now use this address for deliveries</div>' +
641
+ '</div></div>';
642
+ `;
643
+ case 'address-updated':
644
+ return `
645
+ const message = data.message;
646
+ const address = data.address;
647
+ const html = '<div class="widget-container">' +
648
+ '<div class="widget-header">✅ Default Address Updated</div>' +
649
+ '<div class="widget-body">' +
650
+ '<div style="text-align:center;margin-bottom:16px;"><div style="font-size:40px;margin-bottom:12px;">📍</div>' +
651
+ '<div style="font-size:18px;font-weight:600;color:#1a1a1a;">' + message + '</div></div>' +
652
+ (address ? '<div class="card" style="background:rgba(212,175,55,0.05);border-color:#D4AF37;">' +
653
+ '<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:12px;">' +
654
+ '<div style="font-weight:600;color:#1a1a1a;">' + address.full_name + '</div>' +
655
+ '<span class="stock-badge">DEFAULT</span>' +
656
+ '</div>' +
657
+ '<div style="font-size:14px;color:#374151;line-height:1.6;">' +
658
+ '<div>' + address.street + '</div>' +
659
+ '<div>' + address.city + ', ' + address.state + ' ' + address.zip_code + '</div>' +
660
+ '<div>' + address.country + '</div>' +
661
+ '<div style="color:#6b7280;margin-top:8px;">📞 ' + address.phone + '</div>' +
662
+ '</div>' +
663
+ '</div>' : '') +
664
+ '<div style="margin-top:16px;text-align:center;font-size:14px;color:#9ca3af;">This address will be used by default for your orders</div>' +
665
+ '</div></div>';
666
+ `;
667
+ case 'address-deleted':
668
+ return `
669
+ const message = data.message;
670
+ const html = '<div class="widget-container">' +
671
+ '<div class="widget-header">🗑️ Address Deleted</div>' +
672
+ '<div class="widget-body" style="text-align:center;padding:40px 20px;">' +
673
+ '<div style="font-size:56px;margin-bottom:16px;">📍</div>' +
674
+ '<div style="font-size:20px;font-weight:700;color:#1a1a1a;margin-bottom:12px;">' + message + '</div>' +
675
+ '<div class="card" style="margin-top:24px;background:#fef2f2;border-color:#fecaca;">' +
676
+ '<div style="color:#dc2626;">The address has been permanently removed from your account</div>' +
677
+ '</div>' +
678
+ '<div style="margin-top:24px;font-size:14px;color:#9ca3af;">You can add a new address anytime</div>' +
679
+ '</div></div>';
680
+ `;
681
+ default:
682
+ return `
683
+ const html = '<div class="widget-container"><div class="widget-body"><pre style="background:#f3f4f6;padding:12px;border-radius:8px;overflow:auto;font-size:12px;">' + JSON.stringify(data, null, 2) + '</pre></div></div>';
684
+ `;
685
+ }
686
+ }
687
+ //# sourceMappingURL=index.js.map