cf-yoyo 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 (141) hide show
  1. package/.eslintrc.json +28 -0
  2. package/.github/workflows/ci.yml +96 -0
  3. package/.prettierrc.json +10 -0
  4. package/CHANGELOG.md +55 -0
  5. package/README.md +138 -0
  6. package/__tests__/cli-e2e.test.ts +145 -0
  7. package/__tests__/config.test.ts +268 -0
  8. package/__tests__/filesystem.test.ts +453 -0
  9. package/__tests__/logger.test.ts +274 -0
  10. package/__tests__/template-engine.test.ts +450 -0
  11. package/__tests__/types.test.ts +25 -0
  12. package/deep_todos.md +766 -0
  13. package/dist/cli/commands/create.d.ts +26 -0
  14. package/dist/cli/commands/create.d.ts.map +1 -0
  15. package/dist/cli/commands/create.js +308 -0
  16. package/dist/cli/commands/create.js.map +1 -0
  17. package/dist/cli/commands/git.d.ts +10 -0
  18. package/dist/cli/commands/git.d.ts.map +1 -0
  19. package/dist/cli/commands/git.js +887 -0
  20. package/dist/cli/commands/git.js.map +1 -0
  21. package/dist/cli/commands/list.d.ts +10 -0
  22. package/dist/cli/commands/list.d.ts.map +1 -0
  23. package/dist/cli/commands/list.js +90 -0
  24. package/dist/cli/commands/list.js.map +1 -0
  25. package/dist/cli/index.d.ts +15 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +62 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/core/config.d.ts +35 -0
  30. package/dist/core/config.d.ts.map +1 -0
  31. package/dist/core/config.js +260 -0
  32. package/dist/core/config.js.map +1 -0
  33. package/dist/core/filesystem.d.ts +84 -0
  34. package/dist/core/filesystem.d.ts.map +1 -0
  35. package/dist/core/filesystem.js +417 -0
  36. package/dist/core/filesystem.js.map +1 -0
  37. package/dist/core/git-token.d.ts +81 -0
  38. package/dist/core/git-token.d.ts.map +1 -0
  39. package/dist/core/git-token.js +244 -0
  40. package/dist/core/git-token.js.map +1 -0
  41. package/dist/core/git.d.ts +70 -0
  42. package/dist/core/git.d.ts.map +1 -0
  43. package/dist/core/git.js +367 -0
  44. package/dist/core/git.js.map +1 -0
  45. package/dist/core/prompt.d.ts +28 -0
  46. package/dist/core/prompt.d.ts.map +1 -0
  47. package/dist/core/prompt.js +253 -0
  48. package/dist/core/prompt.js.map +1 -0
  49. package/dist/core/template-engine.d.ts +52 -0
  50. package/dist/core/template-engine.d.ts.map +1 -0
  51. package/dist/core/template-engine.js +308 -0
  52. package/dist/core/template-engine.js.map +1 -0
  53. package/dist/core/template-manager.d.ts +54 -0
  54. package/dist/core/template-manager.d.ts.map +1 -0
  55. package/dist/core/template-manager.js +330 -0
  56. package/dist/core/template-manager.js.map +1 -0
  57. package/dist/index.d.ts +12 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +19 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/types/index.d.ts +244 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +51 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/dist/utils/logger.d.ts +68 -0
  66. package/dist/utils/logger.d.ts.map +1 -0
  67. package/dist/utils/logger.js +140 -0
  68. package/dist/utils/logger.js.map +1 -0
  69. package/memory.md +241 -0
  70. package/need-debug.md +395 -0
  71. package/package.json +42 -0
  72. package/src/cli/commands/create.ts +326 -0
  73. package/src/cli/commands/git.ts +1001 -0
  74. package/src/cli/commands/list.ts +97 -0
  75. package/src/cli/index.ts +71 -0
  76. package/src/core/config.ts +262 -0
  77. package/src/core/filesystem.ts +408 -0
  78. package/src/core/git-token.ts +248 -0
  79. package/src/core/git.ts +384 -0
  80. package/src/core/prompt.ts +345 -0
  81. package/src/core/template-engine.ts +324 -0
  82. package/src/core/template-manager.ts +338 -0
  83. package/src/index.ts +19 -0
  84. package/src/types/index.ts +259 -0
  85. package/src/utils/logger.ts +150 -0
  86. package/templates/pages/basic/README.md.mustache +63 -0
  87. package/templates/pages/basic/package.json.mustache +23 -0
  88. package/templates/pages/basic/public/css/style.css +199 -0
  89. package/templates/pages/basic/public/index.html.mustache +72 -0
  90. package/templates/pages/basic/public/js/main.js +103 -0
  91. package/templates/pages/basic/template.json +38 -0
  92. package/templates/pages/basic/tsconfig.json +21 -0
  93. package/templates/pages/basic/wrangler.toml.mustache +14 -0
  94. package/templates/pages/basic-js/README.md.mustache +62 -0
  95. package/templates/pages/basic-js/package.json.mustache +25 -0
  96. package/templates/pages/basic-js/public/css/style.css +212 -0
  97. package/templates/pages/basic-js/public/index.html.mustache +53 -0
  98. package/templates/pages/basic-js/public/js/main.js +134 -0
  99. package/templates/pages/basic-js/template.json +35 -0
  100. package/templates/pages/basic-js/wrangler.toml.mustache +14 -0
  101. package/templates/pages/react/README.md.mustache +97 -0
  102. package/templates/pages/react/index.html.mustache +14 -0
  103. package/templates/pages/react/package.json.mustache +34 -0
  104. package/templates/pages/react/src/App.css +168 -0
  105. package/templates/pages/react/src/App.tsx.mustache +62 -0
  106. package/templates/pages/react/src/index.css +53 -0
  107. package/templates/pages/react/src/main.tsx.mustache +10 -0
  108. package/templates/pages/react/src/vite-env.d.ts +1 -0
  109. package/templates/pages/react/template.json +54 -0
  110. package/templates/pages/react/tsconfig.json +21 -0
  111. package/templates/pages/react/tsconfig.node.json +10 -0
  112. package/templates/pages/react/vite.config.ts +16 -0
  113. package/templates/worker/basic/README.md.mustache +56 -0
  114. package/templates/worker/basic/package.json.mustache +29 -0
  115. package/templates/worker/basic/src/index.ts.mustache +125 -0
  116. package/templates/worker/basic/template.json +30 -0
  117. package/templates/worker/basic/tsconfig.json +24 -0
  118. package/templates/worker/basic/wrangler.toml.mustache +33 -0
  119. package/templates/worker/basic-js/README.md.mustache +55 -0
  120. package/templates/worker/basic-js/package.json.mustache +25 -0
  121. package/templates/worker/basic-js/src/index.js.mustache +146 -0
  122. package/templates/worker/basic-js/template.json +27 -0
  123. package/templates/worker/basic-js/wrangler.toml.mustache +33 -0
  124. package/templates/worker/hono/README.md.mustache +79 -0
  125. package/templates/worker/hono/package.json.mustache +33 -0
  126. package/templates/worker/hono/src/index.ts.mustache +64 -0
  127. package/templates/worker/hono/src/routes/index.ts.mustache +165 -0
  128. package/templates/worker/hono/template.json +34 -0
  129. package/templates/worker/hono/tsconfig.json +24 -0
  130. package/templates/worker/hono/wrangler.toml.mustache +36 -0
  131. package/templates/worker/hono-js/README.md.mustache +67 -0
  132. package/templates/worker/hono-js/package.json.mustache +29 -0
  133. package/templates/worker/hono-js/src/index.js.mustache +55 -0
  134. package/templates/worker/hono-js/src/routes/index.js.mustache +127 -0
  135. package/templates/worker/hono-js/template.json +31 -0
  136. package/templates/worker/hono-js/wrangler.toml.mustache +36 -0
  137. package/thoughts/ledgers/CONTINUITY_ses_287e.md +74 -0
  138. package/thoughts/ledgers/CONTINUITY_ses_28b5.md +85 -0
  139. package/tsconfig.json +30 -0
  140. package/vitest.config.ts +20 -0
  141. package//351/240/205/347/233/256/350/241/250.md +140 -0
