@forgecart/cli 1.1.0 → 2.1.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 (181) hide show
  1. package/dist/bin/forgecart.d.ts +2 -0
  2. package/dist/bin/forgecart.js +4 -0
  3. package/dist/bin/forgecart.js.map +1 -0
  4. package/dist/src/cli.d.ts +14 -1
  5. package/dist/src/cli.js +30 -15
  6. package/dist/src/cli.js.map +1 -1
  7. package/dist/src/commands/init.d.ts +39 -2
  8. package/dist/src/commands/init.js +173 -301
  9. package/dist/src/commands/init.js.map +1 -1
  10. package/dist/src/commands/placeholders.d.ts +19 -0
  11. package/dist/src/commands/placeholders.js +109 -0
  12. package/dist/src/commands/placeholders.js.map +1 -0
  13. package/dist/src/output.d.ts +11 -0
  14. package/dist/src/output.js +16 -0
  15. package/dist/src/output.js.map +1 -0
  16. package/package.json +21 -11
  17. package/templates/storefront/.env.example +12 -0
  18. package/templates/storefront/.forgecartignore +2 -0
  19. package/templates/storefront/Procfile +1 -0
  20. package/templates/storefront/README.md +87 -0
  21. package/templates/storefront/next.config.js +14 -0
  22. package/templates/storefront/package.json +25 -0
  23. package/templates/storefront/postcss.config.js +6 -0
  24. package/templates/storefront/src/app/cart/page.tsx +88 -0
  25. package/templates/storefront/src/app/globals.css +13 -0
  26. package/templates/storefront/src/app/layout.tsx +32 -0
  27. package/templates/storefront/src/app/page.tsx +49 -0
  28. package/templates/storefront/src/app/products/[slug]/not-found.tsx +20 -0
  29. package/templates/storefront/src/app/products/[slug]/page.tsx +61 -0
  30. package/templates/storefront/src/app/products/page.tsx +27 -0
  31. package/templates/storefront/src/components/Header.tsx +47 -0
  32. package/templates/storefront/src/components/ProductCard.tsx +40 -0
  33. package/templates/storefront/src/components/ProductPurchase.tsx +91 -0
  34. package/templates/storefront/src/lib/cart-actions.ts +148 -0
  35. package/templates/storefront/src/lib/cart-context.tsx +88 -0
  36. package/templates/storefront/src/lib/forgecart.ts +187 -0
  37. package/{dist/templates/storefront-additions → templates/storefront}/tailwind.config.js +1 -1
  38. package/templates/storefront/tsconfig.json +23 -0
  39. package/LICENSE +0 -21
  40. package/README.md +0 -179
  41. package/bin/forgecart.js +0 -3
  42. package/dist/package.json +0 -50
  43. package/dist/src/cli.d.ts.map +0 -1
  44. package/dist/src/commands/delete.d.ts +0 -3
  45. package/dist/src/commands/delete.d.ts.map +0 -1
  46. package/dist/src/commands/delete.js +0 -60
  47. package/dist/src/commands/delete.js.map +0 -1
  48. package/dist/src/commands/deploy.d.ts +0 -3
  49. package/dist/src/commands/deploy.d.ts.map +0 -1
  50. package/dist/src/commands/deploy.js +0 -243
  51. package/dist/src/commands/deploy.js.map +0 -1
  52. package/dist/src/commands/env.d.ts +0 -3
  53. package/dist/src/commands/env.d.ts.map +0 -1
  54. package/dist/src/commands/env.js +0 -158
  55. package/dist/src/commands/env.js.map +0 -1
  56. package/dist/src/commands/init.d.ts.map +0 -1
  57. package/dist/src/commands/list.d.ts +0 -3
  58. package/dist/src/commands/list.d.ts.map +0 -1
  59. package/dist/src/commands/list.js +0 -65
  60. package/dist/src/commands/list.js.map +0 -1
  61. package/dist/src/commands/login.d.ts +0 -3
  62. package/dist/src/commands/login.d.ts.map +0 -1
  63. package/dist/src/commands/login.js +0 -120
  64. package/dist/src/commands/login.js.map +0 -1
  65. package/dist/src/commands/logs.d.ts +0 -3
  66. package/dist/src/commands/logs.d.ts.map +0 -1
  67. package/dist/src/commands/logs.js +0 -88
  68. package/dist/src/commands/logs.js.map +0 -1
  69. package/dist/src/commands/scale.d.ts +0 -3
  70. package/dist/src/commands/scale.d.ts.map +0 -1
  71. package/dist/src/commands/scale.js +0 -49
  72. package/dist/src/commands/scale.js.map +0 -1
  73. package/dist/src/commands/status.d.ts +0 -3
  74. package/dist/src/commands/status.d.ts.map +0 -1
  75. package/dist/src/commands/status.js +0 -90
  76. package/dist/src/commands/status.js.map +0 -1
  77. package/dist/src/commands/whoami.d.ts +0 -3
  78. package/dist/src/commands/whoami.d.ts.map +0 -1
  79. package/dist/src/commands/whoami.js +0 -59
  80. package/dist/src/commands/whoami.js.map +0 -1
  81. package/dist/src/index.d.ts +0 -3
  82. package/dist/src/index.d.ts.map +0 -1
  83. package/dist/src/index.js +0 -5
  84. package/dist/src/index.js.map +0 -1
  85. package/dist/src/lib/api-client.d.ts +0 -34
  86. package/dist/src/lib/api-client.d.ts.map +0 -1
  87. package/dist/src/lib/api-client.js +0 -141
  88. package/dist/src/lib/api-client.js.map +0 -1
  89. package/dist/src/lib/archive.d.ts +0 -9
  90. package/dist/src/lib/archive.d.ts.map +0 -1
  91. package/dist/src/lib/archive.js +0 -118
  92. package/dist/src/lib/archive.js.map +0 -1
  93. package/dist/src/lib/config-updater.d.ts +0 -10
  94. package/dist/src/lib/config-updater.d.ts.map +0 -1
  95. package/dist/src/lib/config-updater.js +0 -34
  96. package/dist/src/lib/config-updater.js.map +0 -1
  97. package/dist/src/lib/config.d.ts +0 -53
  98. package/dist/src/lib/config.d.ts.map +0 -1
  99. package/dist/src/lib/config.js +0 -162
  100. package/dist/src/lib/config.js.map +0 -1
  101. package/dist/src/lib/env-sync.d.ts +0 -44
  102. package/dist/src/lib/env-sync.d.ts.map +0 -1
  103. package/dist/src/lib/env-sync.js +0 -207
  104. package/dist/src/lib/env-sync.js.map +0 -1
  105. package/dist/src/lib/logger.d.ts +0 -15
  106. package/dist/src/lib/logger.d.ts.map +0 -1
  107. package/dist/src/lib/logger.js +0 -54
  108. package/dist/src/lib/logger.js.map +0 -1
  109. package/dist/src/lib/nx-generator.d.ts +0 -22
  110. package/dist/src/lib/nx-generator.d.ts.map +0 -1
  111. package/dist/src/lib/nx-generator.js +0 -345
  112. package/dist/src/lib/nx-generator.js.map +0 -1
  113. package/dist/src/lib/standalone.d.ts +0 -28
  114. package/dist/src/lib/standalone.d.ts.map +0 -1
  115. package/dist/src/lib/standalone.js +0 -107
  116. package/dist/src/lib/standalone.js.map +0 -1
  117. package/dist/src/types/index.d.ts +0 -80
  118. package/dist/src/types/index.d.ts.map +0 -1
  119. package/dist/src/types/index.js +0 -14
  120. package/dist/src/types/index.js.map +0 -1
  121. package/dist/src/utils/spinner.d.ts +0 -16
  122. package/dist/src/utils/spinner.d.ts.map +0 -1
  123. package/dist/src/utils/spinner.js +0 -88
  124. package/dist/src/utils/spinner.js.map +0 -1
  125. package/dist/src/utils/validation.d.ts +0 -12
  126. package/dist/src/utils/validation.d.ts.map +0 -1
  127. package/dist/src/utils/validation.js +0 -82
  128. package/dist/src/utils/validation.js.map +0 -1
  129. package/dist/templates/application-additions/.forgecartignore +0 -37
  130. package/dist/templates/application-additions/Procfile +0 -1
  131. package/dist/templates/application-additions/src/app/app.module.ts +0 -16
  132. package/dist/templates/application-additions/src/services/forgecart.service.ts +0 -62
  133. package/dist/templates/application-additions/src/services/index.ts +0 -2
  134. package/dist/templates/application-additions/src/services/product-event-listener.service.ts +0 -150
  135. package/dist/templates/application-e2e-additions/src/support/global-setup.ts +0 -16
  136. package/dist/templates/application-e2e-additions/src/support/test-setup.ts +0 -9
  137. package/dist/templates/storefront-additions/.forgecartignore +0 -64
  138. package/dist/templates/storefront-additions/Procfile +0 -1
  139. package/dist/templates/storefront-additions/package.json +0 -11
  140. package/dist/templates/storefront-additions/postcss.config.js +0 -5
  141. package/dist/templates/storefront-additions/src/app/cart/page.tsx +0 -77
  142. package/dist/templates/storefront-additions/src/app/global.css +0 -1
  143. package/dist/templates/storefront-additions/src/app/layout.tsx +0 -25
  144. package/dist/templates/storefront-additions/src/app/page.tsx +0 -43
  145. package/dist/templates/storefront-additions/src/components/AddToCartButton.tsx +0 -29
  146. package/dist/templates/storefront-additions/src/components/CartItem.tsx +0 -82
  147. package/dist/templates/storefront-additions/src/components/Header.tsx +0 -42
  148. package/dist/templates/storefront-additions/src/components/ProductCard.tsx +0 -57
  149. package/dist/templates/storefront-additions/src/components/QuantitySelector.tsx +0 -35
  150. package/dist/templates/storefront-additions/src/context/CartContext.tsx +0 -158
  151. package/dist/templates/storefront-additions/src/lib/forgecart.ts +0 -22
  152. package/dist/templates/storefront-e2e-additions/playwright.config.ts +0 -26
  153. package/dist/templates/storefront-e2e-additions/src/example.spec.ts +0 -11
  154. package/dist/templates/workspace/.nxignore +0 -2
  155. package/templates/application-additions/.forgecartignore +0 -37
  156. package/templates/application-additions/Procfile +0 -1
  157. package/templates/application-additions/src/app/app.module.ts +0 -16
  158. package/templates/application-additions/src/services/forgecart.service.ts +0 -62
  159. package/templates/application-additions/src/services/index.ts +0 -2
  160. package/templates/application-additions/src/services/product-event-listener.service.ts +0 -150
  161. package/templates/application-e2e-additions/src/support/global-setup.ts +0 -16
  162. package/templates/application-e2e-additions/src/support/test-setup.ts +0 -9
  163. package/templates/storefront-additions/.forgecartignore +0 -64
  164. package/templates/storefront-additions/Procfile +0 -1
  165. package/templates/storefront-additions/package.json +0 -11
  166. package/templates/storefront-additions/postcss.config.js +0 -5
  167. package/templates/storefront-additions/src/app/cart/page.tsx +0 -77
  168. package/templates/storefront-additions/src/app/global.css +0 -1
  169. package/templates/storefront-additions/src/app/layout.tsx +0 -25
  170. package/templates/storefront-additions/src/app/page.tsx +0 -43
  171. package/templates/storefront-additions/src/components/AddToCartButton.tsx +0 -29
  172. package/templates/storefront-additions/src/components/CartItem.tsx +0 -82
  173. package/templates/storefront-additions/src/components/Header.tsx +0 -42
  174. package/templates/storefront-additions/src/components/ProductCard.tsx +0 -57
  175. package/templates/storefront-additions/src/components/QuantitySelector.tsx +0 -35
  176. package/templates/storefront-additions/src/context/CartContext.tsx +0 -158
  177. package/templates/storefront-additions/src/lib/forgecart.ts +0 -22
  178. package/templates/storefront-additions/tailwind.config.js +0 -8
  179. package/templates/storefront-e2e-additions/playwright.config.ts +0 -26
  180. package/templates/storefront-e2e-additions/src/example.spec.ts +0 -11
  181. package/templates/workspace/.nxignore +0 -2
