@l4yercak3/cli 1.3.2 → 2.0.0-alpha.1
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.
- package/README.md +10 -220
- package/dist/api/client.d.ts +12 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +37 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/platform.d.ts +161 -0
- package/dist/api/platform.d.ts.map +1 -0
- package/dist/api/platform.js +70 -0
- package/dist/api/platform.js.map +1 -0
- package/dist/bin/sevenlayers.d.ts +3 -0
- package/dist/bin/sevenlayers.d.ts.map +1 -0
- package/dist/bin/sevenlayers.js +198 -0
- package/dist/bin/sevenlayers.js.map +1 -0
- package/dist/commands/agent/catalog.d.ts +5 -0
- package/dist/commands/agent/catalog.d.ts.map +1 -0
- package/dist/commands/agent/catalog.js +142 -0
- package/dist/commands/agent/catalog.js.map +1 -0
- package/dist/commands/agent/drift.d.ts +5 -0
- package/dist/commands/agent/drift.d.ts.map +1 -0
- package/dist/commands/agent/drift.js +113 -0
- package/dist/commands/agent/drift.js.map +1 -0
- package/dist/commands/agent/init.d.ts +5 -0
- package/dist/commands/agent/init.d.ts.map +1 -0
- package/dist/commands/agent/init.js +75 -0
- package/dist/commands/agent/init.js.map +1 -0
- package/dist/commands/agent/permissions.d.ts +5 -0
- package/dist/commands/agent/permissions.d.ts.map +1 -0
- package/dist/commands/agent/permissions.js +88 -0
- package/dist/commands/agent/permissions.js.map +1 -0
- package/dist/commands/agent/runner.d.ts +14 -0
- package/dist/commands/agent/runner.d.ts.map +1 -0
- package/dist/commands/agent/runner.js +59 -0
- package/dist/commands/agent/runner.js.map +1 -0
- package/dist/commands/agent/shared.d.ts +13 -0
- package/dist/commands/agent/shared.d.ts.map +1 -0
- package/dist/commands/agent/shared.js +31 -0
- package/dist/commands/agent/shared.js.map +1 -0
- package/dist/commands/agent/template.d.ts +5 -0
- package/dist/commands/agent/template.d.ts.map +1 -0
- package/dist/commands/agent/template.js +104 -0
- package/dist/commands/agent/template.js.map +1 -0
- package/dist/commands/app/connect.d.ts +7 -0
- package/dist/commands/app/connect.d.ts.map +1 -0
- package/dist/commands/app/connect.js +12 -0
- package/dist/commands/app/connect.js.map +1 -0
- package/dist/commands/app/init.d.ts +7 -0
- package/dist/commands/app/init.d.ts.map +1 -0
- package/dist/commands/app/init.js +12 -0
- package/dist/commands/app/init.js.map +1 -0
- package/dist/commands/app/link.d.ts +3 -0
- package/dist/commands/app/link.d.ts.map +1 -0
- package/dist/commands/app/link.js +92 -0
- package/dist/commands/app/link.js.map +1 -0
- package/dist/commands/app/pages.d.ts +15 -0
- package/dist/commands/app/pages.d.ts.map +1 -0
- package/dist/commands/app/pages.js +180 -0
- package/dist/commands/app/pages.js.map +1 -0
- package/dist/commands/app/register.d.ts +3 -0
- package/dist/commands/app/register.d.ts.map +1 -0
- package/dist/commands/app/register.js +120 -0
- package/dist/commands/app/register.js.map +1 -0
- package/dist/commands/app/remote.d.ts +14 -0
- package/dist/commands/app/remote.d.ts.map +1 -0
- package/dist/commands/app/remote.js +44 -0
- package/dist/commands/app/remote.js.map +1 -0
- package/dist/commands/app/setup.d.ts +3 -0
- package/dist/commands/app/setup.d.ts.map +1 -0
- package/dist/commands/app/setup.js +299 -0
- package/dist/commands/app/setup.js.map +1 -0
- package/dist/commands/app/shared.d.ts +9 -0
- package/dist/commands/app/shared.d.ts.map +1 -0
- package/dist/commands/app/shared.js +122 -0
- package/dist/commands/app/shared.js.map +1 -0
- package/dist/commands/app/sync.d.ts +7 -0
- package/dist/commands/app/sync.d.ts.map +1 -0
- package/dist/commands/app/sync.js +107 -0
- package/dist/commands/app/sync.js.map +1 -0
- package/dist/commands/booking/check.d.ts +3 -0
- package/dist/commands/booking/check.d.ts.map +1 -0
- package/dist/commands/booking/check.js +68 -0
- package/dist/commands/booking/check.js.map +1 -0
- package/dist/commands/booking/setup.d.ts +3 -0
- package/dist/commands/booking/setup.d.ts.map +1 -0
- package/dist/commands/booking/setup.js +95 -0
- package/dist/commands/booking/setup.js.map +1 -0
- package/dist/commands/booking/shared.d.ts +31 -0
- package/dist/commands/booking/shared.d.ts.map +1 -0
- package/dist/commands/booking/shared.js +112 -0
- package/dist/commands/booking/shared.js.map +1 -0
- package/dist/commands/booking/smoke.d.ts +3 -0
- package/dist/commands/booking/smoke.d.ts.map +1 -0
- package/dist/commands/booking/smoke.js +101 -0
- package/dist/commands/booking/smoke.js.map +1 -0
- package/dist/commands/cms/bind.d.ts +3 -0
- package/dist/commands/cms/bind.d.ts.map +1 -0
- package/dist/commands/cms/bind.js +212 -0
- package/dist/commands/cms/bind.js.map +1 -0
- package/dist/commands/cms/content.d.ts +40 -0
- package/dist/commands/cms/content.d.ts.map +1 -0
- package/dist/commands/cms/content.js +169 -0
- package/dist/commands/cms/content.js.map +1 -0
- package/dist/commands/cms/doctor.d.ts +3 -0
- package/dist/commands/cms/doctor.d.ts.map +1 -0
- package/dist/commands/cms/doctor.js +69 -0
- package/dist/commands/cms/doctor.js.map +1 -0
- package/dist/commands/cms/migrate.d.ts +3 -0
- package/dist/commands/cms/migrate.d.ts.map +1 -0
- package/dist/commands/cms/migrate.js +78 -0
- package/dist/commands/cms/migrate.js.map +1 -0
- package/dist/commands/cms/registry.d.ts +3 -0
- package/dist/commands/cms/registry.d.ts.map +1 -0
- package/dist/commands/cms/registry.js +161 -0
- package/dist/commands/cms/registry.js.map +1 -0
- package/dist/commands/cms/seed.d.ts +3 -0
- package/dist/commands/cms/seed.d.ts.map +1 -0
- package/dist/commands/cms/seed.js +102 -0
- package/dist/commands/cms/seed.js.map +1 -0
- package/dist/commands/cms/shared.d.ts +22 -0
- package/dist/commands/cms/shared.d.ts.map +1 -0
- package/dist/commands/cms/shared.js +82 -0
- package/dist/commands/cms/shared.js.map +1 -0
- package/dist/commands/doctor/target.d.ts +3 -0
- package/dist/commands/doctor/target.d.ts.map +1 -0
- package/dist/commands/doctor/target.js +46 -0
- package/dist/commands/doctor/target.js.map +1 -0
- package/dist/commands/env/list.d.ts +3 -0
- package/dist/commands/env/list.d.ts.map +1 -0
- package/dist/commands/env/list.js +28 -0
- package/dist/commands/env/list.js.map +1 -0
- package/dist/commands/env/set.d.ts +3 -0
- package/dist/commands/env/set.d.ts.map +1 -0
- package/dist/commands/env/set.js +36 -0
- package/dist/commands/env/set.js.map +1 -0
- package/dist/commands/env/use.d.ts +3 -0
- package/dist/commands/env/use.d.ts.map +1 -0
- package/dist/commands/env/use.js +15 -0
- package/dist/commands/env/use.js.map +1 -0
- package/dist/commands/legacy/connect.d.ts +3 -0
- package/dist/commands/legacy/connect.d.ts.map +1 -0
- package/dist/commands/legacy/connect.js +8 -0
- package/dist/commands/legacy/connect.js.map +1 -0
- package/dist/commands/legacy/pages.d.ts +3 -0
- package/dist/commands/legacy/pages.d.ts.map +1 -0
- package/dist/commands/legacy/pages.js +16 -0
- package/dist/commands/legacy/pages.js.map +1 -0
- package/dist/commands/legacy/spread.d.ts +3 -0
- package/dist/commands/legacy/spread.d.ts.map +1 -0
- package/dist/commands/legacy/spread.js +8 -0
- package/dist/commands/legacy/spread.js.map +1 -0
- package/dist/commands/legacy/sync.d.ts +3 -0
- package/dist/commands/legacy/sync.d.ts.map +1 -0
- package/dist/commands/legacy/sync.js +8 -0
- package/dist/commands/legacy/sync.js.map +1 -0
- package/dist/config/env-diff.d.ts +10 -0
- package/dist/config/env-diff.d.ts.map +1 -0
- package/dist/config/env-diff.js +24 -0
- package/dist/config/env-diff.js.map +1 -0
- package/dist/config/env-parser.d.ts +20 -0
- package/dist/config/env-parser.d.ts.map +1 -0
- package/dist/config/env-parser.js +70 -0
- package/dist/config/env-parser.js.map +1 -0
- package/dist/config/env-writer.d.ts +22 -0
- package/dist/config/env-writer.d.ts.map +1 -0
- package/dist/config/env-writer.js +172 -0
- package/dist/config/env-writer.js.map +1 -0
- package/dist/config/profile-store.d.ts +29 -0
- package/dist/config/profile-store.d.ts.map +1 -0
- package/dist/config/profile-store.js +257 -0
- package/dist/config/profile-store.js.map +1 -0
- package/dist/core/args.d.ts +11 -0
- package/dist/core/args.d.ts.map +1 -0
- package/dist/core/args.js +106 -0
- package/dist/core/args.js.map +1 -0
- package/dist/core/colors.d.ts +6 -0
- package/dist/core/colors.d.ts.map +1 -0
- package/dist/core/colors.js +29 -0
- package/dist/core/colors.js.map +1 -0
- package/dist/safety/target-guard.d.ts +16 -0
- package/dist/safety/target-guard.d.ts.map +1 -0
- package/dist/safety/target-guard.js +55 -0
- package/dist/safety/target-guard.js.map +1 -0
- package/dist/testing/booking-smoke.d.ts +17 -0
- package/dist/testing/booking-smoke.d.ts.map +1 -0
- package/dist/testing/booking-smoke.js +43 -0
- package/dist/testing/booking-smoke.js.map +1 -0
- package/dist/tests/agent-commands.test.d.ts +2 -0
- package/dist/tests/agent-commands.test.d.ts.map +1 -0
- package/dist/tests/agent-commands.test.js +180 -0
- package/dist/tests/agent-commands.test.js.map +1 -0
- package/dist/tests/agent-governance.test.d.ts +2 -0
- package/dist/tests/agent-governance.test.d.ts.map +1 -0
- package/dist/tests/agent-governance.test.js +233 -0
- package/dist/tests/agent-governance.test.js.map +1 -0
- package/dist/tests/app-commands.test.d.ts +2 -0
- package/dist/tests/app-commands.test.d.ts.map +1 -0
- package/dist/tests/app-commands.test.js +462 -0
- package/dist/tests/app-commands.test.js.map +1 -0
- package/dist/tests/booking-commands.test.d.ts +2 -0
- package/dist/tests/booking-commands.test.d.ts.map +1 -0
- package/dist/tests/booking-commands.test.js +204 -0
- package/dist/tests/booking-commands.test.js.map +1 -0
- package/dist/tests/booking-smoke.test.d.ts +2 -0
- package/dist/tests/booking-smoke.test.d.ts.map +1 -0
- package/dist/tests/booking-smoke.test.js +183 -0
- package/dist/tests/booking-smoke.test.js.map +1 -0
- package/dist/tests/cms-commands.test.d.ts +2 -0
- package/dist/tests/cms-commands.test.d.ts.map +1 -0
- package/dist/tests/cms-commands.test.js +254 -0
- package/dist/tests/cms-commands.test.js.map +1 -0
- package/dist/tests/cms-ops.test.d.ts +2 -0
- package/dist/tests/cms-ops.test.d.ts.map +1 -0
- package/dist/tests/cms-ops.test.js +125 -0
- package/dist/tests/cms-ops.test.js.map +1 -0
- package/dist/tests/env-writer.test.d.ts +2 -0
- package/dist/tests/env-writer.test.d.ts.map +1 -0
- package/dist/tests/env-writer.test.js +90 -0
- package/dist/tests/env-writer.test.js.map +1 -0
- package/dist/tests/profile-store.test.d.ts +2 -0
- package/dist/tests/profile-store.test.d.ts.map +1 -0
- package/dist/tests/profile-store.test.js +88 -0
- package/dist/tests/profile-store.test.js.map +1 -0
- package/dist/tests/target-guard.test.d.ts +2 -0
- package/dist/tests/target-guard.test.d.ts.map +1 -0
- package/dist/tests/target-guard.test.js +132 -0
- package/dist/tests/target-guard.test.js.map +1 -0
- package/dist/ui/logo.d.ts +2 -0
- package/dist/ui/logo.d.ts.map +1 -0
- package/dist/ui/logo.js +22 -0
- package/dist/ui/logo.js.map +1 -0
- package/package.json +17 -53
- package/.claude/settings.local.json +0 -36
- package/.cursor/rules.md +0 -203
- package/.eslintrc.js +0 -31
- package/CLAUDE.md +0 -100
- package/bin/cli.js +0 -116
- package/docs/ADDING_FRAMEWORK_DETECTORS.md +0 -391
- package/docs/ADDING_NEW_PROJECT_TYPE.md +0 -156
- package/docs/ARCHITECTURE_RELATIONSHIPS.md +0 -411
- package/docs/CLI_AUTHENTICATION.md +0 -214
- package/docs/CLI_PAGE_DETECTION_REQUIREMENTS.md +0 -519
- package/docs/CRM-PIPELINES-SEQUENCES-SPEC.md +0 -429
- package/docs/DETECTOR_ARCHITECTURE.md +0 -326
- package/docs/DEVELOPMENT.md +0 -194
- package/docs/IMPLEMENTATION_PHASES.md +0 -468
- package/docs/INTEGRATION_PATHS_ARCHITECTURE.md +0 -1543
- package/docs/OAUTH_CLARIFICATION.md +0 -258
- package/docs/OAUTH_SETUP_GUIDE_TEMPLATE.md +0 -211
- package/docs/PHASE_0_PROGRESS.md +0 -120
- package/docs/PHASE_1_COMPLETE.md +0 -366
- package/docs/PHASE_SUMMARY.md +0 -149
- package/docs/PLAN.md +0 -511
- package/docs/README.md +0 -56
- package/docs/STRIPE_INTEGRATION.md +0 -447
- package/docs/SUMMARY.md +0 -230
- package/docs/UPDATED_PLAN.md +0 -447
- package/docs/mcp_server/MCP_EXTENSION_GUIDE.md +0 -1313
- package/docs/mcp_server/MCP_SERVER_ARCHITECTURE.md +0 -1481
- package/docs/mcp_server/applicationOntology.ts +0 -817
- package/docs/mcp_server/cliApplications.ts +0 -639
- package/docs/mcp_server/crmOntology.ts +0 -1063
- package/docs/mcp_server/eventOntology.ts +0 -1183
- package/docs/mcp_server/formsOntology.ts +0 -1401
- package/docs/mcp_server/ontologySchemas.ts +0 -185
- package/docs/mcp_server/schema.ts +0 -250
- package/docs/microsass_production_machine/CLI_API_REFERENCE.md +0 -1197
- package/docs/microsass_production_machine/CLI_PRODUCT_VISION.md +0 -676
- package/docs/microsass_production_machine/CLI_REQUIREMENTS.md +0 -606
- package/docs/microsass_production_machine/CONNECTED_APPLICATIONS_SPEC.md +0 -390
- package/docs/microsass_production_machine/IMPLEMENTATION_ROADMAP.md +0 -725
- package/docs/microsass_production_machine/OBJECT_MAPPINGS.md +0 -808
- package/docs/microsass_production_machine/REFERENCE_IMPLEMENTATION.md +0 -532
- package/src/api/backend-client.js +0 -449
- package/src/commands/api-keys.js +0 -119
- package/src/commands/connect.js +0 -253
- package/src/commands/login.js +0 -332
- package/src/commands/logout.js +0 -30
- package/src/commands/mcp-server.js +0 -85
- package/src/commands/mcp-setup.js +0 -686
- package/src/commands/pages.js +0 -317
- package/src/commands/scaffold.js +0 -409
- package/src/commands/spread.js +0 -861
- package/src/commands/status.js +0 -62
- package/src/commands/sync.js +0 -169
- package/src/commands/upgrade.js +0 -48
- package/src/config/config-manager.js +0 -206
- package/src/detectors/api-client-detector.js +0 -85
- package/src/detectors/base-detector.js +0 -77
- package/src/detectors/database-detector.js +0 -245
- package/src/detectors/expo-detector.js +0 -166
- package/src/detectors/github-detector.js +0 -74
- package/src/detectors/index.js +0 -106
- package/src/detectors/mapping-suggestor.js +0 -119
- package/src/detectors/model-detector.js +0 -318
- package/src/detectors/nextjs-detector.js +0 -139
- package/src/detectors/oauth-detector.js +0 -122
- package/src/detectors/page-detector.js +0 -480
- package/src/detectors/registry.js +0 -121
- package/src/generators/api-client-generator.js +0 -223
- package/src/generators/api-only/client.js +0 -683
- package/src/generators/api-only/index.js +0 -96
- package/src/generators/api-only/types.js +0 -618
- package/src/generators/api-only/webhooks.js +0 -377
- package/src/generators/env-generator.js +0 -191
- package/src/generators/expo-auth-generator.js +0 -1009
- package/src/generators/gitignore-generator.js +0 -92
- package/src/generators/index.js +0 -166
- package/src/generators/manifest-generator.js +0 -154
- package/src/generators/mcp-guide-generator.js +0 -256
- package/src/generators/nextauth-generator.js +0 -247
- package/src/generators/oauth-guide-generator.js +0 -277
- package/src/generators/quickstart/components/index.js +0 -1699
- package/src/generators/quickstart/components-mobile/index.js +0 -1440
- package/src/generators/quickstart/database/convex.js +0 -1257
- package/src/generators/quickstart/database/index.js +0 -34
- package/src/generators/quickstart/database/supabase.js +0 -1132
- package/src/generators/quickstart/hooks/index.js +0 -1065
- package/src/generators/quickstart/index.js +0 -191
- package/src/generators/quickstart/pages/index.js +0 -1466
- package/src/generators/quickstart/screens/index.js +0 -1498
- package/src/logo.js +0 -116
- package/src/mcp/auth.js +0 -127
- package/src/mcp/registry/domains/applications.js +0 -516
- package/src/mcp/registry/domains/benefits.js +0 -798
- package/src/mcp/registry/domains/codegen.js +0 -894
- package/src/mcp/registry/domains/core.js +0 -324
- package/src/mcp/registry/domains/crm.js +0 -591
- package/src/mcp/registry/domains/events.js +0 -649
- package/src/mcp/registry/domains/forms.js +0 -696
- package/src/mcp/registry/index.js +0 -164
- package/src/mcp/server.js +0 -116
- package/src/utils/file-utils.js +0 -117
- package/src/utils/init-helpers.js +0 -243
- package/src/utils/prompt-utils.js +0 -195
- package/templates/CLAUDE.md +0 -86
- package/tests/api-client-detector.test.js +0 -214
- package/tests/api-client-generator.test.js +0 -176
- package/tests/backend-client.test.js +0 -640
- package/tests/base-detector.test.js +0 -101
- package/tests/commands/login.test.js +0 -143
- package/tests/commands/logout.test.js +0 -84
- package/tests/commands/status.test.js +0 -167
- package/tests/config-manager.test.js +0 -321
- package/tests/database-detector.test.js +0 -221
- package/tests/detector-index.test.js +0 -209
- package/tests/detector-registry.test.js +0 -93
- package/tests/env-generator.test.js +0 -278
- package/tests/expo-detector.test.js +0 -263
- package/tests/file-utils.test.js +0 -194
- package/tests/generators-index.test.js +0 -454
- package/tests/github-detector.test.js +0 -145
- package/tests/gitignore-generator.test.js +0 -109
- package/tests/logo.test.js +0 -96
- package/tests/nextauth-generator.test.js +0 -255
- package/tests/nextjs-detector.test.js +0 -235
- package/tests/oauth-detector.test.js +0 -264
- package/tests/oauth-guide-generator.test.js +0 -273
- package/tests/page-detector.test.js +0 -371
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model/Type Scanner
|
|
3
|
-
* Detects data models and types across multiple sources:
|
|
4
|
-
* - Prisma schemas
|
|
5
|
-
* - TypeScript interfaces/types
|
|
6
|
-
* - Drizzle table definitions
|
|
7
|
-
* - Convex schemas
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @typedef {Object} DetectedModel
|
|
15
|
-
* @property {string} name - Model name
|
|
16
|
-
* @property {string} source - Source identifier (e.g., 'prisma/schema.prisma')
|
|
17
|
-
* @property {string[]} fields - Field names
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Check if a path exists
|
|
22
|
-
* @param {string} filePath
|
|
23
|
-
* @returns {boolean}
|
|
24
|
-
*/
|
|
25
|
-
function exists(filePath) {
|
|
26
|
-
try {
|
|
27
|
-
return fs.existsSync(filePath);
|
|
28
|
-
} catch {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Safely read a file
|
|
35
|
-
* @param {string} filePath
|
|
36
|
-
* @returns {string|null}
|
|
37
|
-
*/
|
|
38
|
-
function readFile(filePath) {
|
|
39
|
-
try {
|
|
40
|
-
return fs.readFileSync(filePath, 'utf8');
|
|
41
|
-
} catch {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Find files matching a pattern in a directory (non-recursive)
|
|
48
|
-
* @param {string} dir
|
|
49
|
-
* @param {RegExp} pattern
|
|
50
|
-
* @returns {string[]}
|
|
51
|
-
*/
|
|
52
|
-
function findFiles(dir, pattern) {
|
|
53
|
-
if (!exists(dir)) return [];
|
|
54
|
-
try {
|
|
55
|
-
return fs.readdirSync(dir)
|
|
56
|
-
.filter(f => pattern.test(f))
|
|
57
|
-
.map(f => path.join(dir, f));
|
|
58
|
-
} catch {
|
|
59
|
-
return [];
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Parse Prisma schema file for model definitions
|
|
65
|
-
* @param {string} filePath - Path to schema.prisma
|
|
66
|
-
* @returns {DetectedModel[]}
|
|
67
|
-
*/
|
|
68
|
-
function parsePrismaSchema(filePath) {
|
|
69
|
-
const content = readFile(filePath);
|
|
70
|
-
if (!content) return [];
|
|
71
|
-
|
|
72
|
-
const models = [];
|
|
73
|
-
const modelRegex = /^model\s+(\w+)\s*\{([^}]+)\}/gm;
|
|
74
|
-
let match;
|
|
75
|
-
|
|
76
|
-
while ((match = modelRegex.exec(content)) !== null) {
|
|
77
|
-
const name = match[1];
|
|
78
|
-
const body = match[2];
|
|
79
|
-
const fields = [];
|
|
80
|
-
|
|
81
|
-
for (const line of body.split('\n')) {
|
|
82
|
-
const trimmed = line.trim();
|
|
83
|
-
// Skip empty lines, comments, and @@ annotations
|
|
84
|
-
if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('@@')) continue;
|
|
85
|
-
// Extract field name (first word on the line)
|
|
86
|
-
const fieldMatch = trimmed.match(/^(\w+)\s+/);
|
|
87
|
-
if (fieldMatch) {
|
|
88
|
-
fields.push(fieldMatch[1]);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
models.push({
|
|
93
|
-
name,
|
|
94
|
-
source: 'prisma/schema.prisma',
|
|
95
|
-
fields,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return models;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Parse TypeScript files for interface and type definitions
|
|
104
|
-
* @param {string[]} dirs - Directories to scan
|
|
105
|
-
* @param {string} projectPath - Project root for relative paths
|
|
106
|
-
* @returns {DetectedModel[]}
|
|
107
|
-
*/
|
|
108
|
-
function parseTypeScriptTypes(dirs, projectPath) {
|
|
109
|
-
const models = [];
|
|
110
|
-
const filePattern = /\.(ts|tsx)$/;
|
|
111
|
-
|
|
112
|
-
for (const dir of dirs) {
|
|
113
|
-
const files = findFiles(dir, filePattern);
|
|
114
|
-
|
|
115
|
-
for (const filePath of files) {
|
|
116
|
-
const content = readFile(filePath);
|
|
117
|
-
if (!content) continue;
|
|
118
|
-
|
|
119
|
-
const relativePath = path.relative(projectPath, filePath);
|
|
120
|
-
|
|
121
|
-
// Match interface declarations
|
|
122
|
-
const interfaceRegex = /^(?:export\s+)?interface\s+(\w+)\s*(?:extends\s+[\w,\s<>]+)?\s*\{([^}]+)\}/gm;
|
|
123
|
-
let match;
|
|
124
|
-
|
|
125
|
-
while ((match = interfaceRegex.exec(content)) !== null) {
|
|
126
|
-
const name = match[1];
|
|
127
|
-
const body = match[2];
|
|
128
|
-
const fields = extractTsFields(body);
|
|
129
|
-
if (fields.length > 0) {
|
|
130
|
-
models.push({ name, source: relativePath, fields });
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Match type aliases with object shapes
|
|
135
|
-
const typeRegex = /^(?:export\s+)?type\s+(\w+)\s*=\s*\{([^}]+)\}/gm;
|
|
136
|
-
while ((match = typeRegex.exec(content)) !== null) {
|
|
137
|
-
const name = match[1];
|
|
138
|
-
const body = match[2];
|
|
139
|
-
const fields = extractTsFields(body);
|
|
140
|
-
if (fields.length > 0) {
|
|
141
|
-
models.push({ name, source: relativePath, fields });
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return models;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Extract field names from a TypeScript object body
|
|
152
|
-
* @param {string} body
|
|
153
|
-
* @returns {string[]}
|
|
154
|
-
*/
|
|
155
|
-
function extractTsFields(body) {
|
|
156
|
-
const fields = [];
|
|
157
|
-
for (const line of body.split('\n')) {
|
|
158
|
-
const trimmed = line.trim();
|
|
159
|
-
if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('/*')) continue;
|
|
160
|
-
// Match: fieldName: type or fieldName?: type
|
|
161
|
-
const fieldMatch = trimmed.match(/^(\w+)\s*\??:/);
|
|
162
|
-
if (fieldMatch) {
|
|
163
|
-
fields.push(fieldMatch[1]);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return fields;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Parse Drizzle schema files for table definitions
|
|
171
|
-
* @param {string[]} dirs - Directories to scan
|
|
172
|
-
* @param {string} projectPath - Project root for relative paths
|
|
173
|
-
* @returns {DetectedModel[]}
|
|
174
|
-
*/
|
|
175
|
-
function parseDrizzleSchemas(dirs, projectPath) {
|
|
176
|
-
const models = [];
|
|
177
|
-
const filePattern = /schema.*\.(ts|js)$/;
|
|
178
|
-
|
|
179
|
-
for (const dir of dirs) {
|
|
180
|
-
const files = findFiles(dir, filePattern);
|
|
181
|
-
|
|
182
|
-
for (const filePath of files) {
|
|
183
|
-
const content = readFile(filePath);
|
|
184
|
-
if (!content) continue;
|
|
185
|
-
|
|
186
|
-
const relativePath = path.relative(projectPath, filePath);
|
|
187
|
-
|
|
188
|
-
// Match: export const tableName = pgTable('table_name', { ... })
|
|
189
|
-
const tableRegex = /export\s+const\s+(\w+)\s*=\s*(?:pgTable|mysqlTable|sqliteTable)\s*\(\s*['"](\w+)['"]\s*,\s*\{([^}]+)\}/g;
|
|
190
|
-
let match;
|
|
191
|
-
|
|
192
|
-
while ((match = tableRegex.exec(content)) !== null) {
|
|
193
|
-
// match[1] is the variable name (e.g., 'users'), match[2] is the SQL table name
|
|
194
|
-
const tableName = match[2];
|
|
195
|
-
const body = match[3];
|
|
196
|
-
const fields = [];
|
|
197
|
-
|
|
198
|
-
for (const line of body.split('\n')) {
|
|
199
|
-
const trimmed = line.trim();
|
|
200
|
-
if (!trimmed || trimmed.startsWith('//')) continue;
|
|
201
|
-
// Match: columnName: type(...)
|
|
202
|
-
const colMatch = trimmed.match(/^(\w+)\s*:/);
|
|
203
|
-
if (colMatch) {
|
|
204
|
-
fields.push(colMatch[1]);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Use PascalCase version of table name as model name
|
|
209
|
-
const name = tableName
|
|
210
|
-
.split('_')
|
|
211
|
-
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
|
|
212
|
-
.join('');
|
|
213
|
-
|
|
214
|
-
models.push({ name, source: relativePath, fields });
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return models;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Parse Convex schema file
|
|
224
|
-
* @param {string} filePath - Path to convex/schema.ts
|
|
225
|
-
* @param {string} projectPath - Project root
|
|
226
|
-
* @returns {DetectedModel[]}
|
|
227
|
-
*/
|
|
228
|
-
function parseConvexSchema(filePath, projectPath) {
|
|
229
|
-
const content = readFile(filePath);
|
|
230
|
-
if (!content) return [];
|
|
231
|
-
|
|
232
|
-
const models = [];
|
|
233
|
-
const relativePath = path.relative(projectPath, filePath);
|
|
234
|
-
|
|
235
|
-
// Match: tableName: defineTable({ ... })
|
|
236
|
-
const tableRegex = /(\w+)\s*:\s*defineTable\s*\(\s*\{([^}]+)\}/g;
|
|
237
|
-
let match;
|
|
238
|
-
|
|
239
|
-
while ((match = tableRegex.exec(content)) !== null) {
|
|
240
|
-
const tableName = match[1];
|
|
241
|
-
const body = match[2];
|
|
242
|
-
const fields = [];
|
|
243
|
-
|
|
244
|
-
for (const line of body.split('\n')) {
|
|
245
|
-
const trimmed = line.trim();
|
|
246
|
-
if (!trimmed || trimmed.startsWith('//')) continue;
|
|
247
|
-
const fieldMatch = trimmed.match(/^(\w+)\s*:/);
|
|
248
|
-
if (fieldMatch) {
|
|
249
|
-
fields.push(fieldMatch[1]);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const name = tableName.charAt(0).toUpperCase() + tableName.slice(1);
|
|
254
|
-
models.push({ name, source: relativePath, fields });
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return models;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Detect all models/types in a project
|
|
262
|
-
* @param {string} projectPath - Project root path
|
|
263
|
-
* @returns {{ hasModels: boolean, models: DetectedModel[] }}
|
|
264
|
-
*/
|
|
265
|
-
function detect(projectPath = process.cwd()) {
|
|
266
|
-
const allModels = [];
|
|
267
|
-
|
|
268
|
-
// 1. Prisma
|
|
269
|
-
const prismaPath = path.join(projectPath, 'prisma', 'schema.prisma');
|
|
270
|
-
if (exists(prismaPath)) {
|
|
271
|
-
allModels.push(...parsePrismaSchema(prismaPath));
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// 2. TypeScript types/interfaces
|
|
275
|
-
const tsDirs = [
|
|
276
|
-
path.join(projectPath, 'types'),
|
|
277
|
-
path.join(projectPath, 'src', 'types'),
|
|
278
|
-
path.join(projectPath, 'models'),
|
|
279
|
-
path.join(projectPath, 'src', 'models'),
|
|
280
|
-
].filter(d => exists(d));
|
|
281
|
-
|
|
282
|
-
if (tsDirs.length > 0) {
|
|
283
|
-
allModels.push(...parseTypeScriptTypes(tsDirs, projectPath));
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// 3. Drizzle
|
|
287
|
-
const drizzleDirs = [
|
|
288
|
-
path.join(projectPath, 'drizzle'),
|
|
289
|
-
path.join(projectPath, 'src', 'db'),
|
|
290
|
-
path.join(projectPath, 'db'),
|
|
291
|
-
].filter(d => exists(d));
|
|
292
|
-
|
|
293
|
-
if (drizzleDirs.length > 0) {
|
|
294
|
-
allModels.push(...parseDrizzleSchemas(drizzleDirs, projectPath));
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// 4. Convex
|
|
298
|
-
const convexSchemaTs = path.join(projectPath, 'convex', 'schema.ts');
|
|
299
|
-
const convexSchemaJs = path.join(projectPath, 'convex', 'schema.js');
|
|
300
|
-
if (exists(convexSchemaTs)) {
|
|
301
|
-
allModels.push(...parseConvexSchema(convexSchemaTs, projectPath));
|
|
302
|
-
} else if (exists(convexSchemaJs)) {
|
|
303
|
-
allModels.push(...parseConvexSchema(convexSchemaJs, projectPath));
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return {
|
|
307
|
-
hasModels: allModels.length > 0,
|
|
308
|
-
models: allModels,
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
module.exports = {
|
|
313
|
-
detect,
|
|
314
|
-
parsePrismaSchema,
|
|
315
|
-
parseTypeScriptTypes,
|
|
316
|
-
parseDrizzleSchemas,
|
|
317
|
-
parseConvexSchema,
|
|
318
|
-
};
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Next.js Project Detector
|
|
3
|
-
* Detects Next.js projects and their configuration
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const BaseDetector = require('./base-detector');
|
|
9
|
-
|
|
10
|
-
class NextJsDetector extends BaseDetector {
|
|
11
|
-
get name() {
|
|
12
|
-
return 'nextjs';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
get priority() {
|
|
16
|
-
return 100; // High priority - very specific framework
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Detect if current directory is a Next.js project
|
|
21
|
-
*/
|
|
22
|
-
detect(projectPath = process.cwd()) {
|
|
23
|
-
const results = {
|
|
24
|
-
isNextJs: false,
|
|
25
|
-
version: null,
|
|
26
|
-
routerType: null, // 'app' or 'pages'
|
|
27
|
-
hasTypeScript: false,
|
|
28
|
-
config: null,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// Check for package.json
|
|
32
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
33
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
34
|
-
return results;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
39
|
-
const dependencies = {
|
|
40
|
-
...packageJson.dependencies,
|
|
41
|
-
...packageJson.devDependencies,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// Check if Next.js is installed
|
|
45
|
-
if (dependencies.next) {
|
|
46
|
-
results.isNextJs = true;
|
|
47
|
-
results.version = dependencies.next;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Check for TypeScript
|
|
51
|
-
if (dependencies.typescript || fs.existsSync(path.join(projectPath, 'tsconfig.json'))) {
|
|
52
|
-
results.hasTypeScript = true;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Detect router type (App Router vs Pages Router)
|
|
56
|
-
const appDir = path.join(projectPath, 'app');
|
|
57
|
-
const pagesDir = path.join(projectPath, 'pages');
|
|
58
|
-
const srcAppDir = path.join(projectPath, 'src', 'app');
|
|
59
|
-
const srcPagesDir = path.join(projectPath, 'src', 'pages');
|
|
60
|
-
|
|
61
|
-
if (fs.existsSync(appDir) || fs.existsSync(srcAppDir)) {
|
|
62
|
-
results.routerType = 'app';
|
|
63
|
-
} else if (fs.existsSync(pagesDir) || fs.existsSync(srcPagesDir)) {
|
|
64
|
-
results.routerType = 'pages';
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Read Next.js config if exists
|
|
68
|
-
const configFiles = [
|
|
69
|
-
'next.config.js',
|
|
70
|
-
'next.config.mjs',
|
|
71
|
-
'next.config.ts',
|
|
72
|
-
'next.config.cjs',
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
for (const configFile of configFiles) {
|
|
76
|
-
const configPath = path.join(projectPath, configFile);
|
|
77
|
-
if (fs.existsSync(configPath)) {
|
|
78
|
-
try {
|
|
79
|
-
// For .js/.mjs/.cjs files, we'd need to require them
|
|
80
|
-
// For now, just note that config exists
|
|
81
|
-
results.config = configFile;
|
|
82
|
-
break;
|
|
83
|
-
} catch (error) {
|
|
84
|
-
// Config file exists but couldn't be read
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
} catch (error) {
|
|
89
|
-
// Error reading package.json
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Return in BaseDetector format
|
|
93
|
-
if (!results.isNextJs) {
|
|
94
|
-
return {
|
|
95
|
-
detected: false,
|
|
96
|
-
confidence: 0,
|
|
97
|
-
metadata: {},
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
detected: true,
|
|
103
|
-
confidence: 0.95, // High confidence for Next.js detection
|
|
104
|
-
metadata: {
|
|
105
|
-
version: results.version,
|
|
106
|
-
routerType: results.routerType,
|
|
107
|
-
hasTypeScript: results.hasTypeScript,
|
|
108
|
-
config: results.config,
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Get supported features for Next.js
|
|
115
|
-
*/
|
|
116
|
-
getSupportedFeatures() {
|
|
117
|
-
return {
|
|
118
|
-
oauth: true, // Full NextAuth.js support
|
|
119
|
-
stripe: true, // Full Stripe support
|
|
120
|
-
crm: true, // Full CRM support
|
|
121
|
-
projects: true, // Full Projects support
|
|
122
|
-
invoices: true, // Full Invoices support
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Get available generators for Next.js
|
|
128
|
-
*/
|
|
129
|
-
getAvailableGenerators() {
|
|
130
|
-
return [
|
|
131
|
-
'api-client',
|
|
132
|
-
'env',
|
|
133
|
-
'nextauth', // Next.js-specific
|
|
134
|
-
'oauth-guide',
|
|
135
|
-
];
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = new NextJsDetector();
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OAuth Setup Detector
|
|
3
|
-
* Detects existing OAuth/NextAuth.js configuration
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
class OAuthDetector {
|
|
10
|
-
/**
|
|
11
|
-
* Detect existing OAuth setup
|
|
12
|
-
*/
|
|
13
|
-
detect(projectPath = process.cwd()) {
|
|
14
|
-
const results = {
|
|
15
|
-
hasOAuth: false,
|
|
16
|
-
oauthType: null, // 'nextauth', 'custom', 'unknown'
|
|
17
|
-
configPath: null,
|
|
18
|
-
providers: [], // ['google', 'microsoft', 'github']
|
|
19
|
-
hasEnvVars: false,
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// Check for NextAuth.js configuration
|
|
23
|
-
const nextAuthPaths = [
|
|
24
|
-
// App Router
|
|
25
|
-
'app/api/auth/[...nextauth]/route.ts',
|
|
26
|
-
'app/api/auth/[...nextauth]/route.js',
|
|
27
|
-
'src/app/api/auth/[...nextauth]/route.ts',
|
|
28
|
-
'src/app/api/auth/[...nextauth]/route.js',
|
|
29
|
-
// Pages Router
|
|
30
|
-
'pages/api/auth/[...nextauth].ts',
|
|
31
|
-
'pages/api/auth/[...nextauth].js',
|
|
32
|
-
'src/pages/api/auth/[...nextauth].ts',
|
|
33
|
-
'src/pages/api/auth/[...nextauth].js',
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
for (const configPath of nextAuthPaths) {
|
|
37
|
-
const fullPath = path.join(projectPath, configPath);
|
|
38
|
-
if (fs.existsSync(fullPath)) {
|
|
39
|
-
results.hasOAuth = true;
|
|
40
|
-
results.oauthType = 'nextauth';
|
|
41
|
-
results.configPath = configPath;
|
|
42
|
-
|
|
43
|
-
// Try to detect providers from config file
|
|
44
|
-
try {
|
|
45
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
46
|
-
const detectedProviders = [];
|
|
47
|
-
|
|
48
|
-
if (content.includes('GoogleProvider') || content.includes('google')) {
|
|
49
|
-
detectedProviders.push('google');
|
|
50
|
-
}
|
|
51
|
-
if (content.includes('AzureADProvider') || content.includes('microsoft') || content.includes('azure')) {
|
|
52
|
-
detectedProviders.push('microsoft');
|
|
53
|
-
}
|
|
54
|
-
if (content.includes('GitHubProvider') || content.includes('github')) {
|
|
55
|
-
detectedProviders.push('github');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
results.providers = detectedProviders;
|
|
59
|
-
} catch (error) {
|
|
60
|
-
// Couldn't read config file
|
|
61
|
-
}
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Check for OAuth-related environment variables
|
|
67
|
-
const envFiles = ['.env.local', '.env', '.env.development'];
|
|
68
|
-
for (const envFile of envFiles) {
|
|
69
|
-
const envPath = path.join(projectPath, envFile);
|
|
70
|
-
if (fs.existsSync(envPath)) {
|
|
71
|
-
try {
|
|
72
|
-
const content = fs.readFileSync(envPath, 'utf8');
|
|
73
|
-
const oauthVars = [
|
|
74
|
-
'NEXTAUTH_URL',
|
|
75
|
-
'NEXTAUTH_SECRET',
|
|
76
|
-
'GOOGLE_CLIENT_ID',
|
|
77
|
-
'GOOGLE_CLIENT_SECRET',
|
|
78
|
-
'MICROSOFT_CLIENT_ID',
|
|
79
|
-
'MICROSOFT_CLIENT_SECRET',
|
|
80
|
-
'GITHUB_CLIENT_ID',
|
|
81
|
-
'GITHUB_CLIENT_SECRET',
|
|
82
|
-
'GOOGLE_OAUTH_CLIENT_ID',
|
|
83
|
-
'GOOGLE_OAUTH_CLIENT_SECRET',
|
|
84
|
-
];
|
|
85
|
-
|
|
86
|
-
const hasOAuthVars = oauthVars.some(varName => content.includes(varName));
|
|
87
|
-
if (hasOAuthVars) {
|
|
88
|
-
results.hasEnvVars = true;
|
|
89
|
-
}
|
|
90
|
-
} catch (error) {
|
|
91
|
-
// Couldn't read env file
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Check package.json for NextAuth.js dependency
|
|
97
|
-
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
98
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
99
|
-
try {
|
|
100
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
101
|
-
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
102
|
-
|
|
103
|
-
if (deps['next-auth'] || deps.nextauth) {
|
|
104
|
-
results.hasOAuth = true;
|
|
105
|
-
if (!results.oauthType) {
|
|
106
|
-
results.oauthType = 'nextauth';
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
} catch (error) {
|
|
110
|
-
// Couldn't read package.json
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return results;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
module.exports = new OAuthDetector();
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|