@epic-web/workshop-utils 6.47.6 → 6.47.7

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 (117) hide show
  1. package/dist/{esm/apps.server.d.ts → apps.server.d.ts} +1 -2
  2. package/dist/{esm/apps.server.js → apps.server.js} +11 -12
  3. package/dist/{esm/cache.server.d.ts → cache.server.d.ts} +1 -2
  4. package/dist/{esm/cache.server.js → cache.server.js} +5 -6
  5. package/dist/{esm/compile-mdx.server.d.ts → compile-mdx.server.d.ts} +2 -3
  6. package/dist/{esm/compile-mdx.server.js → compile-mdx.server.js} +3 -4
  7. package/dist/{esm/config.server.d.ts → config.server.d.ts} +0 -1
  8. package/dist/{esm/config.server.js → config.server.js} +2 -3
  9. package/dist/{esm/data-storage.server.d.ts → data-storage.server.d.ts} +0 -1
  10. package/dist/{esm/data-storage.server.js → data-storage.server.js} +0 -1
  11. package/dist/{esm/db.server.d.ts → db.server.d.ts} +1 -2
  12. package/dist/{esm/db.server.js → db.server.js} +3 -4
  13. package/dist/{esm/diff.server.d.ts → diff.server.d.ts} +2 -3
  14. package/dist/{esm/diff.server.js → diff.server.js} +5 -6
  15. package/dist/{esm/env.server.d.ts → env.server.d.ts} +0 -1
  16. package/dist/{esm/env.server.js → env.server.js} +1 -2
  17. package/dist/{esm/epic-api.server.d.ts → epic-api.server.d.ts} +1 -2
  18. package/dist/{esm/epic-api.server.js → epic-api.server.js} +7 -8
  19. package/dist/{esm/git.server.d.ts → git.server.d.ts} +1 -2
  20. package/dist/{esm/git.server.js → git.server.js} +8 -9
  21. package/dist/{esm/iframe-sync.d.ts → iframe-sync.d.ts} +0 -1
  22. package/dist/{esm/iframe-sync.js → iframe-sync.js} +0 -1
  23. package/dist/init-env.d.ts +2 -0
  24. package/dist/init-env.js +5 -0
  25. package/dist/{esm/launch-editor.server.d.ts → launch-editor.server.d.ts} +0 -1
  26. package/dist/{esm/launch-editor.server.js → launch-editor.server.js} +1 -2
  27. package/dist/{esm/logger.d.ts → logger.d.ts} +0 -1
  28. package/dist/{esm/logger.js → logger.js} +0 -1
  29. package/dist/{esm/modified-time.server.d.ts → modified-time.server.d.ts} +1 -2
  30. package/dist/{esm/modified-time.server.js → modified-time.server.js} +2 -3
  31. package/dist/{esm/notifications.server.d.ts → notifications.server.d.ts} +0 -1
  32. package/dist/{esm/notifications.server.js → notifications.server.js} +4 -5
  33. package/dist/{esm/playwright.server.d.ts → playwright.server.d.ts} +1 -2
  34. package/dist/{esm/playwright.server.js → playwright.server.js} +2 -3
  35. package/dist/{esm/process-manager.server.d.ts → process-manager.server.d.ts} +2 -3
  36. package/dist/{esm/process-manager.server.js → process-manager.server.js} +4 -5
  37. package/dist/{esm/request-context.server.d.ts → request-context.server.d.ts} +1 -2
  38. package/dist/{esm/request-context.server.js → request-context.server.js} +1 -2
  39. package/dist/{esm/test.d.ts → test.d.ts} +0 -1
  40. package/dist/{esm/test.js → test.js} +0 -1
  41. package/dist/{esm/timing.server.d.ts → timing.server.d.ts} +1 -2
  42. package/dist/{esm/timing.server.js → timing.server.js} +1 -2
  43. package/dist/{esm/user.server.d.ts → user.server.d.ts} +0 -1
  44. package/dist/{esm/user.server.js → user.server.js} +2 -3
  45. package/dist/{esm/utils.d.ts → utils.d.ts} +1 -2
  46. package/dist/{esm/utils.js → utils.js} +1 -2
  47. package/dist/utils.server.d.ts +7 -0
  48. package/dist/{esm/utils.server.js → utils.server.js} +4 -15
  49. package/dist/{esm/workshops.server.d.ts → workshops.server.d.ts} +0 -1
  50. package/dist/{esm/workshops.server.js → workshops.server.js} +1 -2
  51. package/package.json +56 -109
  52. package/dist/esm/apps.server.d.ts.map +0 -1
  53. package/dist/esm/apps.server.js.map +0 -1
  54. package/dist/esm/cache.server.d.ts.map +0 -1
  55. package/dist/esm/cache.server.js.map +0 -1
  56. package/dist/esm/compile-mdx.server.d.ts.map +0 -1
  57. package/dist/esm/compile-mdx.server.js.map +0 -1
  58. package/dist/esm/config.server.d.ts.map +0 -1
  59. package/dist/esm/config.server.js.map +0 -1
  60. package/dist/esm/config.test.d.ts +0 -2
  61. package/dist/esm/config.test.d.ts.map +0 -1
  62. package/dist/esm/config.test.js +0 -77
  63. package/dist/esm/config.test.js.map +0 -1
  64. package/dist/esm/data-storage.server.d.ts.map +0 -1
  65. package/dist/esm/data-storage.server.js.map +0 -1
  66. package/dist/esm/data-storage.test.d.ts +0 -2
  67. package/dist/esm/data-storage.test.d.ts.map +0 -1
  68. package/dist/esm/data-storage.test.js +0 -339
  69. package/dist/esm/data-storage.test.js.map +0 -1
  70. package/dist/esm/db.server.d.ts.map +0 -1
  71. package/dist/esm/db.server.js.map +0 -1
  72. package/dist/esm/diff.server.d.ts.map +0 -1
  73. package/dist/esm/diff.server.js.map +0 -1
  74. package/dist/esm/env.server.d.ts.map +0 -1
  75. package/dist/esm/env.server.js.map +0 -1
  76. package/dist/esm/epic-api.server.d.ts.map +0 -1
  77. package/dist/esm/epic-api.server.js.map +0 -1
  78. package/dist/esm/git.server.d.ts.map +0 -1
  79. package/dist/esm/git.server.js.map +0 -1
  80. package/dist/esm/iframe-sync.d.ts.map +0 -1
  81. package/dist/esm/iframe-sync.js.map +0 -1
  82. package/dist/esm/init-env.d.ts +0 -3
  83. package/dist/esm/init-env.d.ts.map +0 -1
  84. package/dist/esm/init-env.js +0 -6
  85. package/dist/esm/init-env.js.map +0 -1
  86. package/dist/esm/launch-editor.server.d.ts.map +0 -1
  87. package/dist/esm/launch-editor.server.js.map +0 -1
  88. package/dist/esm/logger.d.ts.map +0 -1
  89. package/dist/esm/logger.js.map +0 -1
  90. package/dist/esm/modified-time.server.d.ts.map +0 -1
  91. package/dist/esm/modified-time.server.js.map +0 -1
  92. package/dist/esm/notifications.server.d.ts.map +0 -1
  93. package/dist/esm/notifications.server.js.map +0 -1
  94. package/dist/esm/package.json +0 -3
  95. package/dist/esm/playwright.server.d.ts.map +0 -1
  96. package/dist/esm/playwright.server.js.map +0 -1
  97. package/dist/esm/process-manager.server.d.ts.map +0 -1
  98. package/dist/esm/process-manager.server.js.map +0 -1
  99. package/dist/esm/request-context.server.d.ts.map +0 -1
  100. package/dist/esm/request-context.server.js.map +0 -1
  101. package/dist/esm/test.d.ts.map +0 -1
  102. package/dist/esm/test.js.map +0 -1
  103. package/dist/esm/timing.server.d.ts.map +0 -1
  104. package/dist/esm/timing.server.js.map +0 -1
  105. package/dist/esm/user.server.d.ts.map +0 -1
  106. package/dist/esm/user.server.js.map +0 -1
  107. package/dist/esm/utils.d.ts.map +0 -1
  108. package/dist/esm/utils.js.map +0 -1
  109. package/dist/esm/utils.server.d.ts +0 -9
  110. package/dist/esm/utils.server.d.ts.map +0 -1
  111. package/dist/esm/utils.server.js.map +0 -1
  112. package/dist/esm/utils.test.d.ts +0 -2
  113. package/dist/esm/utils.test.d.ts.map +0 -1
  114. package/dist/esm/utils.test.js +0 -139
  115. package/dist/esm/utils.test.js.map +0 -1
  116. package/dist/esm/workshops.server.d.ts.map +0 -1
  117. package/dist/esm/workshops.server.js.map +0 -1
