@icarusmx/creta 1.3.4 → 1.3.5

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 (38) hide show
  1. package/bin/creta.js +8 -1576
  2. package/codex-refactor.txt +13 -0
  3. package/lib/builders/LessonBuilder.js +228 -0
  4. package/lib/builders/MenuBuilder.js +154 -0
  5. package/lib/builders/ProjectBuilder.js +56 -0
  6. package/lib/cli/index.js +81 -0
  7. package/lib/commands/help.js +5 -0
  8. package/lib/constants/paths.js +9 -0
  9. package/lib/data/enunciados.js +44 -0
  10. package/lib/data/lessons/index.js +25 -0
  11. package/lib/data/lessons/lesson1-system-decomposition.js +312 -0
  12. package/lib/data/lessons/lesson2-object-requests.js +318 -0
  13. package/lib/data/lessons/lesson3-only-way.js +349 -0
  14. package/lib/data/lessons/lesson4-operation-signatures.js +332 -0
  15. package/lib/data/lessons/lesson5-interface-set.js +341 -0
  16. package/lib/data/lessons/lesson6-interface-design.js +407 -0
  17. package/lib/data/lessons/lesson7-object-definition.js +375 -0
  18. package/lib/data/lessons/sintaxis/terminal-basico.js +46 -0
  19. package/lib/data/menus.js +43 -0
  20. package/lib/data/messages.js +28 -0
  21. package/lib/executors/enunciados-executor.js +63 -0
  22. package/lib/executors/portfolio-executor.js +167 -0
  23. package/lib/executors/proyectos-executor.js +23 -0
  24. package/lib/executors/sintaxis-executor.js +7 -0
  25. package/lib/templates/LevelModifier.js +287 -0
  26. package/lib/utils/file-utils.js +18 -0
  27. package/lib/utils/input.js +15 -0
  28. package/lib/utils/output.js +4 -0
  29. package/package.json +4 -1
  30. package/refactor.txt +581 -0
  31. package/test/enunciados.test.js +72 -0
  32. package/lessons/lesson1-system-decomposition.js +0 -313
  33. package/lessons/lesson2-object-requests.js +0 -309
  34. package/lessons/lesson3-only-way.js +0 -324
  35. package/lessons/lesson4-operation-signatures.js +0 -319
  36. package/lessons/lesson5-interface-set.js +0 -326
  37. package/lessons/lesson6-interface-design.js +0 -391
  38. package/lessons/lesson7-object-definition.js +0 -300