@@ -1,88 +0,0 @@
1
- import chalk from 'chalk';
2
- import ora from 'ora';
3
- export function createSpinner(text) {
4
- return ora({
5
- text,
6
- spinner: 'dots',
7
- });
8
- }
9
- export async function withSpinner(text, successText, failText, fn) {
10
- const spinner = createSpinner(text).start();
11
- try {
12
- const result = await fn();
13
- spinner.succeed(successText);
14
- return result;
15
- }
16
- catch (error) {
17
- spinner.fail(failText);
18
- throw error;
19
- }
20
- }
21
- /**
22
- * Displays a spinner with inline log streaming below it.
23
- * Logs are displayed as they arrive from the subscription.
24
- */
25
- export async function withSpinnerAndLogs(text, successText, failText, fn, logStream, onCancel) {
26
- const spinner = createSpinner(text).start();
27
- let cancelled = false;
28
- if (logStream) {
29
- ;
30
- (async () => {
31
- try {
32
- for await (const result of logStream) {
33
- if (cancelled)
34
- break;
35
- const log = result.deploymentLogs;
36
- if (!log?.message)
37
- continue;
38
- let displayMessage = log.message;
39
- try {
40
- const parsed = JSON.parse(log.message);
41
- if ('Message' in parsed) {
42
- displayMessage = parsed.Message?.trim() || '';
43
- }
44
- }
45
- catch {
46
- // Not JSON, use as-is
47
- }
48
- if (!displayMessage)
49
- continue;
50
- const timestamp = new Date(log.timestamp).toLocaleTimeString('en-US', {
51
- hour12: false,
52
- hour: '2-digit',
53
- minute: '2-digit',
54
- second: '2-digit',
55
- });
56
- spinner.clear();
57
- console.log(` ${chalk.gray(timestamp)} ${displayMessage}`);
58
- spinner.render();
59
- }
60
- }
61
- catch {
62
- // Stream ended
63
- }
64
- })();
65
- }
66
- try {
67
- const result = await fn();
68
- cancelled = true;
69
- // Close the async iterator to stop the WebSocket connection
70
- if (logStream?.return) {
71
- logStream.return(undefined);
72
- }
73
- onCancel?.();
74
- spinner.succeed(successText);
75
- return result;
76
- }
77
- catch (error) {
78
- cancelled = true;
79
- // Close the async iterator to stop the WebSocket connection
80
- if (logStream?.return) {
81
- logStream.return(undefined);
82
- }
83
- onCancel?.();
84
- spinner.fail(failText);
85
- throw error;
86
- }
87
- }
88
- //# sourceMappingURL=spinner.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../src/utils/spinner.ts"],"names":[],"mappings":"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"}
@@ -1,12 +0,0 @@
1
- import { DeploymentType } from '../types/index.js';
2
- export declare function isValidProjectName(name: string): boolean;
3
- export declare function detectProjectType(dir: string): DeploymentType | null;
4
- export declare function validateChannelToken(token: string): boolean;
5
- export declare function isNxWorkspace(dir: string): boolean;
6
- export declare function hasStorefront(projectRoot: string, storefrontPath: string): boolean;
7
- export declare function hasApplication(projectRoot: string, applicationPath: string): boolean;
8
- export declare function getCurrentAppDir(projectRoot: string): {
9
- type: DeploymentType;
10
- path: string;
11
- } | null;
12
- //# sourceMappingURL=validation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/utils/validation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAElD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CA+CpE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAMT;AAED,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,OAAO,CAMT;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IACrD,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,IAAI,CAcP"}
@@ -1,82 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { DeploymentType } from '../types/index.js';
4
- export function isValidProjectName(name) {
5
- // Must start with letter, can contain letters, numbers, hyphens
6
- return /^[a-z][a-z0-9-]*$/.test(name);
7
- }
8
- export function detectProjectType(dir) {
9
- // Check for Next.js project
10
- const nextConfig = path.join(dir, 'next.config.js');
11
- const nextConfigMjs = path.join(dir, 'next.config.mjs');
12
- if (fs.existsSync(nextConfig) || fs.existsSync(nextConfigMjs)) {
13
- return DeploymentType.STOREFRONT;
14
- }
15
- // Check for NestJS project
16
- const nestCliJson = path.join(dir, 'nest-cli.json');
17
- if (fs.existsSync(nestCliJson)) {
18
- return DeploymentType.APPLICATION;
19
- }
20
- // Check package.json for hints
21
- const packageJson = path.join(dir, 'package.json');
22
- if (fs.existsSync(packageJson)) {
23
- try {
24
- const pkg = JSON.parse(fs.readFileSync(packageJson, 'utf-8'));
25
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
26
- if (deps['next']) {
27
- return DeploymentType.STOREFRONT;
28
- }
29
- if (deps['@nestjs/core']) {
30
- return DeploymentType.APPLICATION;
31
- }
32
- }
33
- catch {
34
- // Ignore parse errors
35
- }
36
- }
37
- // Check for Nx monorepo NestJS project (no nest-cli.json or local package.json)
38
- // Look for src/main.ts with NestJS imports
39
- const mainTs = path.join(dir, 'src', 'main.ts');
40
- if (fs.existsSync(mainTs)) {
41
- try {
42
- const content = fs.readFileSync(mainTs, 'utf-8');
43
- if (content.includes('@nestjs/core') || content.includes('NestFactory')) {
44
- return DeploymentType.APPLICATION;
45
- }
46
- }
47
- catch {
48
- // Ignore read errors
49
- }
50
- }
51
- return null;
52
- }
53
- export function validateChannelToken(token) {
54
- // Basic validation - tokens should be non-empty strings
55
- return typeof token === 'string' && token.length > 0;
56
- }
57
- export function isNxWorkspace(dir) {
58
- return fs.existsSync(path.join(dir, 'nx.json'));
59
- }
60
- export function hasStorefront(projectRoot, storefrontPath) {
61
- const fullPath = path.join(projectRoot, storefrontPath);
62
- return (fs.existsSync(fullPath) &&
63
- detectProjectType(fullPath) === DeploymentType.STOREFRONT);
64
- }
65
- export function hasApplication(projectRoot, applicationPath) {
66
- const fullPath = path.join(projectRoot, applicationPath);
67
- return (fs.existsSync(fullPath) &&
68
- detectProjectType(fullPath) === DeploymentType.APPLICATION);
69
- }
70
- export function getCurrentAppDir(projectRoot) {
71
- const cwd = process.cwd();
72
- // Check if we're in apps/storefront
73
- if (cwd.includes(path.join(projectRoot, 'apps', 'storefront'))) {
74
- return { type: DeploymentType.STOREFRONT, path: cwd };
75
- }
76
- // Check if we're in apps/application
77
- if (cwd.includes(path.join(projectRoot, 'apps', 'application'))) {
78
- return { type: DeploymentType.APPLICATION, path: cwd };
79
- }
80
- return null;
81
- }
82
- //# sourceMappingURL=validation.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/utils/validation.ts"],"names":[],"mappings":"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"}
@@ -1,37 +0,0 @@
1
- # ForgeCart deployment ignore file
2
- # Files and directories listed here will not be uploaded during deployment
3
-
4
- # Dependencies (will be installed during build)
5
- node_modules/
6
-
7
- # Development files
8
- .git/
9
- .gitignore
10
- .env
11
- .env.local
12
- .env.development
13
-
14
- # IDE
15
- .idea/
16
- .vscode/
17
- *.swp
18
- *.swo
19
-
20
- # Build artifacts (we build on the server)
21
- dist/
22
-
23
- # Test files
24
- __tests__/
25
- test/
26
- *.test.ts
27
- *.spec.ts
28
- coverage/
29
-
30
- # Documentation
31
- README.md
32
- CHANGELOG.md
33
- docs/
34
-
35
- # OS files
36
- .DS_Store
37
- Thumbs.db
@@ -1 +0,0 @@
1
- web: node main.js
@@ -1,16 +0,0 @@
1
- import { Module } from '@nestjs/common'
2
- import { ConfigModule } from '@nestjs/config'
3
- import { AppController } from './app.controller'
4
- import { AppService } from './app.service'
5
- import { ForgeCartService, ProductEventListenerService } from '../services'
6
-
7
- @Module({
8
- imports: [
9
- ConfigModule.forRoot({
10
- isGlobal: true,
11
- }),
12
- ],
13
- controllers: [AppController],
14
- providers: [AppService, ForgeCartService, ProductEventListenerService],
15
- })
16
- export class AppModule {}
@@ -1,62 +0,0 @@
1
- import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'
2
- import { ConfigService } from '@nestjs/config'
3
- import { ForgeCartSDK } from '@forgecart/sdk'
4
-
5
- /**
6
- * ForgeCart SDK Service
7
- *
8
- * Singleton service that manages the ForgeCart SDK instance.
9
- * The SDK is initialized once on module init to maintain
10
- * persistent socket connections for real-time features.
11
- */
12
- @Injectable()
13
- export class ForgeCartService implements OnModuleInit, OnModuleDestroy {
14
- private sdk: ForgeCartSDK | null = null
15
-
16
- constructor(private configService: ConfigService) {}
17
-
18
- onModuleInit(): void {
19
- const endpoint = this.configService.get<string>('FORGECART_API_URL')
20
- const token = this.configService.get<string>('FORGECART_CHANNEL_TOKEN')
21
-
22
- if (!token) {
23
- throw new Error('FORGECART_CHANNEL_TOKEN environment variable is required')
24
- }
25
-
26
- this.sdk = new ForgeCartSDK({
27
- endpoint: endpoint || 'http://localhost:3000',
28
- token,
29
- })
30
- }
31
-
32
- onModuleDestroy(): void {
33
- if (this.sdk) {
34
- this.sdk.dispose()
35
- }
36
- this.sdk = null
37
- }
38
-
39
- /**
40
- * Get the ForgeCart SDK instance
41
- */
42
- getSDK(): ForgeCartSDK {
43
- if (!this.sdk) {
44
- throw new Error('ForgeCart SDK not initialized')
45
- }
46
- return this.sdk
47
- }
48
-
49
- /**
50
- * Access Shop API operations
51
- */
52
- get shop() {
53
- return this.getSDK().shop
54
- }
55
-
56
- /**
57
- * Access Admin API operations (requires admin token)
58
- */
59
- get admin() {
60
- return this.getSDK().admin
61
- }
62
- }
@@ -1,2 +0,0 @@
1
- export { ForgeCartService } from './forgecart.service'
2
- export { ProductEventListenerService } from './product-event-listener.service'
@@ -1,150 +0,0 @@
1
- import {
2
- Injectable,
3
- OnModuleInit,
4
- OnModuleDestroy,
5
- Logger,
6
- } from '@nestjs/common'
7
- import { ConfigService } from '@nestjs/config'
8
- import { ForgeCartService } from './forgecart.service'
9
-
10
- interface EventSubscription {
11
- unsubscribe: () => void
12
- }
13
-
14
- @Injectable()
15
- export class ProductEventListenerService
16
- implements OnModuleInit, OnModuleDestroy
17
- {
18
- private readonly logger = new Logger(ProductEventListenerService.name)
19
- private subscriptions: EventSubscription[] = []
20
- private isAuthenticated = false
21
-
22
- constructor(
23
- private readonly forgeCart: ForgeCartService,
24
- private readonly configService: ConfigService
25
- ) {}
26
-
27
- async onModuleInit(): Promise<void> {
28
- await this.initialize()
29
- }
30
-
31
- onModuleDestroy(): void {
32
- this.cleanup()
33
- }
34
-
35
- private async initialize(): Promise<void> {
36
- const username = this.configService.get<string>('FORGECART_ADMIN_USERNAME')
37
- const password = this.configService.get<string>('FORGECART_ADMIN_PASSWORD')
38
-
39
- // Skip if credentials are not provided
40
- if (!username || !password) {
41
- this.logger.warn(
42
- 'FORGECART_ADMIN_USERNAME and FORGECART_ADMIN_PASSWORD not set. ' +
43
- 'Product event listeners will not be registered.'
44
- )
45
- return
46
- }
47
-
48
- try {
49
- // Login with admin credentials
50
- const loginResult = await this.forgeCart.admin.administrator.login({
51
- username,
52
- password,
53
- })
54
-
55
- const login = (
56
- loginResult as { login?: { __typename?: string; message?: string } }
57
- )?.login
58
- if (login?.__typename !== 'CurrentUser') {
59
- this.logger.error(
60
- 'Admin login failed:',
61
- login?.message || 'Unknown error'
62
- )
63
- return
64
- }
65
-
66
- this.isAuthenticated = true
67
- this.logger.log('Successfully authenticated as admin')
68
-
69
- // Register event handlers
70
- this.registerEventHandlers()
71
- } catch (error) {
72
- this.logger.error('Failed to initialize product event listener:', error)
73
- }
74
- }
75
-
76
- private registerEventHandlers(): void {
77
- if (!this.isAuthenticated) return
78
-
79
- const sdk = this.forgeCart.getSDK()
80
-
81
- // Non-blocking handlers
82
- const productUpdatedSub = sdk.admin.registerEventHandler(
83
- 'product.updated',
84
- (event) => {
85
- this.logger.log(`Product updated: ${JSON.stringify(event)}`)
86
- this.handleProductUpdated(event)
87
- }
88
- )
89
- this.subscriptions.push(productUpdatedSub)
90
-
91
- const productCreatedSub = sdk.admin.registerEventHandler(
92
- 'product.created',
93
- (event) => {
94
- this.logger.log(`Product created: ${JSON.stringify(event)}`)
95
- this.handleProductCreated(event)
96
- }
97
- )
98
- this.subscriptions.push(productCreatedSub)
99
-
100
- const productDeletedSub = sdk.admin.registerEventHandler(
101
- 'product.deleted',
102
- (event) => {
103
- this.logger.log(`Product deleted: ${JSON.stringify(event)}`)
104
- this.handleProductDeleted(event)
105
- }
106
- )
107
- this.subscriptions.push(productDeletedSub)
108
-
109
- // Blocking handler (must complete within 1000ms)
110
- const variantUpdatedSub = sdk.admin.registerBlockingEventHandler(
111
- 'product.variant.updated',
112
- async (event) => {
113
- this.logger.log(
114
- `Product variant updated (blocking): ${JSON.stringify(event)}`
115
- )
116
- await this.handleVariantUpdated(event)
117
- }
118
- )
119
- this.subscriptions.push(variantUpdatedSub)
120
-
121
- this.logger.log('Product event handlers registered successfully')
122
- }
123
-
124
- private handleProductUpdated(event: unknown): void {
125
- // Implement custom logic here
126
- this.logger.debug('handleProductUpdated called', event)
127
- }
128
-
129
- private handleProductCreated(event: unknown): void {
130
- // Implement custom logic here
131
- this.logger.debug('handleProductCreated called', event)
132
- }
133
-
134
- private handleProductDeleted(event: unknown): void {
135
- // Implement custom logic here
136
- this.logger.debug('handleProductDeleted called', event)
137
- }
138
-
139
- private async handleVariantUpdated(event: unknown): Promise<void> {
140
- // Blocking handler - must complete within 1000ms
141
- this.logger.debug('handleVariantUpdated called', event)
142
- }
143
-
144
- private cleanup(): void {
145
- for (const subscription of this.subscriptions) {
146
- subscription.unsubscribe()
147
- }
148
- this.subscriptions = []
149
- }
150
- }
@@ -1,16 +0,0 @@
1
- import { waitForPortOpen } from '@nx/node/utils'
2
-
3
- /* eslint-disable */
4
- var __TEARDOWN_MESSAGE__: string
5
-
6
- module.exports = async function () {
7
- // Start services that the app needs to run (e.g. database, docker-compose, etc.).
8
- console.log('\nSetting up...\n')
9
-
10
- const host = process.env.HOST ?? 'localhost'
11
- const port = process.env.PORT ? Number(process.env.PORT) : 8080 // Match application's default port
12
- await waitForPortOpen(port, { host })
13
-
14
- // Hint: Use `globalThis` to pass variables to global teardown.
15
- globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n'
16
- }
@@ -1,9 +0,0 @@
1
- /* eslint-disable */
2
- import axios from 'axios'
3
-
4
- module.exports = async function () {
5
- // Configure axios for tests to use.
6
- const host = process.env.HOST ?? 'localhost'
7
- const port = process.env.PORT ?? '8080' // Match application's default port
8
- axios.defaults.baseURL = `http://${host}:${port}`
9
- }
@@ -1,64 +0,0 @@
1
- # ForgeCart deployment ignore file
2
- # Files and directories listed here will not be uploaded during deployment
3
-
4
- # Dependencies - only exclude root node_modules (standalone has its own)
5
- /node_modules/
6
-
7
- # Development files
8
- .git/
9
- .gitignore
10
- .env
11
- .env.local
12
- .env.development
13
- .env.development.local
14
-
15
- # IDE
16
- .idea/
17
- .vscode/
18
- *.swp
19
- *.swo
20
-
21
- # Build artifacts - exclude root level only (standalone has nested .next that must be kept)
22
- /.next/cache/
23
- /.next/server/
24
- /.next/types/
25
- /.next/trace
26
- /.next/trace-build
27
- /.next/dev/
28
- /.next/build/
29
- /.next/diagnostics/
30
- # Keep .next/standalone/ and everything inside it
31
- /out/
32
-
33
- # Test files
34
- __tests__/
35
- *.test.ts
36
- *.test.tsx
37
- *.spec.ts
38
- *.spec.tsx
39
- coverage/
40
- specs/
41
-
42
- # Source files - not needed for runtime
43
- src/
44
-
45
- # Config files not needed at runtime
46
- tsconfig.json
47
- tsconfig.spec.json
48
- project.json
49
- jest.config.cts
50
- eslint.config.mjs
51
- postcss.config.js
52
- tailwind.config.js
53
- .swcrc
54
- index.d.ts
55
- next-env.d.ts
56
-
57
- # Documentation
58
- README.md
59
- CHANGELOG.md
60
- docs/
61
-
62
- # OS files
63
- .DS_Store
64
- Thumbs.db
@@ -1 +0,0 @@
1
- web: node .next/standalone/apps/storefront/server.js
@@ -1,11 +0,0 @@
1
- {
2
- "name": "storefront",
3
- "version": "1.0.0",
4
- "private": true,
5
- "engines": {
6
- "node": ">=20.0.0"
7
- },
8
- "scripts": {
9
- "start": "node .next/standalone/apps/storefront/server.js"
10
- }
11
- }
@@ -1,5 +0,0 @@
1
- module.exports = {
2
- plugins: {
3
- '@tailwindcss/postcss': {},
4
- },
5
- }
@@ -1,77 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { useCart } from '../../context/CartContext'
5
- import { CartItem } from '../../components/CartItem'
6
-
7
- export default function CartPage() {
8
- const { cart, loading, itemCount } = useCart()
9
-
10
- if (loading && !cart) {
11
- return (
12
- <div className="max-w-4xl mx-auto px-4 py-8">
13
- <h1 className="text-3xl font-bold mb-8 text-gray-900">Your Cart</h1>
14
- <p className="text-gray-600">Loading cart...</p>
15
- </div>
16
- )
17
- }
18
-
19
- if (!cart || cart.lines.length === 0) {
20
- return (
21
- <div className="max-w-4xl mx-auto px-4 py-8">
22
- <h1 className="text-3xl font-bold mb-8 text-gray-900">Your Cart</h1>
23
- <p className="text-gray-600 mb-4">Your cart is empty.</p>
24
- <Link
25
- href="/"
26
- className="inline-block bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700"
27
- >
28
- Continue Shopping
29
- </Link>
30
- </div>
31
- )
32
- }
33
-
34
- const subtotal = (cart.subTotalWithTax / 100).toFixed(2)
35
- const total = (cart.totalWithTax / 100).toFixed(2)
36
-
37
- return (
38
- <div className="max-w-4xl mx-auto px-4 py-8">
39
- <h1 className="text-3xl font-bold mb-8 text-gray-900">Your Cart</h1>
40
-
41
- <div className="bg-white rounded-lg shadow p-6">
42
- {cart.lines
43
- .filter((line) => line.productVariant)
44
- .map((line) => (
45
- <CartItem key={line.id} line={line as never} />
46
- ))}
47
-
48
- <div className="mt-6 pt-4 border-t">
49
- <div className="flex justify-between text-lg mb-2">
50
- <span className="text-gray-600">Subtotal ({itemCount} items)</span>
51
- <span className="font-semibold">
52
- {subtotal} {cart.currencyCode}
53
- </span>
54
- </div>
55
- <div className="flex justify-between text-xl font-bold">
56
- <span>Total</span>
57
- <span>
58
- {total} {cart.currencyCode}
59
- </span>
60
- </div>
61
- </div>
62
-
63
- <div className="mt-6 flex gap-4">
64
- <Link
65
- href="/"
66
- className="flex-1 text-center border border-gray-300 py-3 rounded-lg hover:bg-gray-50"
67
- >
68
- Continue Shopping
69
- </Link>
70
- <button className="flex-1 bg-blue-600 text-white py-3 rounded-lg hover:bg-blue-700">
71
- Checkout
72
- </button>
73
- </div>
74
- </div>
75
- </div>
76
- )
77
- }
@@ -1 +0,0 @@
1
- @import "tailwindcss";