@@ -0,0 +1,274 @@
1
+ /**
2
+ * logger.ts 模組測試
3
+ * 測試日誌輸出功能
4
+ */
5
+
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import { LoggerClass, logger } from '../src/utils/logger';
8
+ import { LogLevel } from '../src/types';
9
+
10
+ describe('Logger', () => {
11
+ let consoleSpy: ReturnType<typeof vi.spyOn>;
12
+
13
+ beforeEach(() => {
14
+ consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
15
+ });
16
+
17
+ afterEach(() => {
18
+ consoleSpy.mockRestore();
19
+ });
20
+
21
+ describe('constructor', () => {
22
+ it('should create logger instance with default level', () => {
23
+ const logger = new LoggerClass();
24
+ expect(logger).toBeInstanceOf(LoggerClass);
25
+ expect(logger.getLevel()).toBe(LogLevel.INFO);
26
+ });
27
+
28
+ it('should create logger with custom level', () => {
29
+ const logger = new LoggerClass({ level: LogLevel.DEBUG });
30
+ expect(logger.getLevel()).toBe(LogLevel.DEBUG);
31
+ });
32
+
33
+ it('should create logger with timestamp option', () => {
34
+ const logger = new LoggerClass({ timestamp: true });
35
+ expect(logger).toBeInstanceOf(LoggerClass);
36
+ });
37
+
38
+ it('should create logger with color disabled', () => {
39
+ const logger = new LoggerClass({ color: false });
40
+ expect(logger).toBeInstanceOf(LoggerClass);
41
+ });
42
+
43
+ it('should create logger with silent mode', () => {
44
+ const logger = new LoggerClass({ silent: true });
45
+ expect(logger).toBeInstanceOf(LoggerClass);
46
+ });
47
+ });
48
+
49
+ describe('setLevel', () => {
50
+ it('should change log level', () => {
51
+ const logger = new LoggerClass({ level: LogLevel.INFO });
52
+ logger.setLevel(LogLevel.DEBUG);
53
+ expect(logger.getLevel()).toBe(LogLevel.DEBUG);
54
+ });
55
+
56
+ it('should set level to ERROR', () => {
57
+ const logger = new LoggerClass();
58
+ logger.setLevel(LogLevel.ERROR);
59
+ expect(logger.getLevel()).toBe(LogLevel.ERROR);
60
+ });
61
+ });
62
+
63
+ describe('getLevel', () => {
64
+ it('should return current log level', () => {
65
+ const logger = new LoggerClass({ level: LogLevel.WARN });
66
+ expect(logger.getLevel()).toBe(LogLevel.WARN);
67
+ });
68
+ });
69
+
70
+ describe('debug', () => {
71
+ it('should log debug messages at DEBUG level', () => {
72
+ const logger = new LoggerClass({ level: LogLevel.DEBUG });
73
+ logger.debug('Test debug message');
74
+ expect(consoleSpy).toHaveBeenCalled();
75
+ });
76
+
77
+ it('should not log debug messages at INFO level', () => {
78
+ const logger = new LoggerClass({ level: LogLevel.INFO });
79
+ logger.debug('Test debug message');
80
+ expect(consoleSpy).not.toHaveBeenCalled();
81
+ });
82
+
83
+ it('should respect silent mode', () => {
84
+ const logger = new LoggerClass({ silent: true, level: LogLevel.DEBUG });
85
+ logger.debug('Silent debug message');
86
+ expect(consoleSpy).not.toHaveBeenCalled();
87
+ });
88
+ });
89
+
90
+ describe('info', () => {
91
+ it('should log info messages at INFO level', () => {
92
+ const logger = new LoggerClass({ level: LogLevel.INFO });
93
+ logger.info('Test info message');
94
+ expect(consoleSpy).toHaveBeenCalled();
95
+ });
96
+
97
+ it('should log info messages at DEBUG level', () => {
98
+ const logger = new LoggerClass({ level: LogLevel.DEBUG });
99
+ logger.info('Test info message');
100
+ expect(consoleSpy).toHaveBeenCalled();
101
+ });
102
+
103
+ it('should not log info messages at WARN level', () => {
104
+ const logger = new LoggerClass({ level: LogLevel.WARN });
105
+ logger.info('Test info message');
106
+ expect(consoleSpy).not.toHaveBeenCalled();
107
+ });
108
+ });
109
+
110
+ describe('warn', () => {
111
+ it('should log warn messages at WARN level', () => {
112
+ const logger = new LoggerClass({ level: LogLevel.WARN });
113
+ logger.warn('Test warn message');
114
+ expect(consoleSpy).toHaveBeenCalled();
115
+ });
116
+
117
+ it('should log warn messages at INFO level', () => {
118
+ const logger = new LoggerClass({ level: LogLevel.INFO });
119
+ logger.warn('Test warn message');
120
+ expect(consoleSpy).toHaveBeenCalled();
121
+ });
122
+
123
+ it('should not log warn messages at ERROR level', () => {
124
+ const logger = new LoggerClass({ level: LogLevel.ERROR });
125
+ logger.warn('Test warn message');
126
+ expect(consoleSpy).not.toHaveBeenCalled();
127
+ });
128
+ });
129
+
130
+ describe('error', () => {
131
+ it('should log error messages at ERROR level', () => {
132
+ const logger = new LoggerClass({ level: LogLevel.ERROR });
133
+ logger.error('Test error message');
134
+ expect(consoleSpy).toHaveBeenCalled();
135
+ });
136
+
137
+ it('should log error messages at DEBUG level', () => {
138
+ const logger = new LoggerClass({ level: LogLevel.DEBUG });
139
+ logger.error('Test error message');
140
+ expect(consoleSpy).toHaveBeenCalled();
141
+ });
142
+ });
143
+
144
+ describe('success', () => {
145
+ it('should log success messages at INFO level', () => {
146
+ const logger = new LoggerClass({ level: LogLevel.INFO });
147
+ logger.success('Test success message');
148
+ expect(consoleSpy).toHaveBeenCalled();
149
+ });
150
+
151
+ it('should not log success messages at WARN level', () => {
152
+ const logger = new LoggerClass({ level: LogLevel.WARN });
153
+ logger.success('Test success message');
154
+ expect(consoleSpy).not.toHaveBeenCalled();
155
+ });
156
+ });
157
+
158
+ describe('icon', () => {
159
+ it('should log icon messages at INFO level', () => {
160
+ const logger = new LoggerClass({ level: LogLevel.INFO });
161
+ logger.icon('✓', 'Test icon message');
162
+ expect(consoleSpy).toHaveBeenCalled();
163
+ });
164
+
165
+ it('should not log icon messages at WARN level', () => {
166
+ const logger = new LoggerClass({ level: LogLevel.WARN });
167
+ logger.icon('✓', 'Test icon message');
168
+ expect(consoleSpy).not.toHaveBeenCalled();
169
+ });
170
+
171
+ it('should use plain text when color is disabled', () => {
172
+ const logger = new LoggerClass({ level: LogLevel.INFO, color: false });
173
+ logger.icon('✓', 'Test icon message');
174
+ expect(consoleSpy).toHaveBeenCalled();
175
+ });
176
+ });
177
+
178
+ describe('empty', () => {
179
+ it('should output empty line', () => {
180
+ const logger = new LoggerClass();
181
+ logger.empty();
182
+ expect(consoleSpy).toHaveBeenCalledWith('');
183
+ });
184
+ });
185
+
186
+ describe('divider', () => {
187
+ it('should output default divider', () => {
188
+ const logger = new LoggerClass({ color: false });
189
+ logger.divider();
190
+ expect(consoleSpy).toHaveBeenCalled();
191
+ });
192
+
193
+ it('should output custom divider', () => {
194
+ const logger = new LoggerClass({ color: false });
195
+ logger.divider('=', 20);
196
+ expect(consoleSpy).toHaveBeenCalledWith('='.repeat(20));
197
+ });
198
+
199
+ it('should use color when enabled', () => {
200
+ const logger = new LoggerClass({ color: true });
201
+ logger.divider('─', 40);
202
+ expect(consoleSpy).toHaveBeenCalled();
203
+ });
204
+ });
205
+
206
+ describe('timestamp option', () => {
207
+ it('should include timestamp when enabled', () => {
208
+ const logger = new LoggerClass({ timestamp: true, level: LogLevel.INFO });
209
+ logger.info('Test message');
210
+ expect(consoleSpy).toHaveBeenCalled();
211
+ // The output should contain timestamp in format [YYYY-MM-DD HH:MM:SS]
212
+ const call = consoleSpy.mock.calls[0][0];
213
+ expect(call).toMatch(/\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]/);
214
+ });
215
+
216
+ it('should not include timestamp when disabled', () => {
217
+ const logger = new LoggerClass({ timestamp: false, level: LogLevel.INFO });
218
+ logger.info('Test message');
219
+ expect(consoleSpy).toHaveBeenCalled();
220
+ const call = consoleSpy.mock.calls[0][0];
221
+ expect(call).not.toMatch(/\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]/);
222
+ });
223
+ });
224
+
225
+ describe('log level filtering', () => {
226
+ it('should only log ERROR at ERROR level', () => {
227
+ const logger = new LoggerClass({ level: LogLevel.ERROR });
228
+ logger.debug('debug');
229
+ logger.info('info');
230
+ logger.warn('warn');
231
+ logger.error('error');
232
+
233
+ expect(consoleSpy).toHaveBeenCalledTimes(1);
234
+ expect(consoleSpy.mock.calls[0][0]).toContain('ERROR');
235
+ });
236
+
237
+ it('should log WARN and ERROR at WARN level', () => {
238
+ const logger = new LoggerClass({ level: LogLevel.WARN });
239
+ logger.debug('debug');
240
+ logger.info('info');
241
+ logger.warn('warn');
242
+ logger.error('error');
243
+
244
+ expect(consoleSpy).toHaveBeenCalledTimes(2);
245
+ });
246
+
247
+ it('should log INFO, WARN and ERROR at INFO level', () => {
248
+ const logger = new LoggerClass({ level: LogLevel.INFO });
249
+ logger.debug('debug');
250
+ logger.info('info');
251
+ logger.warn('warn');
252
+ logger.error('error');
253
+
254
+ expect(consoleSpy).toHaveBeenCalledTimes(3);
255
+ });
256
+
257
+ it('should log all at DEBUG level', () => {
258
+ const logger = new LoggerClass({ level: LogLevel.DEBUG });
259
+ logger.debug('debug');
260
+ logger.info('info');
261
+ logger.warn('warn');
262
+ logger.error('error');
263
+
264
+ expect(consoleSpy).toHaveBeenCalledTimes(4);
265
+ });
266
+ });
267
+
268
+ describe('singleton instance', () => {
269
+ it('should export a logger instance', () => {
270
+ expect(logger).toBeDefined();
271
+ expect(logger).toBeInstanceOf(LoggerClass);
272
+ });
273
+ });
274
+ });