@@ -1,139 +0,0 @@
1
- import { test, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { getErrorMessage, handleGitHubRepoAndRoot } from './utils.js';
3
- // Setup console.error mocking for all tests
4
- beforeEach(() => {
5
- vi.spyOn(console, 'error').mockImplementation(() => { });
6
- });
7
- afterEach(() => {
8
- vi.restoreAllMocks();
9
- });
10
- test('getErrorMessage should return string errors as-is', () => {
11
- const error = 'Something went wrong';
12
- expect(getErrorMessage(error)).toBe('Something went wrong');
13
- });
14
- test('getErrorMessage should extract message from Error objects', () => {
15
- const error = new Error('Database connection failed');
16
- expect(getErrorMessage(error)).toBe('Database connection failed');
17
- });
18
- test('getErrorMessage should extract message from objects with message property', () => {
19
- const error = { message: 'Custom error message' };
20
- expect(getErrorMessage(error)).toBe('Custom error message');
21
- });
22
- test('getErrorMessage should handle objects with non-string message property', () => {
23
- const error = { message: 123 };
24
- const consoleSpy = vi.spyOn(console, 'error');
25
- expect(getErrorMessage(error)).toBe('Unknown Error');
26
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', error);
27
- });
28
- test('getErrorMessage should handle objects without message property', () => {
29
- const error = { code: 500, status: 'error' };
30
- const consoleSpy = vi.spyOn(console, 'error');
31
- expect(getErrorMessage(error)).toBe('Unknown Error');
32
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', error);
33
- });
34
- test('getErrorMessage should handle null errors', () => {
35
- const consoleSpy = vi.spyOn(console, 'error');
36
- expect(getErrorMessage(null)).toBe('Unknown Error');
37
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', null);
38
- });
39
- test('getErrorMessage should handle undefined errors', () => {
40
- const consoleSpy = vi.spyOn(console, 'error');
41
- expect(getErrorMessage(undefined)).toBe('Unknown Error');
42
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', undefined);
43
- });
44
- test('getErrorMessage should handle primitive non-string errors', () => {
45
- const consoleSpy = vi.spyOn(console, 'error');
46
- expect(getErrorMessage(123)).toBe('Unknown Error');
47
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', 123);
48
- expect(getErrorMessage(true)).toBe('Unknown Error');
49
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', true);
50
- });
51
- test('getErrorMessage should handle empty objects', () => {
52
- const error = {};
53
- const consoleSpy = vi.spyOn(console, 'error');
54
- expect(getErrorMessage(error)).toBe('Unknown Error');
55
- expect(consoleSpy).toHaveBeenCalledWith('Unable to get error message for error', error);
56
- });
57
- test('handleGitHubRepoAndRoot should handle githubRepo with trailing slash', () => {
58
- const result = handleGitHubRepoAndRoot({
59
- githubRepo: 'https://github.com/user/repo/',
60
- });
61
- expect(result).toEqual({
62
- githubRepo: 'https://github.com/user/repo',
63
- githubRoot: 'https://github.com/user/repo/tree/main',
64
- });
65
- });
66
- test('handleGitHubRepoAndRoot should handle githubRepo without trailing slash', () => {
67
- const result = handleGitHubRepoAndRoot({
68
- githubRepo: 'https://github.com/user/repo',
69
- });
70
- expect(result).toEqual({
71
- githubRepo: 'https://github.com/user/repo',
72
- githubRoot: 'https://github.com/user/repo/tree/main',
73
- });
74
- });
75
- test('handleGitHubRepoAndRoot should handle githubRoot with blob path', () => {
76
- const result = handleGitHubRepoAndRoot({
77
- githubRoot: 'https://github.com/user/repo/blob/main/src/file.ts',
78
- });
79
- expect(result).toEqual({
80
- githubRepo: 'https://github.com/user/repo',
81
- githubRoot: 'https://github.com/user/repo/tree/main',
82
- });
83
- });
84
- test('handleGitHubRepoAndRoot should handle githubRoot with tree path', () => {
85
- const result = handleGitHubRepoAndRoot({
86
- githubRoot: 'https://github.com/user/repo/tree/develop/src',
87
- });
88
- expect(result).toEqual({
89
- githubRepo: 'https://github.com/user/repo',
90
- githubRoot: 'https://github.com/user/repo/tree/main',
91
- });
92
- });
93
- test('handleGitHubRepoAndRoot should handle githubRoot without path', () => {
94
- const result = handleGitHubRepoAndRoot({
95
- githubRoot: 'https://github.com/user/repo',
96
- });
97
- expect(result).toEqual({
98
- githubRepo: 'https://github.com/user/repo',
99
- githubRoot: 'https://github.com/user/repo/tree/main',
100
- });
101
- });
102
- test('handleGitHubRepoAndRoot should prioritize githubRepo over githubRoot when both provided', () => {
103
- const result = handleGitHubRepoAndRoot({
104
- githubRepo: 'https://github.com/user/repo',
105
- githubRoot: 'https://github.com/other/repo/blob/main/src/file.ts',
106
- });
107
- expect(result).toEqual({
108
- githubRepo: 'https://github.com/user/repo',
109
- githubRoot: 'https://github.com/user/repo/tree/main',
110
- });
111
- });
112
- test('handleGitHubRepoAndRoot should throw error when neither githubRepo nor githubRoot provided', () => {
113
- expect(() => handleGitHubRepoAndRoot({})).toThrow('Either githubRepo or githubRoot is required. Please ensure your epicshop package.json config includes either githubRepo or githubRoot configuration.');
114
- });
115
- test('handleGitHubRepoAndRoot should throw error when both githubRepo and githubRoot are undefined', () => {
116
- expect(() => handleGitHubRepoAndRoot({
117
- githubRepo: undefined,
118
- githubRoot: undefined,
119
- })).toThrow('Either githubRepo or githubRoot is required. Please ensure your epicshop package.json config includes either githubRepo or githubRoot configuration.');
120
- });
121
- test('handleGitHubRepoAndRoot should handle githubRoot with complex blob path', () => {
122
- const result = handleGitHubRepoAndRoot({
123
- githubRoot: 'https://github.com/user/repo/blob/feature-branch/packages/app/src/components/button.tsx',
124
- });
125
- expect(result).toEqual({
126
- githubRepo: 'https://github.com/user/repo',
127
- githubRoot: 'https://github.com/user/repo/tree/main',
128
- });
129
- });
130
- test('handleGitHubRepoAndRoot should handle githubRoot with complex tree path', () => {
131
- const result = handleGitHubRepoAndRoot({
132
- githubRoot: 'https://github.com/user/repo/tree/develop/packages/workshop/src/utils.ts',
133
- });
134
- expect(result).toEqual({
135
- githubRepo: 'https://github.com/user/repo',
136
- githubRoot: 'https://github.com/user/repo/tree/main',
137
- });
138
- });
139
- //# sourceMappingURL=utils.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect, vi, beforeEach, afterEach } from 'vitest'\nimport { getErrorMessage, handleGitHubRepoAndRoot } from './utils.js'\n\n// Setup console.error mocking for all tests\nbeforeEach(() => {\n\tvi.spyOn(console, 'error').mockImplementation(() => {})\n})\n\nafterEach(() => {\n\tvi.restoreAllMocks()\n})\n\ntest('getErrorMessage should return string errors as-is', () => {\n\tconst error = 'Something went wrong'\n\texpect(getErrorMessage(error)).toBe('Something went wrong')\n})\n\ntest('getErrorMessage should extract message from Error objects', () => {\n\tconst error = new Error('Database connection failed')\n\texpect(getErrorMessage(error)).toBe('Database connection failed')\n})\n\ntest('getErrorMessage should extract message from objects with message property', () => {\n\tconst error = { message: 'Custom error message' }\n\texpect(getErrorMessage(error)).toBe('Custom error message')\n})\n\ntest('getErrorMessage should handle objects with non-string message property', () => {\n\tconst error = { message: 123 }\n\tconst consoleSpy = vi.spyOn(console, 'error')\n\n\texpect(getErrorMessage(error)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\terror,\n\t)\n})\n\ntest('getErrorMessage should handle objects without message property', () => {\n\tconst error = { code: 500, status: 'error' }\n\tconst consoleSpy = vi.spyOn(console, 'error')\n\n\texpect(getErrorMessage(error)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\terror,\n\t)\n})\n\ntest('getErrorMessage should handle null errors', () => {\n\tconst consoleSpy = vi.spyOn(console, 'error')\n\n\texpect(getErrorMessage(null)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\tnull,\n\t)\n})\n\ntest('getErrorMessage should handle undefined errors', () => {\n\tconst consoleSpy = vi.spyOn(console, 'error')\n\n\texpect(getErrorMessage(undefined)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\tundefined,\n\t)\n})\n\ntest('getErrorMessage should handle primitive non-string errors', () => {\n\tconst consoleSpy = vi.spyOn(console, 'error')\n\n\texpect(getErrorMessage(123)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\t123,\n\t)\n\n\texpect(getErrorMessage(true)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\ttrue,\n\t)\n})\n\ntest('getErrorMessage should handle empty objects', () => {\n\tconst error = {}\n\tconst consoleSpy = vi.spyOn(console, 'error')\n\n\texpect(getErrorMessage(error)).toBe('Unknown Error')\n\texpect(consoleSpy).toHaveBeenCalledWith(\n\t\t'Unable to get error message for error',\n\t\terror,\n\t)\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRepo with trailing slash', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRepo: 'https://github.com/user/repo/',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRepo without trailing slash', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRoot with blob path', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRoot: 'https://github.com/user/repo/blob/main/src/file.ts',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRoot with tree path', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRoot: 'https://github.com/user/repo/tree/develop/src',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRoot without path', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRoot: 'https://github.com/user/repo',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should prioritize githubRepo over githubRoot when both provided', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/other/repo/blob/main/src/file.ts',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should throw error when neither githubRepo nor githubRoot provided', () => {\n\texpect(() => handleGitHubRepoAndRoot({})).toThrow(\n\t\t'Either githubRepo or githubRoot is required. Please ensure your epicshop package.json config includes either githubRepo or githubRoot configuration.',\n\t)\n})\n\ntest('handleGitHubRepoAndRoot should throw error when both githubRepo and githubRoot are undefined', () => {\n\texpect(() =>\n\t\thandleGitHubRepoAndRoot({\n\t\t\tgithubRepo: undefined,\n\t\t\tgithubRoot: undefined,\n\t\t}),\n\t).toThrow(\n\t\t'Either githubRepo or githubRoot is required. Please ensure your epicshop package.json config includes either githubRepo or githubRoot configuration.',\n\t)\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRoot with complex blob path', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRoot:\n\t\t\t'https://github.com/user/repo/blob/feature-branch/packages/app/src/components/button.tsx',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n\ntest('handleGitHubRepoAndRoot should handle githubRoot with complex tree path', () => {\n\tconst result = handleGitHubRepoAndRoot({\n\t\tgithubRoot:\n\t\t\t'https://github.com/user/repo/tree/develop/packages/workshop/src/utils.ts',\n\t})\n\n\texpect(result).toEqual({\n\t\tgithubRepo: 'https://github.com/user/repo',\n\t\tgithubRoot: 'https://github.com/user/repo/tree/main',\n\t})\n})\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"workshops.server.d.ts","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,YAAY;;;;;;EAEhB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AA2B1D,wBAAsB,UAAU,IAAI,OAAO,CAAC,eAAe,CAAC,CAS3D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAOlD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAGnE;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxE;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CA4CzD;AAED,wBAAsB,WAAW,CAChC,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQ/B;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAKvE;AAED,wBAAsB,iBAAiB,CACtC,YAAY,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAI/B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACnE,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxD,kBAAkB,EAAE,OAAO,CAAA;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC,CA6HD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"workshops.server.js","sourceRoot":"","sources":["../../src/workshops.server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { promises as fs } from 'node:fs'\nimport * as os from 'node:os'\nimport * as path from 'node:path'\nimport { z } from 'zod'\nimport { resolvePrimaryDir } from './data-storage.server.js'\n\nconst CONFIG_FILE = 'workshops-config.json'\n\n// Schema for the epicshop property in package.json\nconst EpicshopConfigSchema = z.object({\n\ttitle: z.string(),\n\tsubtitle: z.string().optional(),\n\tproduct: z\n\t\t.object({\n\t\t\thost: z.string().optional(),\n\t\t\tslug: z.string().optional(),\n\t\t\tlogo: z.string().optional(),\n\t\t\tdisplayName: z.string().optional(),\n\t\t\tdisplayNameShort: z.string().optional(),\n\t\t})\n\t\t.optional(),\n})\n\n// Schema for workshop configuration (stored settings only)\nconst ConfigSchema = z.object({\n\treposDirectory: z.string().optional(),\n})\n\nexport type Workshop = {\n\tname: string\n\ttitle: string\n\tsubtitle?: string\n\trepoName: string\n\tpath: string\n}\n\nexport type WorkshopsConfig = z.infer<typeof ConfigSchema>\n\nfunction getDefaultReposDirectory(): string {\n\treturn path.join(os.homedir(), 'epic-workshops')\n}\n\nfunction resolveConfigPath(): string {\n\treturn path.join(resolvePrimaryDir(), CONFIG_FILE)\n}\n\nasync function ensureDir(dir: string) {\n\ttry {\n\t\tawait fs.mkdir(dir, { recursive: true, mode: 0o700 })\n\t} catch {}\n\ttry {\n\t\tawait fs.chmod(dir, 0o700)\n\t} catch {}\n}\n\nasync function atomicWriteJSON(filePath: string, data: unknown) {\n\tconst dir = path.dirname(filePath)\n\tawait ensureDir(dir)\n\tconst tmp = path.join(dir, `.tmp-${randomUUID()}`)\n\tawait fs.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 0o600 })\n\tawait fs.rename(tmp, filePath)\n}\n\nexport async function loadConfig(): Promise<WorkshopsConfig> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tconst txt = await fs.readFile(configPath, 'utf8')\n\t\tconst data = JSON.parse(txt)\n\t\treturn ConfigSchema.parse(data)\n\t} catch {\n\t\treturn {}\n\t}\n}\n\nexport async function saveConfig(config: WorkshopsConfig): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\tawait atomicWriteJSON(configPath, config)\n}\n\nexport async function deleteConfig(): Promise<void> {\n\tconst configPath = resolveConfigPath()\n\ttry {\n\t\tawait fs.unlink(configPath)\n\t} catch {\n\t\t// File doesn't exist, which is fine\n\t}\n}\n\nexport async function getReposDirectory(): Promise<string> {\n\tconst config = await loadConfig()\n\treturn config.reposDirectory || getDefaultReposDirectory()\n}\n\nexport async function isReposDirectoryConfigured(): Promise<boolean> {\n\tconst config = await loadConfig()\n\treturn Boolean(config.reposDirectory)\n}\n\nexport function getDefaultReposDir(): string {\n\treturn getDefaultReposDirectory()\n}\n\nexport async function setReposDirectory(directory: string): Promise<void> {\n\tconst config = await loadConfig()\n\tconfig.reposDirectory = path.resolve(directory)\n\tawait saveConfig(config)\n}\n\n/**\n * Scan a directory for workshops (directories with package.json containing \"epicshop\" property)\n */\nexport async function listWorkshops(): Promise<Workshop[]> {\n\tconst reposDir = await getReposDirectory()\n\n\t// Check if directory exists\n\ttry {\n\t\tawait fs.access(reposDir)\n\t} catch {\n\t\treturn []\n\t}\n\n\tconst entries = await fs.readdir(reposDir, { withFileTypes: true })\n\tconst workshops: Workshop[] = []\n\n\tfor (const entry of entries) {\n\t\tif (!entry.isDirectory()) continue\n\n\t\tconst workshopPath = path.join(reposDir, entry.name)\n\t\tconst pkgPath = path.join(workshopPath, 'package.json')\n\n\t\ttry {\n\t\t\tconst pkgContent = await fs.readFile(pkgPath, 'utf8')\n\t\t\tconst pkg = JSON.parse(pkgContent) as {\n\t\t\t\tname?: string\n\t\t\t\tepicshop?: unknown\n\t\t\t}\n\n\t\t\tif (pkg.epicshop) {\n\t\t\t\tconst epicshopConfig = EpicshopConfigSchema.safeParse(pkg.epicshop)\n\t\t\t\tif (epicshopConfig.success) {\n\t\t\t\t\tworkshops.push({\n\t\t\t\t\t\tname: pkg.name || entry.name,\n\t\t\t\t\t\ttitle: epicshopConfig.data.title,\n\t\t\t\t\t\tsubtitle: epicshopConfig.data.subtitle,\n\t\t\t\t\t\trepoName: entry.name,\n\t\t\t\t\t\tpath: workshopPath,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not a valid workshop directory, skip\n\t\t}\n\t}\n\n\treturn workshops\n}\n\nexport async function getWorkshop(\n\tidOrName: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.find(\n\t\t(w) =>\n\t\t\tw.name.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.repoName.toLowerCase() === idOrName.toLowerCase() ||\n\t\t\tw.title.toLowerCase() === idOrName.toLowerCase(),\n\t)\n}\n\nexport async function workshopExists(repoName: string): Promise<boolean> {\n\tconst workshops = await listWorkshops()\n\treturn workshops.some(\n\t\t(w) => w.repoName.toLowerCase() === repoName.toLowerCase(),\n\t)\n}\n\nexport async function getWorkshopByPath(\n\tworkshopPath: string,\n): Promise<Workshop | undefined> {\n\tconst workshops = await listWorkshops()\n\tconst resolvedPath = path.resolve(workshopPath)\n\treturn workshops.find((w) => path.resolve(w.path) === resolvedPath)\n}\n\n/**\n * Check for unpushed changes in a git repository\n * Returns info about unpushed commits across all branches\n */\nexport async function getUnpushedChanges(repoPath: string): Promise<{\n\thasUnpushed: boolean\n\tbranches: Array<{ name: string; unpushedCount: number }>\n\tuncommittedChanges: boolean\n\tsummary: string[]\n}> {\n\tconst { execSync } = await import('node:child_process')\n\n\tconst result = {\n\t\thasUnpushed: false,\n\t\tbranches: [] as Array<{ name: string; unpushedCount: number }>,\n\t\tuncommittedChanges: false,\n\t\tsummary: [] as string[],\n\t}\n\n\ttry {\n\t\t// Check if it's a git repository\n\t\texecSync('git rev-parse --git-dir', {\n\t\t\tcwd: repoPath,\n\t\t\tstdio: 'pipe',\n\t\t})\n\t} catch {\n\t\t// Not a git repository\n\t\treturn result\n\t}\n\n\ttry {\n\t\t// Check for uncommitted changes\n\t\tconst status = execSync('git status --porcelain', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tif (status) {\n\t\t\tresult.uncommittedChanges = true\n\t\t\tresult.hasUnpushed = true\n\t\t\tconst lines = status.split('\\n')\n\t\t\tconst modified = lines.filter(\n\t\t\t\t(l) => l.startsWith(' M') || l.startsWith('M '),\n\t\t\t).length\n\t\t\tconst added = lines.filter(\n\t\t\t\t(l) => l.startsWith('A ') || l.startsWith('??'),\n\t\t\t).length\n\t\t\tconst deleted = lines.filter(\n\t\t\t\t(l) => l.startsWith(' D') || l.startsWith('D '),\n\t\t\t).length\n\n\t\t\tconst parts = []\n\t\t\tif (modified > 0) parts.push(`${modified} modified`)\n\t\t\tif (added > 0) parts.push(`${added} untracked/added`)\n\t\t\tif (deleted > 0) parts.push(`${deleted} deleted`)\n\t\t\tif (parts.length > 0) {\n\t\t\t\tresult.summary.push(`Uncommitted changes: ${parts.join(', ')}`)\n\t\t\t}\n\t\t}\n\n\t\t// Get all local branches\n\t\tconst branchOutput = execSync('git branch', {\n\t\t\tcwd: repoPath,\n\t\t\tencoding: 'utf8',\n\t\t}).trim()\n\n\t\tconst branches = branchOutput\n\t\t\t.split('\\n')\n\t\t\t.map((b) => b.replace(/^\\*?\\s*/, '').trim())\n\t\t\t.filter(Boolean)\n\n\t\tfor (const branch of branches) {\n\t\t\ttry {\n\t\t\t\t// Check if branch has an upstream\n\t\t\t\tconst upstream = execSync(\n\t\t\t\t\t`git rev-parse --abbrev-ref ${branch}@{upstream}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\t// Count unpushed commits\n\t\t\t\tconst unpushedOutput = execSync(\n\t\t\t\t\t`git rev-list --count ${upstream}..${branch}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t},\n\t\t\t\t).trim()\n\n\t\t\t\tconst unpushedCount = parseInt(unpushedOutput, 10)\n\t\t\t\tif (unpushedCount > 0) {\n\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount })\n\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t`Branch \"${branch}\": ${unpushedCount} unpushed commit${unpushedCount > 1 ? 's' : ''}`,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Branch has no upstream, check if it has any commits not in any remote\n\t\t\t\ttry {\n\t\t\t\t\tconst allRemotes = execSync('git remote', {\n\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t}).trim()\n\n\t\t\t\t\tif (allRemotes) {\n\t\t\t\t\t\t// Branch exists but has no upstream tracking\n\t\t\t\t\t\tconst commitCount = execSync(`git rev-list --count ${branch}`, {\n\t\t\t\t\t\t\tcwd: repoPath,\n\t\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\t}).trim()\n\n\t\t\t\t\t\tconst count = parseInt(commitCount, 10)\n\t\t\t\t\t\tif (count > 0) {\n\t\t\t\t\t\t\tresult.hasUnpushed = true\n\t\t\t\t\t\t\tresult.branches.push({ name: branch, unpushedCount: count })\n\t\t\t\t\t\t\tresult.summary.push(\n\t\t\t\t\t\t\t\t`Branch \"${branch}\": ${count} local commit${count > 1 ? 's' : ''} (no upstream)`,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors for individual branches\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Error checking git status, assume no unpushed changes\n\t}\n\n\treturn result\n}\n\n/**\n * Delete a workshop directory\n */\nexport async function deleteWorkshop(workshopPath: string): Promise<void> {\n\tawait fs.rm(workshopPath, { recursive: true, force: true })\n}\n"]}