@apso/cli 0.8.6 → 0.10.2
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 +221 -1653
- package/dist/commands/config.d.ts +13 -0
- package/dist/commands/config.js +114 -0
- package/dist/commands/deploy.d.ts +11 -0
- package/dist/commands/deploy.js +141 -0
- package/dist/commands/dev.d.ts +15 -0
- package/dist/commands/dev.js +95 -0
- package/dist/commands/generate.d.ts +12 -0
- package/dist/commands/generate.js +179 -0
- package/dist/commands/init.d.ts +16 -0
- package/dist/commands/init.js +313 -0
- package/dist/commands/link.d.ts +11 -0
- package/dist/commands/link.js +139 -0
- package/dist/commands/login.d.ts +22 -0
- package/dist/commands/login.js +345 -0
- package/dist/commands/logout.d.ts +9 -0
- package/dist/commands/logout.js +38 -0
- package/dist/commands/logs.d.ts +10 -0
- package/dist/commands/logs.js +64 -0
- package/dist/commands/mcp/serve.d.ts +11 -0
- package/dist/commands/mcp/serve.js +818 -0
- package/dist/commands/migrate.d.ts +11 -0
- package/dist/commands/migrate.js +137 -0
- package/dist/commands/open.d.ts +10 -0
- package/dist/commands/open.js +79 -0
- package/dist/commands/projects.d.ts +10 -0
- package/dist/commands/projects.js +106 -0
- package/dist/commands/schema/diff.d.ts +7 -0
- package/dist/commands/schema/diff.js +63 -0
- package/dist/commands/schema/pull.d.ts +9 -0
- package/dist/commands/schema/pull.js +81 -0
- package/dist/commands/schema/push.d.ts +9 -0
- package/dist/commands/schema/push.js +97 -0
- package/dist/commands/schema/validate.d.ts +9 -0
- package/dist/commands/schema/validate.js +90 -0
- package/dist/commands/server/new.d.ts +2 -19
- package/dist/commands/server/new.js +6 -192
- package/dist/commands/server/scaffold.d.ts +2 -25
- package/dist/commands/server/scaffold.js +6 -312
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +53 -0
- package/dist/commands/unlink.d.ts +9 -0
- package/dist/commands/unlink.js +47 -0
- package/dist/commands/whoami.d.ts +10 -0
- package/dist/commands/whoami.js +97 -0
- package/dist/lib/api/client.js +1 -1
- package/dist/lib/api/services.js +3 -3
- package/dist/lib/api/types.d.ts +9 -2
- package/dist/lib/apsorc-parser.d.ts +0 -19
- package/dist/lib/apsorc-parser.js +2 -73
- package/dist/lib/guards.d.ts +3 -20
- package/dist/lib/guards.js +1 -113
- package/dist/lib/index.d.ts +1 -9
- package/dist/lib/index.js +1 -18
- package/dist/lib/migrate/entity-generator.d.ts +14 -0
- package/dist/lib/migrate/entity-generator.js +7 -0
- package/dist/lib/migrate/sandbox.d.ts +42 -0
- package/dist/lib/migrate/sandbox.js +337 -0
- package/dist/lib/migrate/snapshot.d.ts +80 -0
- package/dist/lib/migrate/snapshot.js +100 -0
- package/dist/lib/templates/python/models/model-col-datetime.eta +1 -1
- package/dist/lib/templates/python/models/model-col-string.eta +1 -1
- package/dist/lib/templates/python/models/model-col-text.eta +1 -1
- package/dist/lib/templates/python/models/model-col-varchar.eta +1 -1
- package/dist/lib/utils/field.d.ts +12 -0
- package/dist/lib/utils/field.js +80 -1
- package/dist/lib/utils/schema-convert.d.ts +71 -0
- package/dist/lib/utils/schema-convert.js +169 -0
- package/dist/lib/utils/spinner.d.ts +19 -0
- package/dist/lib/utils/spinner.js +87 -0
- package/dist/lib/utils/template.d.ts +12 -0
- package/dist/lib/utils/template.js +49 -0
- package/npm-shrinkwrap.json +18118 -0
- package/oclif.manifest.json +547 -41
- package/package.json +26 -5
- package/dist/lib/controller.d.ts +0 -10
- package/dist/lib/controller.js +0 -99
- package/dist/lib/dto.d.ts +0 -16
- package/dist/lib/dto.js +0 -92
- package/dist/lib/entity.d.ts +0 -19
- package/dist/lib/entity.js +0 -56
- package/dist/lib/enums.d.ts +0 -6
- package/dist/lib/enums.js +0 -28
- package/dist/lib/gql-dto.d.ts +0 -3
- package/dist/lib/gql-dto.js +0 -39
- package/dist/lib/index-module.d.ts +0 -13
- package/dist/lib/index-module.js +0 -26
- package/dist/lib/module.d.ts +0 -13
- package/dist/lib/module.js +0 -42
- package/dist/lib/service.d.ts +0 -2
- package/dist/lib/service.js +0 -61
|
@@ -1,321 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const core_1 = require("@oclif/core");
|
|
5
|
-
const path = tslib_1.__importStar(require("path"));
|
|
6
|
-
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
7
|
-
const lib_1 = require("../../lib");
|
|
8
4
|
const base_command_1 = tslib_1.__importDefault(require("../../lib/base-command"));
|
|
9
|
-
const apsorc_parser_1 = require("../../lib/apsorc-parser");
|
|
10
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
11
|
-
const Eta = tslib_1.__importStar(require("eta"));
|
|
12
|
-
const file_system_1 = require("../../lib/utils/file-system");
|
|
13
|
-
Eta.configure({
|
|
14
|
-
views: path.join(__dirname, "../../lib/templates"),
|
|
15
|
-
cache: false,
|
|
16
|
-
});
|
|
17
5
|
class Scaffold extends base_command_1.default {
|
|
18
|
-
async scaffoldServer(options) {
|
|
19
|
-
const { dir, entity, relationshipMap, apiType, allEntities } = options;
|
|
20
|
-
const entityBuildStart = perf_hooks_1.performance.now();
|
|
21
|
-
this.log(`Building... ${entity.name}`);
|
|
22
|
-
const entityName = entity.name;
|
|
23
|
-
const filePath = path.join(dir, entityName);
|
|
24
|
-
const entityRelationships = relationshipMap[entity.name] || [];
|
|
25
|
-
await (0, lib_1.createEntity)({
|
|
26
|
-
apiBaseDir: filePath,
|
|
27
|
-
entity,
|
|
28
|
-
relationships: entityRelationships,
|
|
29
|
-
apiType,
|
|
30
|
-
allEntities,
|
|
31
|
-
});
|
|
32
|
-
switch (apiType) {
|
|
33
|
-
case apsorc_parser_1.ApiType.Graphql:
|
|
34
|
-
await this.setupGraphqlFiles(dir, entity, relationshipMap);
|
|
35
|
-
break;
|
|
36
|
-
case apsorc_parser_1.ApiType.Rest:
|
|
37
|
-
await this.setupRestFiles(dir, entity, relationshipMap, apiType, allEntities);
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
break;
|
|
41
|
-
}
|
|
42
|
-
await (0, lib_1.createModule)(filePath, entity, { apiType });
|
|
43
|
-
const entityBuildTime = perf_hooks_1.performance.now() - entityBuildStart;
|
|
44
|
-
console.log(`[apso] Finished building entity '${entity.name}' in ${entityBuildTime.toFixed(2)} ms`);
|
|
45
|
-
}
|
|
46
|
-
async setupRestFiles(dir, entity, relationshipMap, apiType, allEntities) {
|
|
47
|
-
const filePath = path.join(dir, entity.name);
|
|
48
|
-
const entityRelationships = relationshipMap[entity.name] || [];
|
|
49
|
-
const tDto = perf_hooks_1.performance.now();
|
|
50
|
-
await (0, lib_1.createDto)(filePath, entity, entityRelationships, {
|
|
51
|
-
apiType,
|
|
52
|
-
allEntities,
|
|
53
|
-
});
|
|
54
|
-
if (process.env.DEBUG) {
|
|
55
|
-
console.log(`[timing] createDto for ${entity.name}: ${(perf_hooks_1.performance.now() - tDto).toFixed(2)}ms`);
|
|
56
|
-
const used = process.memoryUsage();
|
|
57
|
-
console.log(`[mem] heapUsed after createDto for ${entity.name}: ${(used.heapUsed /
|
|
58
|
-
1024 /
|
|
59
|
-
1024).toFixed(2)} MB`);
|
|
60
|
-
}
|
|
61
|
-
const tService = perf_hooks_1.performance.now();
|
|
62
|
-
await (0, lib_1.createService)(filePath, entity, relationshipMap);
|
|
63
|
-
if (process.env.DEBUG) {
|
|
64
|
-
console.log(`[timing] createService for ${entity.name}: ${(perf_hooks_1.performance.now() - tService).toFixed(2)}ms`);
|
|
65
|
-
const used = process.memoryUsage();
|
|
66
|
-
console.log(`[mem] heapUsed after createService for ${entity.name}: ${(used.heapUsed /
|
|
67
|
-
1024 /
|
|
68
|
-
1024).toFixed(2)} MB`);
|
|
69
|
-
}
|
|
70
|
-
const tController = perf_hooks_1.performance.now();
|
|
71
|
-
await (0, lib_1.createController)(filePath, entity, relationshipMap);
|
|
72
|
-
if (process.env.DEBUG) {
|
|
73
|
-
console.log(`[timing] createController for ${entity.name}: ${(perf_hooks_1.performance.now() - tController).toFixed(2)}ms`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async setupGraphqlFiles(dir, entity, relationshipMap) {
|
|
77
|
-
const filePath = path.join(dir, entity.name);
|
|
78
|
-
const entityRelationships = relationshipMap[entity.name] || [];
|
|
79
|
-
await (0, lib_1.createGqlDTO)(filePath, entity, entityRelationships);
|
|
80
|
-
}
|
|
81
6
|
async run() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const totalBuildStart = perf_hooks_1.performance.now();
|
|
85
|
-
const { rootFolder, entities, relationshipMap, apiType, auth, language: configLanguage } = (0, lib_1.parseApsorc)();
|
|
86
|
-
// Resolve language: flag > .apsorc > prompt
|
|
87
|
-
let language;
|
|
88
|
-
if (flags.language) {
|
|
89
|
-
language = flags.language;
|
|
90
|
-
}
|
|
91
|
-
else if (configLanguage && (0, lib_1.isLanguageSupported)(configLanguage)) {
|
|
92
|
-
language = configLanguage;
|
|
93
|
-
console.log(`[apso] Using language from .apsorc: ${language}`);
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
// Prompt the user
|
|
97
|
-
const implementedLanguages = (0, lib_1.getImplementedLanguages)();
|
|
98
|
-
const { selectedLanguage } = await inquirer_1.default.prompt([
|
|
99
|
-
{
|
|
100
|
-
type: "list",
|
|
101
|
-
name: "selectedLanguage",
|
|
102
|
-
message: "Select target language for code generation:",
|
|
103
|
-
choices: implementedLanguages.map((lang) => ({
|
|
104
|
-
name: lang === "typescript" ? "TypeScript (NestJS + TypeORM)" :
|
|
105
|
-
lang === "python" ? "Python (FastAPI + SQLAlchemy)" :
|
|
106
|
-
"Go (Gin + GORM)",
|
|
107
|
-
value: lang,
|
|
108
|
-
})),
|
|
109
|
-
default: "typescript",
|
|
110
|
-
},
|
|
111
|
-
]);
|
|
112
|
-
language = selectedLanguage;
|
|
113
|
-
}
|
|
114
|
-
// Validate language support
|
|
115
|
-
if (!(0, lib_1.isLanguageSupported)(language)) {
|
|
116
|
-
this.error(`Unsupported language: ${language}. Supported: typescript, python, go`);
|
|
117
|
-
}
|
|
118
|
-
const implementedLanguages = (0, lib_1.getImplementedLanguages)();
|
|
119
|
-
if (!implementedLanguages.includes(language)) {
|
|
120
|
-
this.error(`Language '${language}' is not yet implemented. Currently available: ${implementedLanguages.join(", ")}`);
|
|
121
|
-
}
|
|
122
|
-
const rootPath = path.join(process.cwd(), rootFolder);
|
|
123
|
-
const autogenPath = path.join(rootPath, "autogen");
|
|
124
|
-
const lowerCaseApiType = apiType.toLowerCase();
|
|
125
|
-
console.log(`[apso] Generating ${language} code for ${entities.length} entities...`);
|
|
126
|
-
// For TypeScript, use the existing code path (for backward compatibility)
|
|
127
|
-
// For other languages, use the new generator system
|
|
128
|
-
await (language === "typescript" ? this.scaffoldTypeScript({
|
|
129
|
-
autogenPath,
|
|
130
|
-
rootPath,
|
|
131
|
-
entities,
|
|
132
|
-
relationshipMap,
|
|
133
|
-
apiType: lowerCaseApiType,
|
|
134
|
-
auth,
|
|
135
|
-
skipFormat,
|
|
136
|
-
}) : this.scaffoldWithGenerator({
|
|
137
|
-
language,
|
|
138
|
-
rootFolder,
|
|
139
|
-
autogenPath,
|
|
140
|
-
entities,
|
|
141
|
-
relationshipMap,
|
|
142
|
-
apiType: lowerCaseApiType,
|
|
143
|
-
auth,
|
|
144
|
-
skipFormat,
|
|
145
|
-
}));
|
|
146
|
-
const totalBuildTime = perf_hooks_1.performance.now() - totalBuildStart;
|
|
147
|
-
console.log(`[apso] Finished building all entities in ${totalBuildTime.toFixed(2)} ms`);
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Scaffolds TypeScript code using the existing code path (for backward compatibility)
|
|
151
|
-
*/
|
|
152
|
-
async scaffoldTypeScript(options) {
|
|
153
|
-
const { autogenPath, rootPath, entities, relationshipMap, apiType, auth, skipFormat } = options;
|
|
154
|
-
await (0, lib_1.createEnums)(autogenPath, entities, apiType);
|
|
155
|
-
await Promise.all(entities.map(async (entity) => {
|
|
156
|
-
const scaffoldModel = this.scaffoldServer.bind(this);
|
|
157
|
-
await scaffoldModel({
|
|
158
|
-
dir: autogenPath,
|
|
159
|
-
entity,
|
|
160
|
-
relationshipMap,
|
|
161
|
-
apiType,
|
|
162
|
-
allEntities: entities,
|
|
163
|
-
});
|
|
164
|
-
if (process.env.DEBUG) {
|
|
165
|
-
const used = process.memoryUsage();
|
|
166
|
-
console.log(`[mem] heapUsed after ${entity.name}: ${(used.heapUsed /
|
|
167
|
-
1024 /
|
|
168
|
-
1024).toFixed(2)} MB`);
|
|
169
|
-
}
|
|
170
|
-
}));
|
|
171
|
-
// Generate guards (auth and/or scope) based on .apsorc configuration
|
|
172
|
-
await (0, lib_1.createGuards)(rootPath, entities, auth);
|
|
173
|
-
await (0, lib_1.createIndexAppModule)(autogenPath, entities, apiType);
|
|
174
|
-
if (skipFormat) {
|
|
175
|
-
console.log("[apso] Skipping formatting (--skip-format flag set)");
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
const formatStart = perf_hooks_1.performance.now();
|
|
179
|
-
console.log("[apso] Formatting files...");
|
|
180
|
-
await this.runNpmCommand(["run", "format", "src/autogen/**/*.ts", "src/guards/**/*.ts"], true);
|
|
181
|
-
const formatTime = perf_hooks_1.performance.now() - formatStart;
|
|
182
|
-
console.log(`[apso] Finished formatting in ${formatTime.toFixed(2)} ms`);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Scaffolds code using the new generator system (for Python, Go, and future languages)
|
|
187
|
-
* Note: Sequential file operations are intentional to provide progress feedback
|
|
188
|
-
*/
|
|
189
|
-
/* eslint-disable no-await-in-loop */
|
|
190
|
-
async scaffoldWithGenerator(options) {
|
|
191
|
-
const { language, rootFolder, autogenPath, entities, relationshipMap, apiType, auth } = options;
|
|
192
|
-
// Create generator configuration
|
|
193
|
-
const generatorConfig = {
|
|
194
|
-
language,
|
|
195
|
-
rootFolder,
|
|
196
|
-
apiType,
|
|
197
|
-
entities,
|
|
198
|
-
relationshipMap,
|
|
199
|
-
auth,
|
|
200
|
-
};
|
|
201
|
-
// Create the appropriate generator
|
|
202
|
-
const generator = (0, lib_1.createGenerator)(generatorConfig);
|
|
203
|
-
// Validate configuration
|
|
204
|
-
const validationResult = generator.validateConfig(generatorConfig);
|
|
205
|
-
if (!validationResult.valid) {
|
|
206
|
-
this.error(`Configuration validation failed:\n${validationResult.errors.join("\n")}`);
|
|
207
|
-
}
|
|
208
|
-
if (validationResult.warnings.length > 0) {
|
|
209
|
-
console.log(`[apso] Warnings:\n${validationResult.warnings.join("\n")}`);
|
|
210
|
-
}
|
|
211
|
-
// Generate enums
|
|
212
|
-
const enumFiles = await generator.generateEnums(entities, apiType);
|
|
213
|
-
for (const file of enumFiles) {
|
|
214
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
215
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
216
|
-
console.log(`[apso] Generated ${fullPath}`);
|
|
217
|
-
}
|
|
218
|
-
// Generate files for each entity
|
|
219
|
-
for (const entity of entities) {
|
|
220
|
-
console.log(`[apso] Building... ${entity.name}`);
|
|
221
|
-
const entityBuildStart = perf_hooks_1.performance.now();
|
|
222
|
-
const entityRelationships = relationshipMap[entity.name] || [];
|
|
223
|
-
// Generate entity files
|
|
224
|
-
const entityFiles = await generator.generateEntity({
|
|
225
|
-
entity,
|
|
226
|
-
relationships: entityRelationships,
|
|
227
|
-
allEntities: entities,
|
|
228
|
-
apiType,
|
|
229
|
-
});
|
|
230
|
-
for (const file of entityFiles) {
|
|
231
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
232
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
233
|
-
}
|
|
234
|
-
// Generate DTO files
|
|
235
|
-
const dtoFiles = await generator.generateDto({
|
|
236
|
-
entity,
|
|
237
|
-
relationships: entityRelationships,
|
|
238
|
-
allEntities: entities,
|
|
239
|
-
apiType,
|
|
240
|
-
});
|
|
241
|
-
for (const file of dtoFiles) {
|
|
242
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
243
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
244
|
-
}
|
|
245
|
-
// Generate service files
|
|
246
|
-
const serviceFiles = await generator.generateService({
|
|
247
|
-
entity,
|
|
248
|
-
relationships: entityRelationships,
|
|
249
|
-
allEntities: entities,
|
|
250
|
-
apiType,
|
|
251
|
-
relationshipMap,
|
|
252
|
-
});
|
|
253
|
-
for (const file of serviceFiles) {
|
|
254
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
255
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
256
|
-
}
|
|
257
|
-
// Generate controller files
|
|
258
|
-
const controllerFiles = await generator.generateController({
|
|
259
|
-
entity,
|
|
260
|
-
relationships: entityRelationships,
|
|
261
|
-
allEntities: entities,
|
|
262
|
-
apiType,
|
|
263
|
-
relationshipMap,
|
|
264
|
-
});
|
|
265
|
-
for (const file of controllerFiles) {
|
|
266
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
267
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
268
|
-
}
|
|
269
|
-
// Generate module files
|
|
270
|
-
const moduleFiles = await generator.generateModule({
|
|
271
|
-
entity,
|
|
272
|
-
relationships: entityRelationships,
|
|
273
|
-
allEntities: entities,
|
|
274
|
-
apiType,
|
|
275
|
-
});
|
|
276
|
-
for (const file of moduleFiles) {
|
|
277
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
278
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
279
|
-
}
|
|
280
|
-
const entityBuildTime = perf_hooks_1.performance.now() - entityBuildStart;
|
|
281
|
-
console.log(`[apso] Finished building entity '${entity.name}' in ${entityBuildTime.toFixed(2)} ms`);
|
|
282
|
-
}
|
|
283
|
-
// Generate guards
|
|
284
|
-
const guardFiles = await generator.generateGuards(entities, auth);
|
|
285
|
-
const rootPath = path.dirname(autogenPath);
|
|
286
|
-
for (const file of guardFiles) {
|
|
287
|
-
const fullPath = path.join(rootPath, "autogen", file.path);
|
|
288
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
289
|
-
console.log(`[apso] Generated ${fullPath}`);
|
|
290
|
-
}
|
|
291
|
-
// Generate index module
|
|
292
|
-
const indexFiles = await generator.generateIndexModule(entities, apiType);
|
|
293
|
-
for (const file of indexFiles) {
|
|
294
|
-
const fullPath = path.join(autogenPath, file.path);
|
|
295
|
-
await (0, file_system_1.createFile)(fullPath, file.content);
|
|
296
|
-
console.log(`[apso] Generated ${fullPath}`);
|
|
297
|
-
}
|
|
7
|
+
this.warn('"apso server scaffold" is deprecated. Use "apso generate" instead.');
|
|
8
|
+
await this.config.runCommand("generate", this.argv);
|
|
298
9
|
}
|
|
299
10
|
}
|
|
300
|
-
Scaffold.
|
|
301
|
-
Scaffold.
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
`$ apso server scaffold --language typescript`,
|
|
305
|
-
`$ apso server scaffold --language python`,
|
|
306
|
-
`$ apso server scaffold --language go`,
|
|
307
|
-
];
|
|
308
|
-
Scaffold.flags = {
|
|
309
|
-
help: core_1.Flags.help({ char: "h" }),
|
|
310
|
-
"skip-format": core_1.Flags.boolean({
|
|
311
|
-
description: "Skip the formatting step (useful when prettier is not available)",
|
|
312
|
-
default: false,
|
|
313
|
-
}),
|
|
314
|
-
language: core_1.Flags.string({
|
|
315
|
-
char: "l",
|
|
316
|
-
description: "Target language for code generation (typescript, python, go). If not specified, uses .apsorc config or prompts.",
|
|
317
|
-
options: ["typescript", "python", "go"],
|
|
318
|
-
}),
|
|
319
|
-
};
|
|
320
|
-
Scaffold.args = {};
|
|
11
|
+
Scaffold.hidden = true;
|
|
12
|
+
Scaffold.description = "[Deprecated] Use 'apso generate' instead";
|
|
13
|
+
Scaffold.examples = [`$ apso generate`];
|
|
14
|
+
Scaffold.strict = false;
|
|
321
15
|
exports.default = Scaffold;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const base_command_1 = tslib_1.__importDefault(require("../lib/base-command"));
|
|
5
|
+
const config_1 = require("../lib/config");
|
|
6
|
+
const services_1 = require("../lib/api/services");
|
|
7
|
+
class Status extends base_command_1.default {
|
|
8
|
+
async run() {
|
|
9
|
+
// Auth guard
|
|
10
|
+
if (!config_1.credentials.isValid()) {
|
|
11
|
+
this.error("Not logged in. Run 'apso login' first.");
|
|
12
|
+
}
|
|
13
|
+
// Link guard
|
|
14
|
+
const link = config_1.projectLink.read();
|
|
15
|
+
if (!link) {
|
|
16
|
+
this.error("Project not linked. Run 'apso link' first.");
|
|
17
|
+
}
|
|
18
|
+
// Fetch service
|
|
19
|
+
const service = await services_1.servicesApi.get(link.workspaceSlug, link.serviceSlug);
|
|
20
|
+
this.log(`Service: ${service.name} (${service.slug})`);
|
|
21
|
+
this.log(`Workspace: ${link.workspaceSlug}`);
|
|
22
|
+
this.log(`Status: ${service.status}`);
|
|
23
|
+
this.log(`GitHub: ${service.githubRepo || "not connected"}`);
|
|
24
|
+
if (service.endpoint) {
|
|
25
|
+
this.log(`Endpoint: ${service.endpoint}`);
|
|
26
|
+
}
|
|
27
|
+
if (service.lastDeployedAt) {
|
|
28
|
+
this.log(`Last deployed: ${new Date(service.lastDeployedAt).toLocaleString()}`);
|
|
29
|
+
}
|
|
30
|
+
// Fetch latest build
|
|
31
|
+
const latestBuild = await services_1.buildApi.getLatest(link.workspaceSlug, link.serviceSlug);
|
|
32
|
+
if (latestBuild) {
|
|
33
|
+
this.log("");
|
|
34
|
+
this.log("Latest build:");
|
|
35
|
+
this.log(` ID: ${latestBuild.id}`);
|
|
36
|
+
this.log(` Status: ${latestBuild.status}`);
|
|
37
|
+
this.log(` Started: ${new Date(latestBuild.startedAt).toLocaleString()}`);
|
|
38
|
+
if (latestBuild.completedAt) {
|
|
39
|
+
this.log(` Completed: ${new Date(latestBuild.completedAt).toLocaleString()}`);
|
|
40
|
+
}
|
|
41
|
+
if (latestBuild.error) {
|
|
42
|
+
this.log(` Error: ${latestBuild.error}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.log("\nNo builds found. Run 'apso deploy' to trigger one.");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
Status.description = "Show the current service and latest build status";
|
|
51
|
+
Status.examples = [`$ apso status`];
|
|
52
|
+
Status.flags = {};
|
|
53
|
+
exports.default = Status;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import BaseCommand from "../lib/base-command";
|
|
2
|
+
export default class Unlink extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
yes: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
|
|
6
|
+
const base_command_1 = tslib_1.__importDefault(require("../lib/base-command"));
|
|
7
|
+
const config_1 = require("../lib/config");
|
|
8
|
+
class Unlink extends base_command_1.default {
|
|
9
|
+
async run() {
|
|
10
|
+
const { flags } = await this.parse(Unlink);
|
|
11
|
+
const link = config_1.projectLink.read();
|
|
12
|
+
if (!link) {
|
|
13
|
+
this.log("Project is not linked. Nothing to do.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
this.log(`Currently linked to: ${link.workspaceSlug}/${link.serviceSlug}`);
|
|
17
|
+
if (!flags.yes) {
|
|
18
|
+
const { confirm } = await inquirer_1.default.prompt([
|
|
19
|
+
{
|
|
20
|
+
type: "confirm",
|
|
21
|
+
name: "confirm",
|
|
22
|
+
message: "Remove project link?",
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
]);
|
|
26
|
+
if (!confirm) {
|
|
27
|
+
this.log("Unlink cancelled.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
config_1.projectLink.remove();
|
|
32
|
+
this.log("Project unlinked.");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
Unlink.description = "Remove the link between this project and the platform";
|
|
36
|
+
Unlink.examples = [
|
|
37
|
+
`$ apso unlink`,
|
|
38
|
+
`$ apso unlink --yes`,
|
|
39
|
+
];
|
|
40
|
+
Unlink.flags = {
|
|
41
|
+
yes: core_1.Flags.boolean({
|
|
42
|
+
char: "y",
|
|
43
|
+
description: "Skip confirmation prompt",
|
|
44
|
+
default: false,
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
exports.default = Unlink;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import BaseCommand from "../lib/base-command";
|
|
2
|
+
export default class Whoami extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
7
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const base_command_1 = tslib_1.__importDefault(require("../lib/base-command"));
|
|
6
|
+
const config_1 = require("../lib/config");
|
|
7
|
+
class Whoami extends base_command_1.default {
|
|
8
|
+
async run() {
|
|
9
|
+
const { flags } = await this.parse(Whoami);
|
|
10
|
+
const creds = config_1.credentials.read();
|
|
11
|
+
if (!creds) {
|
|
12
|
+
if (flags.json) {
|
|
13
|
+
this.log(JSON.stringify({ authenticated: false }, null, 2));
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
this.log("Not logged in. Run 'apso login' to authenticate.");
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const config = config_1.globalConfig.read();
|
|
21
|
+
const link = config_1.projectLink.read();
|
|
22
|
+
// Check if session is valid
|
|
23
|
+
const isValid = config_1.credentials.isValid();
|
|
24
|
+
const needsRefresh = config_1.credentials.needsRefresh();
|
|
25
|
+
const info = {
|
|
26
|
+
authenticated: true,
|
|
27
|
+
user: {
|
|
28
|
+
id: creds.user.id,
|
|
29
|
+
email: creds.user.email,
|
|
30
|
+
name: creds.user.name || undefined,
|
|
31
|
+
},
|
|
32
|
+
session: {
|
|
33
|
+
valid: isValid,
|
|
34
|
+
needsRefresh,
|
|
35
|
+
expiresAt: creds.tokens.expiresAt,
|
|
36
|
+
},
|
|
37
|
+
context: {
|
|
38
|
+
workspace: (link === null || link === void 0 ? void 0 : link.workspaceSlug) || config.defaultWorkspace || undefined,
|
|
39
|
+
service: (link === null || link === void 0 ? void 0 : link.serviceSlug) || undefined,
|
|
40
|
+
},
|
|
41
|
+
config: {
|
|
42
|
+
apiUrl: config.apiUrl,
|
|
43
|
+
webUrl: config.webUrl,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
if (flags.json) {
|
|
47
|
+
this.log(JSON.stringify(info, null, 2));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// Pretty print
|
|
51
|
+
this.log("");
|
|
52
|
+
this.log(` Email: ${creds.user.email}`);
|
|
53
|
+
if (creds.user.name) {
|
|
54
|
+
this.log(` Name: ${creds.user.name}`);
|
|
55
|
+
}
|
|
56
|
+
this.log(` User ID: ${creds.user.id}`);
|
|
57
|
+
this.log("");
|
|
58
|
+
// Session status
|
|
59
|
+
if (!isValid) {
|
|
60
|
+
this.log(" Session: Expired (run 'apso login' to refresh)");
|
|
61
|
+
}
|
|
62
|
+
else if (needsRefresh) {
|
|
63
|
+
this.log(" Session: Valid (will refresh soon)");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this.log(" Session: Valid");
|
|
67
|
+
}
|
|
68
|
+
this.log("");
|
|
69
|
+
// Context
|
|
70
|
+
if (link) {
|
|
71
|
+
this.log(` Workspace: ${link.workspaceSlug}`);
|
|
72
|
+
this.log(` Service: ${link.serviceSlug}`);
|
|
73
|
+
}
|
|
74
|
+
else if (config.defaultWorkspace) {
|
|
75
|
+
this.log(` Workspace: ${config.defaultWorkspace} (default)`);
|
|
76
|
+
this.log(" Service: None (run 'apso use <service>' to set)");
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.log(" Workspace: None (run 'apso use <service>' to set)");
|
|
80
|
+
this.log(" Service: None");
|
|
81
|
+
}
|
|
82
|
+
this.log("");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
Whoami.description = "Display information about the current user and context";
|
|
86
|
+
Whoami.examples = [
|
|
87
|
+
"$ apso whoami",
|
|
88
|
+
"$ apso whoami --json",
|
|
89
|
+
];
|
|
90
|
+
Whoami.flags = {
|
|
91
|
+
help: core_1.Flags.help({ char: "h" }),
|
|
92
|
+
json: core_1.Flags.boolean({
|
|
93
|
+
description: "Output as JSON",
|
|
94
|
+
default: false,
|
|
95
|
+
}),
|
|
96
|
+
};
|
|
97
|
+
exports.default = Whoami;
|
package/dist/lib/api/client.js
CHANGED
|
@@ -114,7 +114,7 @@ async function refreshAccessToken() {
|
|
|
114
114
|
}
|
|
115
115
|
try {
|
|
116
116
|
const config = config_1.globalConfig.read();
|
|
117
|
-
const response = await fetch(`${config.apiUrl}/auth/cli/refresh`, {
|
|
117
|
+
const response = await fetch(`${config.apiUrl}/api/auth/cli/refresh`, {
|
|
118
118
|
method: "POST",
|
|
119
119
|
headers: {
|
|
120
120
|
"Content-Type": "application/json",
|
package/dist/lib/api/services.js
CHANGED
|
@@ -15,19 +15,19 @@ exports.authApi = {
|
|
|
15
15
|
* Exchange OAuth authorization code for tokens
|
|
16
16
|
*/
|
|
17
17
|
exchangeCode(code) {
|
|
18
|
-
return client_1.api.post("/auth/cli/exchange", { code }, { skipAuth: true });
|
|
18
|
+
return client_1.api.post("/api/auth/cli/exchange", { code }, { skipAuth: true });
|
|
19
19
|
},
|
|
20
20
|
/**
|
|
21
21
|
* Get current user profile
|
|
22
22
|
*/
|
|
23
23
|
getProfile() {
|
|
24
|
-
return client_1.api.get("/auth/me");
|
|
24
|
+
return client_1.api.get("/api/auth/me");
|
|
25
25
|
},
|
|
26
26
|
/**
|
|
27
27
|
* Revoke current session
|
|
28
28
|
*/
|
|
29
29
|
logout() {
|
|
30
|
-
return client_1.api.post("/auth/cli/logout");
|
|
30
|
+
return client_1.api.post("/api/auth/cli/logout");
|
|
31
31
|
},
|
|
32
32
|
};
|
|
33
33
|
/**
|
package/dist/lib/api/types.d.ts
CHANGED
|
@@ -164,8 +164,15 @@ export interface UserProfile {
|
|
|
164
164
|
export interface TokenExchangeResponse {
|
|
165
165
|
accessToken: string;
|
|
166
166
|
refreshToken: string;
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Token expiration as ISO timestamp string
|
|
169
|
+
*/
|
|
170
|
+
expiresAt: string;
|
|
171
|
+
/**
|
|
172
|
+
* Optional: Token expiration in seconds (for compatibility)
|
|
173
|
+
*/
|
|
174
|
+
expiresIn?: number;
|
|
175
|
+
tokenType?: string;
|
|
169
176
|
user: {
|
|
170
177
|
id: string;
|
|
171
178
|
email: string;
|
|
@@ -30,29 +30,10 @@ type ParsedApsorc = {
|
|
|
30
30
|
export declare const parseApsorcV1: (apsorc: ApsorcType) => ParsedApsorcData;
|
|
31
31
|
export declare const parseApsorcV2: (apsorc: ApsorcType) => ParsedApsorcData;
|
|
32
32
|
export declare const parseApsorc: () => ParsedApsorc;
|
|
33
|
-
/**
|
|
34
|
-
* Represents the unified configuration structure after parsing and potential migration.
|
|
35
|
-
*/
|
|
36
|
-
interface UnifiedConfig {
|
|
37
|
-
entities: Entity[];
|
|
38
|
-
relationships: ApsorcRelationship[];
|
|
39
|
-
rootFolder: string;
|
|
40
|
-
}
|
|
41
33
|
/**
|
|
42
34
|
* Finds the .apsorc configuration file path.
|
|
43
35
|
* Searches upwards from the current working directory.
|
|
44
36
|
* @returns The absolute path to the .apsorc file, or null if not found.
|
|
45
37
|
*/
|
|
46
38
|
export declare const findConfigPath: () => string | null;
|
|
47
|
-
/**
|
|
48
|
-
* Loads, validates, and potentially migrates the .apsorc configuration.
|
|
49
|
-
* Uses the `rc` library to find and load the .apsorc file.
|
|
50
|
-
* Detects config version (V1 or V2) and migrates V1 to V2 if necessary.
|
|
51
|
-
* Performs basic validation on the final V2 structure.
|
|
52
|
-
* @param appName The name of the application (used by `rc`). Defaults to 'apso'.
|
|
53
|
-
* @param defaults Default configuration values (used by `rc`).
|
|
54
|
-
* @returns The unified configuration (entities, relationships, rootFolder).
|
|
55
|
-
* @throws Error if the config file cannot be found, is invalid, or migration fails.
|
|
56
|
-
*/
|
|
57
|
-
export declare const loadConfig: (appName?: string, defaults?: {}) => UnifiedConfig;
|
|
58
39
|
export {};
|