@@ -0,0 +1,13 @@
1
+ # creta cli refactor - progress log
2
+
3
+ ## 2025-02-14
4
+ - restored `bin/creta.js` to the original working version so the CLI behaved correctly again.
5
+ - extracted reusable data for the welcome banner, help text, and enunciados into `lib/data/messages.js` and `lib/data/enunciados.js`.
6
+ - added initial utilities (`lib/utils/input.js`, `lib/utils/output.js`, `lib/utils/file-utils.js`) plus `lib/templates/LevelModifier.js` to reuse template logic.
7
+
8
+ ## 2025-02-15
9
+ - introduced Discord-style builders (`lib/builders/MenuBuilder.js`, `lib/builders/ProjectBuilder.js`).
10
+ - defined menu configurations in `lib/data/menus.js` and template paths in `lib/constants/paths.js`.
11
+ - created executors for enunciados, sintaxis, proyectos, and portafolio to encapsulate orchestration logic.
12
+ - added `lib/cli/index.js` as the central command router and reduced `bin/creta.js` to a minimal entry point (<20 lines).
13
+ - verified primary commands (`help`, `portafolio-*`, invalid command handling) after restructuring.
@@ -0,0 +1,228 @@
1
+ import { createPromptInterface, askQuestion } from '../utils/input.js'
2
+ import { clearConsole } from '../utils/output.js'
3
+
4
+ const DEFAULT_WAIT_MESSAGE = '\nPresiona Enter para continuar...'
5
+
6
+ export class LessonBuilder {
7
+ constructor(lessonData) {
8
+ this.lesson = lessonData
9
+ this.rl = null
10
+ }
11
+
12
+ async start() {
13
+ if (!this.lesson) {
14
+ throw new Error('Se requiere un objeto de lección para ejecutar el LessonBuilder')
15
+ }
16
+
17
+ this.rl = createPromptInterface()
18
+
19
+ try {
20
+ const flow = this.collectActions()
21
+ await this.executeActions(flow)
22
+ } finally {
23
+ this.rl.close()
24
+ this.rl = null
25
+ }
26
+ }
27
+
28
+ collectActions() {
29
+ const actions = []
30
+
31
+ const parts = [
32
+ this.lesson.title && { type: 'text', text: this.lesson.title },
33
+ this.lesson.subtitle && { type: 'text', text: this.lesson.subtitle },
34
+ this.lesson.intro && { type: 'intro', ...this.lesson.intro },
35
+ this.lesson.flow,
36
+ this.lesson.actions,
37
+ this.lesson.sections,
38
+ this.lesson.steps,
39
+ this.lesson.body,
40
+ this.lesson.conclusion
41
+ ]
42
+
43
+ for (const part of parts) {
44
+ if (!part) continue
45
+
46
+ if (Array.isArray(part)) {
47
+ actions.push(...part)
48
+ } else if (Array.isArray(part.actions)) {
49
+ actions.push(...part.actions)
50
+ } else {
51
+ actions.push(part)
52
+ }
53
+ }
54
+
55
+ return actions
56
+ }
57
+
58
+ async executeActions(actions = []) {
59
+ for (const action of actions) {
60
+ if (!action) continue
61
+ await this.executeAction(action)
62
+ }
63
+ }
64
+
65
+ async executeAction(action) {
66
+ const type = action.type || 'text'
67
+
68
+ switch (type) {
69
+ case 'clear':
70
+ this.handleClear(action)
71
+ break
72
+ case 'intro':
73
+ await this.handleIntro(action)
74
+ break
75
+ case 'pause':
76
+ case 'wait':
77
+ await this.handlePause(action)
78
+ break
79
+ case 'code':
80
+ this.handleCode(action)
81
+ break
82
+ case 'sleep':
83
+ await this.handleSleep(action)
84
+ break
85
+ case 'command-intro':
86
+ await this.handleCommandIntro(action)
87
+ break
88
+ case 'text':
89
+ default:
90
+ this.handleText(action)
91
+ break
92
+ }
93
+ }
94
+
95
+ handleClear(action) {
96
+ if (action.message) {
97
+ console.log(action.message)
98
+ }
99
+
100
+ if (typeof action.useConsoleClear === 'boolean' && action.useConsoleClear) {
101
+ console.clear()
102
+ return
103
+ }
104
+
105
+ clearConsole()
106
+ }
107
+
108
+ handleText(action) {
109
+ const lines = this.normalizeLines(action)
110
+ lines.forEach(line => console.log(line))
111
+ if (action.extraNewLine) {
112
+ console.log('')
113
+ }
114
+ }
115
+
116
+ handleCode(action) {
117
+ if (action.title) {
118
+ console.log(`\n${action.title}`)
119
+ console.log('━'.repeat(action.width || 50))
120
+ }
121
+
122
+ const lines = typeof action.code === 'string' ? action.code.split('\n') : []
123
+ lines.forEach(line => console.log(this.formatCode(line)))
124
+
125
+ if (action.title) {
126
+ console.log('━'.repeat(action.width || 50))
127
+ }
128
+
129
+ if (action.after) {
130
+ const afterLines = Array.isArray(action.after) ? action.after : [action.after]
131
+ afterLines.forEach(line => console.log(line))
132
+ }
133
+ }
134
+
135
+ async handlePause(action) {
136
+ const message = action.message || DEFAULT_WAIT_MESSAGE
137
+ await askQuestion(this.rl, message)
138
+ if (action.appendNewLines !== false) {
139
+ console.log('\n')
140
+ }
141
+ }
142
+
143
+ async handleSleep(action) {
144
+ const duration = typeof action.duration === 'number' ? action.duration : 800
145
+ await new Promise(resolve => setTimeout(resolve, duration))
146
+ }
147
+
148
+ normalizeLines(action) {
149
+ if (Array.isArray(action.lines)) {
150
+ return action.lines.map(item => (item === null || item === undefined ? '' : String(item)))
151
+ }
152
+
153
+ if (typeof action.lines === 'string') {
154
+ return action.lines.split('\n')
155
+ }
156
+
157
+ if (Array.isArray(action.text)) {
158
+ return action.text.map(item => (item === null || item === undefined ? '' : String(item)))
159
+ }
160
+
161
+ if (typeof action.text === 'string') {
162
+ return action.text.split('\n')
163
+ }
164
+
165
+ if (typeof action.text !== 'undefined') {
166
+ return [String(action.text)]
167
+ }
168
+
169
+ return []
170
+ }
171
+
172
+ formatCode(line = '') {
173
+ const colors = {
174
+ keyword: '\u001b[35m',
175
+ property: '\u001b[32m',
176
+ string: '\u001b[33m',
177
+ comment: '\u001b[90m',
178
+ reset: '\u001b[0m'
179
+ }
180
+
181
+ return line
182
+ .replace(/\b(class|constructor|return|if|const|let|new|async|await|throw|try|catch)\b/g, `${colors.keyword}$1${colors.reset}`)
183
+ .replace(/\bthis\./g, `${colors.property}this.${colors.reset}`)
184
+ .replace(/'([^']*)'/g, (_, inner) => `${colors.string}'${inner}'${colors.reset}`)
185
+ .replace(/"([^\"]*)"/g, (_, inner) => `${colors.string}"${inner}"${colors.reset}`)
186
+ .replace(/`([^`]*)`/g, (_, inner) => `${colors.string}\`${inner}\`${colors.reset}`)
187
+ .replace(/\/\/.*$/g, match => `${colors.comment}${match}${colors.reset}`)
188
+ }
189
+
190
+ async handleIntro(action) {
191
+ // Show definition first
192
+ if (action.definition) {
193
+ console.log(action.definition)
194
+ }
195
+
196
+ // Wait for Enter
197
+ await askQuestion(this.rl, '\nPresiona Enter para comenzar...')
198
+
199
+ // Show explanation and detail
200
+ if (action.explanation) {
201
+ console.log(`\n${action.explanation}`)
202
+ }
203
+
204
+ if (action.detail) {
205
+ console.log('')
206
+ console.log(action.detail)
207
+ }
208
+ }
209
+
210
+ async handleCommandIntro(action) {
211
+ console.log('')
212
+ console.log(action.description)
213
+ console.log('')
214
+ console.log(action.explanation)
215
+
216
+ if (action.example) {
217
+ console.log('')
218
+ console.log(`Ejemplo: ${action.example}`)
219
+ }
220
+
221
+ console.log('')
222
+ console.log(action.instruction)
223
+
224
+ if (!action.exitOnComplete) {
225
+ await askQuestion(this.rl, DEFAULT_WAIT_MESSAGE)
226
+ }
227
+ }
228
+ }
@@ -0,0 +1,154 @@
1
+ import { createPromptInterface, askQuestion } from '../utils/input.js'
2
+ import { clearConsole } from '../utils/output.js'
3
+
4
+ export class MenuBuilder {
5
+ constructor(config) {
6
+ this.config = config
7
+ }
8
+
9
+ async show() {
10
+ if (this.config?.options?.length === 0) {
11
+ return null
12
+ }
13
+
14
+ if (!process.stdin.isTTY) {
15
+ return this.showFallback()
16
+ }
17
+
18
+ try {
19
+ return await this.showInteractive()
20
+ } catch (error) {
21
+ console.log('\nModo interactivo no disponible, usando selección numérica...\n')
22
+ return await this.showFallback()
23
+ }
24
+ }
25
+
26
+ renderHeader() {
27
+ clearConsole()
28
+
29
+ if (this.config.banner) {
30
+ console.log(this.config.banner)
31
+ }
32
+
33
+ if (this.config.description) {
34
+ const lines = Array.isArray(this.config.description)
35
+ ? this.config.description
36
+ : [this.config.description]
37
+ lines.forEach(line => console.log(line))
38
+ console.log('')
39
+ }
40
+
41
+ if (this.config.title) {
42
+ console.log(this.config.title)
43
+ }
44
+ }
45
+
46
+ renderOption(option, isSelected, index) {
47
+ const prefix = isSelected ? '▶ ' : ' '
48
+ const label = option.title || option.label || `Opción ${index + 1}`
49
+
50
+ if (isSelected) {
51
+ console.log(`\x1b[36m${prefix}${label}\x1b[0m`)
52
+ } else {
53
+ console.log(`${prefix}${label}`)
54
+ }
55
+
56
+ if (option.description) {
57
+ console.log(` ${option.description}`)
58
+ }
59
+ console.log('')
60
+ }
61
+
62
+ async showInteractive() {
63
+ if (typeof process.stdin.setRawMode !== 'function') {
64
+ throw new Error('setRawMode not available')
65
+ }
66
+
67
+ let selectedIndex = 0
68
+
69
+ const render = () => {
70
+ this.renderHeader()
71
+ this.config.options.forEach((option, index) => {
72
+ this.renderOption(option, index === selectedIndex, index)
73
+ })
74
+ }
75
+
76
+ return new Promise((resolve) => {
77
+ process.stdin.setRawMode(true)
78
+ process.stdin.resume()
79
+ process.stdin.setEncoding('utf8')
80
+
81
+ const onKeyPress = (key) => {
82
+ if (key === 'q' || key === '\u0003') {
83
+ cleanup()
84
+ resolve(null)
85
+ return
86
+ }
87
+
88
+ if (key === '\r' || key === '\n') {
89
+ const choice = this.config.options[selectedIndex]
90
+ cleanup()
91
+ resolve(choice)
92
+ return
93
+ }
94
+
95
+ if (key === '\u001b[A') {
96
+ selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : this.config.options.length - 1
97
+ render()
98
+ } else if (key === '\u001b[B') {
99
+ selectedIndex = selectedIndex < this.config.options.length - 1 ? selectedIndex + 1 : 0
100
+ render()
101
+ }
102
+ }
103
+
104
+ const cleanup = () => {
105
+ process.stdin.setRawMode(false)
106
+ process.stdin.removeListener('data', onKeyPress)
107
+ }
108
+
109
+ process.stdin.on('data', onKeyPress)
110
+ render()
111
+ })
112
+ }
113
+
114
+ async showFallback() {
115
+ const rl = createPromptInterface()
116
+
117
+ if (this.config.banner) {
118
+ console.log(this.config.banner)
119
+ }
120
+
121
+ if (this.config.description) {
122
+ const lines = Array.isArray(this.config.description)
123
+ ? this.config.description
124
+ : [this.config.description]
125
+ lines.forEach(line => console.log(line))
126
+ console.log('')
127
+ }
128
+
129
+ if (this.config.title) {
130
+ console.log(this.config.title)
131
+ }
132
+
133
+ this.config.options.forEach((option, index) => {
134
+ const label = option.title || option.label || `Opción ${index + 1}`
135
+ console.log(`${index + 1}. ${label}`)
136
+ if (option.description) {
137
+ console.log(` ${option.description}`)
138
+ }
139
+ })
140
+
141
+ console.log('')
142
+ const answer = await askQuestion(rl, `Elige una opción (1-${this.config.options.length}) o 'q' para salir: `)
143
+
144
+ if (answer.toLowerCase() === 'q') {
145
+ rl.close()
146
+ return null
147
+ }
148
+
149
+ const selectedIndex = parseInt(answer, 10) - 1
150
+ const choice = this.config.options[selectedIndex]
151
+ rl.close()
152
+ return choice || null
153
+ }
154
+ }
@@ -0,0 +1,56 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import { isBinaryFile } from '../utils/file-utils.js'
4
+ import { LevelModifier } from '../templates/LevelModifier.js'
5
+
6
+ export class ProjectBuilder {
7
+ constructor(templatePath) {
8
+ this.templatePath = templatePath
9
+ }
10
+
11
+ createProject(targetDir, projectName, studentName, level) {
12
+ if (!fs.existsSync(this.templatePath)) {
13
+ throw new Error(`Template no encontrado en: ${this.templatePath}`)
14
+ }
15
+
16
+ if (fs.existsSync(targetDir)) {
17
+ throw new Error(`El directorio ${projectName} ya existe`)
18
+ }
19
+
20
+ fs.mkdirSync(targetDir, { recursive: true })
21
+ const modifier = new LevelModifier(level)
22
+ this.copyDirectory(this.templatePath, targetDir, projectName, studentName, modifier)
23
+ }
24
+
25
+ applyPlaceholders(content, projectName, studentName) {
26
+ return content
27
+ .replace(/\{\{PROJECT_NAME\}\}/g, projectName)
28
+ .replace(/\{\{STUDENT_NAME\}\}/g, studentName)
29
+ }
30
+
31
+ copyDirectory(source, target, projectName, studentName, modifier) {
32
+ const entries = fs.readdirSync(source)
33
+
34
+ for (const entry of entries) {
35
+ const sourcePath = path.join(source, entry)
36
+ const targetPath = path.join(target, entry)
37
+ const stats = fs.statSync(sourcePath)
38
+
39
+ if (stats.isDirectory()) {
40
+ fs.mkdirSync(targetPath, { recursive: true })
41
+ this.copyDirectory(sourcePath, targetPath, projectName, studentName, modifier)
42
+ continue
43
+ }
44
+
45
+ if (isBinaryFile(sourcePath)) {
46
+ fs.copyFileSync(sourcePath, targetPath)
47
+ continue
48
+ }
49
+
50
+ let content = fs.readFileSync(sourcePath, 'utf8')
51
+ content = modifier.apply(content, entry)
52
+ content = this.applyPlaceholders(content, projectName, studentName)
53
+ fs.writeFileSync(targetPath, content)
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,81 @@
1
+ import { MenuBuilder } from '../builders/MenuBuilder.js'
2
+ import { MAIN_MENU_CONFIG } from '../data/menus.js'
3
+ import { executeEnunciados } from '../executors/enunciados-executor.js'
4
+ import { executeProyectos } from '../executors/proyectos-executor.js'
5
+ import { executeSintaxis } from '../executors/sintaxis-executor.js'
6
+ import { executePortfolio } from '../executors/portfolio-executor.js'
7
+ import { showHelp } from '../commands/help.js'
8
+ import { CretaCodeSession } from '../session.js'
9
+
10
+ async function executeMainMenu() {
11
+ const menu = new MenuBuilder(MAIN_MENU_CONFIG)
12
+
13
+ while (true) {
14
+ const choice = await menu.show()
15
+ if (!choice) {
16
+ console.log('\nHecho con <3 por icarus.mx')
17
+ return
18
+ }
19
+
20
+ if (choice.id === 'sintaxis') {
21
+ await executeSintaxis()
22
+ } else if (choice.id === 'enunciados') {
23
+ await executeEnunciados()
24
+ } else if (choice.id === 'proyectos') {
25
+ await executeProyectos()
26
+ }
27
+ }
28
+ }
29
+
30
+ async function runCodeSession() {
31
+ const session = new CretaCodeSession()
32
+ await session.start()
33
+ }
34
+
35
+ const COMMANDS = new Map([
36
+ ['enunciados', () => executeEnunciados()],
37
+ ['sintaxis', () => executeSintaxis()],
38
+ ['proyectos', () => executeProyectos()],
39
+ ['portafolio', () => executePortfolio(0)],
40
+ ['code', () => runCodeSession()],
41
+ ['help', () => showHelp()],
42
+ ['ayuda', () => showHelp()]
43
+ ])
44
+
45
+ export async function handleCommand(command, args = []) {
46
+ if (!command) {
47
+ return true
48
+ }
49
+
50
+ const normalized = command.toLowerCase()
51
+
52
+ if (normalized.startsWith('portafolio')) {
53
+ const levelPart = normalized.split('-')[1]
54
+ const level = levelPart ? parseInt(levelPart, 10) : 0
55
+ await executePortfolio(Number.isNaN(level) ? 0 : level)
56
+ return true
57
+ }
58
+
59
+ const handler = COMMANDS.get(normalized)
60
+
61
+ if (!handler) {
62
+ console.log(`Comando no reconocido: ${command}`)
63
+ console.log("Escribe 'creta help' para ver comandos disponibles")
64
+ return false
65
+ }
66
+
67
+ await handler(args)
68
+ return true
69
+ }
70
+
71
+ export async function runCLI(args = []) {
72
+ const [command, ...rest] = args
73
+
74
+ if (!command) {
75
+ await executeMainMenu()
76
+ return 0
77
+ }
78
+
79
+ const handled = await handleCommand(command, rest)
80
+ return handled ? 0 : 1
81
+ }
@@ -0,0 +1,5 @@
1
+ import { HELP_TEXT } from '../data/messages.js'
2
+
3
+ export function showHelp() {
4
+ console.log(HELP_TEXT)
5
+ }
@@ -0,0 +1,9 @@
1
+ import path from 'path'
2
+ import { fileURLToPath } from 'url'
3
+
4
+ const __filename = fileURLToPath(import.meta.url)
5
+ const __dirname = path.dirname(__filename)
6
+
7
+ export const CLI_ROOT = path.resolve(__dirname, '../..')
8
+ export const TEMPLATES_ROOT = path.join(CLI_ROOT, 'templates')
9
+ export const SVELTEKIT_PORTFOLIO_TEMPLATE_PATH = path.join(TEMPLATES_ROOT, 'sveltekit-portfolio')
@@ -0,0 +1,44 @@
1
+ export const ENUNCIADOS = [
2
+ {
3
+ id: 1,
4
+ texto: "La parte difícil del diseño orientado a objetos es descomponer un sistema como un conjunto de objetos que interactúan entre sí.",
5
+ nivel: "Fundacional",
6
+ enfoque: "Descomposición de sistemas"
7
+ },
8
+ {
9
+ id: 2,
10
+ texto: "Los objetos interactúan entre sí a través de solicitudes.",
11
+ nivel: "Interacción",
12
+ enfoque: "Comunicación entre objetos"
13
+ },
14
+ {
15
+ id: 3,
16
+ texto: "Las solicitudes son la única forma de conseguir que un objeto lleve a cabo una operación.",
17
+ nivel: "Operaciones",
18
+ enfoque: "Mecanismo de ejecución"
19
+ },
20
+ {
21
+ id: 4,
22
+ texto: "Cada operación declarada por un objeto debe incluir:\na) nombre de la operación\nb) insumos necesarios para realizar la operación\nc) el valor que regresa tras ejecutar la operación\n\nEstos tres elementos constituyen la firma de operación.",
23
+ nivel: "Firmas",
24
+ enfoque: "Contratos de operación"
25
+ },
26
+ {
27
+ id: 5,
28
+ texto: "La interfaz de un objeto es el conjunto de todas sus firmas de operación.",
29
+ nivel: "Interfaces",
30
+ enfoque: "Definición de contratos"
31
+ },
32
+ {
33
+ id: 6,
34
+ texto: "El énfasis al diseñar los objetos debe estar en la definición de sus solicitudes e interfaces.",
35
+ nivel: "Diseño",
36
+ enfoque: "Metodología de desarrollo"
37
+ },
38
+ {
39
+ id: 7,
40
+ texto: "Un objeto es un conjunto de datos y procedimientos que operan sobre esos datos.",
41
+ nivel: "Definición",
42
+ enfoque: "Naturaleza del objeto"
43
+ }
44
+ ]
@@ -0,0 +1,25 @@
1
+ export { LESSON_1_SYSTEM_DECOMPOSITION } from './lesson1-system-decomposition.js'
2
+ export { LESSON_2_OBJECT_REQUESTS } from './lesson2-object-requests.js'
3
+ export { LESSON_3_ONLY_WAY } from './lesson3-only-way.js'
4
+ export { LESSON_4_OPERATION_SIGNATURES } from './lesson4-operation-signatures.js'
5
+ export { LESSON_5_INTERFACE_SET } from './lesson5-interface-set.js'
6
+ export { LESSON_6_INTERFACE_DESIGN } from './lesson6-interface-design.js'
7
+ export { LESSON_7_OBJECT_DEFINITION } from './lesson7-object-definition.js'
8
+
9
+ import { LESSON_1_SYSTEM_DECOMPOSITION } from './lesson1-system-decomposition.js'
10
+ import { LESSON_2_OBJECT_REQUESTS } from './lesson2-object-requests.js'
11
+ import { LESSON_3_ONLY_WAY } from './lesson3-only-way.js'
12
+ import { LESSON_4_OPERATION_SIGNATURES } from './lesson4-operation-signatures.js'
13
+ import { LESSON_5_INTERFACE_SET } from './lesson5-interface-set.js'
14
+ import { LESSON_6_INTERFACE_DESIGN } from './lesson6-interface-design.js'
15
+ import { LESSON_7_OBJECT_DEFINITION } from './lesson7-object-definition.js'
16
+
17
+ export const LESSONS_BY_ID = new Map([
18
+ [1, LESSON_1_SYSTEM_DECOMPOSITION],
19
+ [2, LESSON_2_OBJECT_REQUESTS],
20
+ [3, LESSON_3_ONLY_WAY],
21
+ [4, LESSON_4_OPERATION_SIGNATURES],
22
+ [5, LESSON_5_INTERFACE_SET],
23
+ [6, LESSON_6_INTERFACE_DESIGN],
24
+ [7, LESSON_7_OBJECT_DEFINITION]
25
+ ])