@aurora.purecore.codes/latest 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.
- package/ARCHITECTURE.md +416 -0
- package/BINARY_RELEASE.md +216 -0
- package/CONTEXT_SUMMARY.md +366 -0
- package/DEPLOYMENT_CHECKLIST.md +560 -0
- package/IMPLEMENTATION_STATUS.md +353 -0
- package/NIX_BINARY_ISSUE.md +264 -0
- package/QUICK_START.md +344 -0
- package/README.md +333 -0
- package/TEST_INIT_COMMAND.md +380 -0
- package/TEST_LOCAL.md +307 -0
- package/bin/aurora.js +703 -0
- package/package.json +27 -0
package/bin/aurora.js
ADDED
|
@@ -0,0 +1,703 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Command } = require('commander');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
const program = new Command();
|
|
9
|
+
|
|
10
|
+
const CACHE_DIR = path.join(os.homedir(), '.aurora_austral', 'packages');
|
|
11
|
+
const BIN_CACHE_DIR = path.join(os.homedir(), '.aurora_austral', 'bin');
|
|
12
|
+
const LOCAL_DIR = path.join(process.cwd(), 'aurora_packages');
|
|
13
|
+
const LOCAL_BIN_DIR = path.join(process.cwd(), '.aurora', 'bin');
|
|
14
|
+
const REPO_OWNER = 'Aurora-Austral';
|
|
15
|
+
const REPO_NAME = 'vault';
|
|
16
|
+
const COMPILER_REPO_OWNER = 'austral';
|
|
17
|
+
const COMPILER_REPO_NAME = 'austral';
|
|
18
|
+
const COMPILER_VERSION = 'v0.2.0';
|
|
19
|
+
const API_URL = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/contents/packages`;
|
|
20
|
+
|
|
21
|
+
// Ensure directories exist
|
|
22
|
+
function ensureDirs() {
|
|
23
|
+
if (!fs.existsSync(CACHE_DIR)) fs.mkdirSync(CACHE_DIR, { recursive: true });
|
|
24
|
+
if (!fs.existsSync(BIN_CACHE_DIR)) fs.mkdirSync(BIN_CACHE_DIR, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Detect platform
|
|
28
|
+
function getPlatform() {
|
|
29
|
+
const platform = os.platform();
|
|
30
|
+
const arch = os.arch();
|
|
31
|
+
|
|
32
|
+
if (platform === 'linux' && arch === 'x64') return 'linux-x64';
|
|
33
|
+
if (platform === 'darwin' && arch === 'x64') return 'darwin-x64';
|
|
34
|
+
if (platform === 'darwin' && arch === 'arm64') return 'darwin-arm64';
|
|
35
|
+
if (platform === 'win32' && arch === 'x64') return 'win32-x64';
|
|
36
|
+
|
|
37
|
+
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Download file using native fetch
|
|
41
|
+
async function downloadFile(url, outputPath) {
|
|
42
|
+
const response = await fetch(url, {
|
|
43
|
+
redirect: 'follow',
|
|
44
|
+
headers: {
|
|
45
|
+
'User-Agent': 'aurora-npm',
|
|
46
|
+
'Accept': 'application/octet-stream'
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
55
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
56
|
+
fs.writeFileSync(outputPath, buffer);
|
|
57
|
+
|
|
58
|
+
return outputPath;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Download directory from GitHub API
|
|
62
|
+
async function downloadDirectoryFromRepo(owner, repo, repoPath, targetDir) {
|
|
63
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${repoPath}`;
|
|
64
|
+
const response = await fetch(url, {
|
|
65
|
+
headers: { 'User-Agent': 'aurora-npm' }
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
throw new Error(`Failed to fetch ${repoPath}: ${response.statusText}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const items = await response.json();
|
|
73
|
+
|
|
74
|
+
if (!fs.existsSync(targetDir)) fs.mkdirSync(targetDir, { recursive: true });
|
|
75
|
+
|
|
76
|
+
const downloadPromises = items.map(async (item) => {
|
|
77
|
+
const itemTarget = path.join(targetDir, item.name);
|
|
78
|
+
if (item.type === 'file') {
|
|
79
|
+
const fileResponse = await fetch(item.download_url, {
|
|
80
|
+
headers: { 'User-Agent': 'aurora-npm' }
|
|
81
|
+
});
|
|
82
|
+
if (fileResponse.ok) {
|
|
83
|
+
const arrayBuffer = await fileResponse.arrayBuffer();
|
|
84
|
+
fs.writeFileSync(itemTarget, Buffer.from(arrayBuffer));
|
|
85
|
+
}
|
|
86
|
+
} else if (item.type === 'dir') {
|
|
87
|
+
await downloadDirectoryFromRepo(owner, repo, item.path, itemTarget);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
await Promise.all(downloadPromises);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Run command
|
|
95
|
+
function runCmd(cmd, cwd, silent = false) {
|
|
96
|
+
let finalCmd = cmd;
|
|
97
|
+
if (process.platform === 'win32') {
|
|
98
|
+
finalCmd = `wsl ${cmd}`;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const { execSync } = require('child_process');
|
|
102
|
+
const output = execSync(finalCmd, { cwd, stdio: silent ? 'pipe' : 'inherit', encoding: 'utf-8' });
|
|
103
|
+
return { success: true, message: output };
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
message: error.stdout || error.stderr || error.message
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Color output (simple implementation without chalk)
|
|
113
|
+
function colorize(color, text) {
|
|
114
|
+
const colors = {
|
|
115
|
+
cyan: '\x1b[36m',
|
|
116
|
+
green: '\x1b[32m',
|
|
117
|
+
yellow: '\x1b[33m',
|
|
118
|
+
red: '\x1b[31m',
|
|
119
|
+
bold: '\x1b[1m',
|
|
120
|
+
reset: '\x1b[0m'
|
|
121
|
+
};
|
|
122
|
+
return `${colors[color] || ''}${text}${colors.reset}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Simple spinner
|
|
126
|
+
class Spinner {
|
|
127
|
+
constructor(text) {
|
|
128
|
+
this.text = text;
|
|
129
|
+
this.interval = null;
|
|
130
|
+
this.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
131
|
+
this.i = 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
start() {
|
|
135
|
+
process.stdout.write(`\r${this.frames[this.i]} ${this.text}`);
|
|
136
|
+
this.interval = setInterval(() => {
|
|
137
|
+
this.i = (this.i + 1) % this.frames.length;
|
|
138
|
+
process.stdout.write(`\r${this.frames[this.i]} ${this.text}`);
|
|
139
|
+
}, 80);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
succeed(message) {
|
|
143
|
+
clearInterval(this.interval);
|
|
144
|
+
process.stdout.write(`\r${colorize('green', '✔')} ${message}\n`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
fail(message) {
|
|
148
|
+
clearInterval(this.interval);
|
|
149
|
+
process.stdout.write(`\r${colorize('red', '✖')} ${message}\n`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
info(message) {
|
|
153
|
+
clearInterval(this.interval);
|
|
154
|
+
process.stdout.write(`\r${colorize('cyan', 'ℹ')} ${message}\n`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Partial cleanup
|
|
159
|
+
async function partialCleanup(dir) {
|
|
160
|
+
if (!fs.existsSync(dir)) return;
|
|
161
|
+
const items = fs.readdirSync(dir);
|
|
162
|
+
for (const item of items) {
|
|
163
|
+
const itemPath = path.join(dir, item);
|
|
164
|
+
const stats = fs.statSync(itemPath);
|
|
165
|
+
if (stats.isFile()) {
|
|
166
|
+
const name = item.toLowerCase();
|
|
167
|
+
const shouldKeep = name.endsWith('.html') ||
|
|
168
|
+
name.includes('.test') ||
|
|
169
|
+
name.endsWith('.aui') ||
|
|
170
|
+
name.endsWith('.aum') ||
|
|
171
|
+
name === 'makefile';
|
|
172
|
+
if (!shouldKeep) {
|
|
173
|
+
fs.unlinkSync(itemPath);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Main aurora init command
|
|
180
|
+
async function initCommand(options) {
|
|
181
|
+
console.log(colorize('bold', colorize('cyan', '\n🚀 Initializing Aurora project...\n')));
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
// Create aurora.json
|
|
185
|
+
const packageJsonPath = path.join(process.cwd(), 'aurora.json');
|
|
186
|
+
|
|
187
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
188
|
+
console.log(colorize('yellow', '⚠️ aurora.json already exists'));
|
|
189
|
+
} else {
|
|
190
|
+
const packageJson = {
|
|
191
|
+
name: path.basename(process.cwd()),
|
|
192
|
+
version: '0.1.0',
|
|
193
|
+
description: 'Aurora Austral project',
|
|
194
|
+
main: 'src/Main.aum',
|
|
195
|
+
scripts: {
|
|
196
|
+
build: 'make',
|
|
197
|
+
test: 'make test',
|
|
198
|
+
clean: 'make clean'
|
|
199
|
+
},
|
|
200
|
+
dependencies: {},
|
|
201
|
+
devDependencies: {},
|
|
202
|
+
aurora: {
|
|
203
|
+
compiler: 'local',
|
|
204
|
+
stdlib: 'local'
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
209
|
+
console.log(colorize('green', '✓ Created aurora.json'));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Create directory structure
|
|
213
|
+
const srcDir = path.join(process.cwd(), 'src');
|
|
214
|
+
const auroraPackagesDir = path.join(process.cwd(), 'aurora_packages');
|
|
215
|
+
const auroraDir = path.join(process.cwd(), '.aurora');
|
|
216
|
+
|
|
217
|
+
if (!fs.existsSync(srcDir)) fs.mkdirSync(srcDir);
|
|
218
|
+
if (!fs.existsSync(auroraPackagesDir)) fs.mkdirSync(auroraPackagesDir);
|
|
219
|
+
if (!fs.existsSync(auroraDir)) fs.mkdirSync(auroraDir);
|
|
220
|
+
|
|
221
|
+
console.log(colorize('green', '✓ Created project directories'));
|
|
222
|
+
|
|
223
|
+
// Download compiler binary if requested
|
|
224
|
+
if (options.binary !== false) {
|
|
225
|
+
ensureDirs();
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const platform = getPlatform();
|
|
229
|
+
const binName = platform.startsWith('win') ? 'austral.exe' : 'austral';
|
|
230
|
+
|
|
231
|
+
const assetMap = {
|
|
232
|
+
'linux-x64': 'austral-linux',
|
|
233
|
+
'darwin-x64': 'austral-macos',
|
|
234
|
+
'darwin-arm64': 'austral-macos',
|
|
235
|
+
'win32-x64': 'austral-windows.exe'
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const assetName = assetMap[platform];
|
|
239
|
+
if (!assetName) {
|
|
240
|
+
throw new Error(`No binary available for platform ${platform}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const downloadUrl = `https://github.com/${COMPILER_REPO_OWNER}/${COMPILER_REPO_NAME}/releases/download/${COMPILER_VERSION}/${assetName}`;
|
|
244
|
+
|
|
245
|
+
const spinner = new Spinner(`Downloading ${assetName} from ${COMPILER_VERSION}...`);
|
|
246
|
+
spinner.start();
|
|
247
|
+
|
|
248
|
+
const binPath = path.join(BIN_CACHE_DIR, binName);
|
|
249
|
+
await downloadFile(downloadUrl, binPath);
|
|
250
|
+
fs.chmodSync(binPath, 0o755);
|
|
251
|
+
|
|
252
|
+
spinner.succeed(`Compiler ${COMPILER_VERSION} downloaded: ${binPath}`);
|
|
253
|
+
|
|
254
|
+
// Copy to local .aurora/bin
|
|
255
|
+
const localBinDir = path.join(process.cwd(), '.aurora', 'bin');
|
|
256
|
+
if (!fs.existsSync(localBinDir)) fs.mkdirSync(localBinDir);
|
|
257
|
+
const localBinPath = path.join(localBinDir, binName);
|
|
258
|
+
fs.copyFileSync(binPath, localBinPath);
|
|
259
|
+
fs.chmodSync(localBinPath, 0o755);
|
|
260
|
+
|
|
261
|
+
console.log(colorize('green', `✓ Compiler installed: ${localBinPath}`));
|
|
262
|
+
|
|
263
|
+
// Test if binary works
|
|
264
|
+
const testSpinner = new Spinner('Testing compiler binary...');
|
|
265
|
+
testSpinner.start();
|
|
266
|
+
|
|
267
|
+
const testResult = runCmd(`${localBinPath} --version`, process.cwd(), true);
|
|
268
|
+
|
|
269
|
+
if (!testResult.success) {
|
|
270
|
+
testSpinner.fail('Downloaded binary cannot execute (likely Nix-compiled)');
|
|
271
|
+
console.log(colorize('yellow', '⚠️ The official release binary has Nix dependencies'));
|
|
272
|
+
console.log(colorize('yellow', ' Falling back to system compiler'));
|
|
273
|
+
console.log(colorize('yellow', ' Please ensure "austral" is in your PATH'));
|
|
274
|
+
|
|
275
|
+
fs.unlinkSync(localBinPath);
|
|
276
|
+
|
|
277
|
+
const config = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
278
|
+
config.aurora.compiler = 'system';
|
|
279
|
+
config.aurora.note = 'Using system-installed austral compiler';
|
|
280
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(config, null, 2));
|
|
281
|
+
} else {
|
|
282
|
+
testSpinner.succeed('Compiler binary works!');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Download stdlib regardless of binary status
|
|
286
|
+
const stdlibSpinner = new Spinner('Downloading standard library...');
|
|
287
|
+
stdlibSpinner.start();
|
|
288
|
+
|
|
289
|
+
const stdlibPath = path.join(BIN_CACHE_DIR, 'stdlib');
|
|
290
|
+
await downloadDirectoryFromRepo(
|
|
291
|
+
COMPILER_REPO_OWNER,
|
|
292
|
+
COMPILER_REPO_NAME,
|
|
293
|
+
'standard/src',
|
|
294
|
+
stdlibPath
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
const localStdlibPath = path.join(process.cwd(), '.aurora', 'stdlib');
|
|
298
|
+
if (fs.existsSync(localStdlibPath)) {
|
|
299
|
+
fs.rmSync(localStdlibPath, { recursive: true, force: true });
|
|
300
|
+
}
|
|
301
|
+
fs.renameSync(stdlibPath, localStdlibPath);
|
|
302
|
+
|
|
303
|
+
stdlibSpinner.succeed(`Standard library installed: ${localStdlibPath}`);
|
|
304
|
+
|
|
305
|
+
// Update aurora.json
|
|
306
|
+
const config = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
307
|
+
if (testResult.success) {
|
|
308
|
+
config.aurora.compiler = 'local';
|
|
309
|
+
config.aurora.compilerPath = `.aurora/bin/${binName}`;
|
|
310
|
+
} else {
|
|
311
|
+
config.aurora.compiler = 'system';
|
|
312
|
+
config.aurora.note = 'Using system-installed austral compiler';
|
|
313
|
+
}
|
|
314
|
+
config.aurora.stdlibPath = '.aurora/stdlib';
|
|
315
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(config, null, 2));
|
|
316
|
+
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.log(colorize('yellow', `⚠️ Could not download binaries: ${error.message}`));
|
|
319
|
+
console.log(colorize('yellow', ' You can install the compiler manually or use system installation'));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Create example files
|
|
324
|
+
const mainAui = path.join(srcDir, 'Main.aui');
|
|
325
|
+
if (!fs.existsSync(mainAui)) {
|
|
326
|
+
fs.writeFileSync(mainAui, `module Example.Main is
|
|
327
|
+
function main(): ExitCode;
|
|
328
|
+
end module.
|
|
329
|
+
`);
|
|
330
|
+
console.log(colorize('green', '✓ Created src/Main.aui'));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const mainAum = path.join(srcDir, 'Main.aum');
|
|
334
|
+
if (!fs.existsSync(mainAum)) {
|
|
335
|
+
fs.writeFileSync(mainAum, `module body Example.Main is
|
|
336
|
+
function main(): ExitCode is
|
|
337
|
+
printLn("Hello, Aurora Austral!");
|
|
338
|
+
return ExitSuccess();
|
|
339
|
+
end;
|
|
340
|
+
end module body.
|
|
341
|
+
`);
|
|
342
|
+
console.log(colorize('green', '✓ Created src/Main.aum'));
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Create Makefile
|
|
346
|
+
const makefilePath = path.join(process.cwd(), 'Makefile');
|
|
347
|
+
if (!fs.existsSync(makefilePath)) {
|
|
348
|
+
const makefile = `# Aurora Austral Project Makefile
|
|
349
|
+
|
|
350
|
+
# Detect compiler - excluding broken Nix binaries in .local/bin
|
|
351
|
+
AU_COMPILER := $(shell \\
|
|
352
|
+
if [ -x ".aurora/bin/austral" ]; then \\
|
|
353
|
+
echo ".aurora/bin/austral"; \\
|
|
354
|
+
else \\
|
|
355
|
+
for path in $$(echo $$PATH | tr ':' ' '); do \\
|
|
356
|
+
if [ -x "$$path/austral" ] && echo "$$path" | grep -qv "/.local/bin"; then \\
|
|
357
|
+
echo "$$path/austral"; \\
|
|
358
|
+
break; \\
|
|
359
|
+
fi; \\
|
|
360
|
+
done; \\
|
|
361
|
+
fi)
|
|
362
|
+
|
|
363
|
+
ifeq ($(AU_COMPILER),)
|
|
364
|
+
$(error Austral compiler not found. Please install austral in /usr/local/bin)
|
|
365
|
+
endif
|
|
366
|
+
|
|
367
|
+
# Detect stdlib
|
|
368
|
+
ifneq ($(wildcard .aurora/stdlib),)
|
|
369
|
+
AUSTRAL_STDLIB = .aurora/stdlib
|
|
370
|
+
else ifneq ($(wildcard /usr/local/lib/austral/standard/src),)
|
|
371
|
+
AUSTRAL_STDLIB = /usr/local/lib/austral/standard/src
|
|
372
|
+
else ifneq ($(wildcard /usr/lib/austral/standard/src),)
|
|
373
|
+
AUSTRAL_STDLIB = /usr/lib/austral/standard/src
|
|
374
|
+
else
|
|
375
|
+
$(error AUSTRAL_STDLIB not found. Please set AUSTRAL_STDLIB environment variable)
|
|
376
|
+
endif
|
|
377
|
+
|
|
378
|
+
# Standard library modules
|
|
379
|
+
STDLIB := \\
|
|
380
|
+
$(AUSTRAL_STDLIB)/Tuples.aui,$(AUSTRAL_STDLIB)/Tuples.aum \\
|
|
381
|
+
$(AUSTRAL_STDLIB)/Bounded.aui,$(AUSTRAL_STDLIB)/Bounded.aum \\
|
|
382
|
+
$(AUSTRAL_STDLIB)/Equality.aui,$(AUSTRAL_STDLIB)/Equality.aum \\
|
|
383
|
+
$(AUSTRAL_STDLIB)/Order.aui,$(AUSTRAL_STDLIB)/Order.aum \\
|
|
384
|
+
$(AUSTRAL_STDLIB)/Box.aui,$(AUSTRAL_STDLIB)/Box.aum \\
|
|
385
|
+
$(AUSTRAL_STDLIB)/Buffer.aui,$(AUSTRAL_STDLIB)/Buffer.aum \\
|
|
386
|
+
$(AUSTRAL_STDLIB)/String.aui,$(AUSTRAL_STDLIB)/String.aum \\
|
|
387
|
+
$(AUSTRAL_STDLIB)/StringBuilder.aui,$(AUSTRAL_STDLIB)/StringBuilder.aum \\
|
|
388
|
+
$(AUSTRAL_STDLIB)/IO/IO.aui,$(AUSTRAL_STDLIB)/IO/IO.aum \\
|
|
389
|
+
$(AUSTRAL_STDLIB)/IO/Terminal.aui,$(AUSTRAL_STDLIB)/IO/Terminal.aum
|
|
390
|
+
|
|
391
|
+
SRC := src/Main.aui,src/Main.aum
|
|
392
|
+
ENTRY := Example.Main:main
|
|
393
|
+
OUTPUT := main
|
|
394
|
+
|
|
395
|
+
all: build
|
|
396
|
+
|
|
397
|
+
build:
|
|
398
|
+
@echo "Building project..."
|
|
399
|
+
@echo "Using compiler: $(AU_COMPILER)"
|
|
400
|
+
@echo "Using stdlib: $(AUSTRAL_STDLIB)"
|
|
401
|
+
$(AU_COMPILER) compile $(STDLIB) $(SRC) --entrypoint=$(ENTRY) --output=$(OUTPUT)
|
|
402
|
+
@echo "Build successful!"
|
|
403
|
+
|
|
404
|
+
run: build
|
|
405
|
+
./$(OUTPUT)
|
|
406
|
+
|
|
407
|
+
test:
|
|
408
|
+
@echo "No tests defined yet"
|
|
409
|
+
|
|
410
|
+
clean:
|
|
411
|
+
rm -f $(OUTPUT) calltree.html error.html
|
|
412
|
+
|
|
413
|
+
.PHONY: all build run test clean
|
|
414
|
+
`;
|
|
415
|
+
fs.writeFileSync(makefilePath, makefile);
|
|
416
|
+
console.log(colorize('green', '✓ Created Makefile'));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Create .gitignore
|
|
420
|
+
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
421
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
422
|
+
fs.writeFileSync(gitignorePath, `# Aurora Austral
|
|
423
|
+
aurora_packages/
|
|
424
|
+
.aurora/bin/
|
|
425
|
+
.aurora/stdlib/
|
|
426
|
+
main
|
|
427
|
+
*.o
|
|
428
|
+
calltree.html
|
|
429
|
+
error.html
|
|
430
|
+
|
|
431
|
+
# OS
|
|
432
|
+
.DS_Store
|
|
433
|
+
Thumbs.db
|
|
434
|
+
`);
|
|
435
|
+
console.log(colorize('green', '✓ Created .gitignore'));
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
console.log(colorize('bold', colorize('green', '\n✨ Project initialized successfully!\n')));
|
|
439
|
+
console.log(colorize('cyan', 'Next steps:'));
|
|
440
|
+
console.log(colorize('white', ' 1. Edit src/Main.aum'));
|
|
441
|
+
console.log(colorize('white', ' 2. Run: make build'));
|
|
442
|
+
console.log(colorize('white', ' 3. Run: ./main'));
|
|
443
|
+
console.log(colorize('white', ' 4. Install packages: aurora install <package-name>\n'));
|
|
444
|
+
|
|
445
|
+
} catch (error) {
|
|
446
|
+
console.log(colorize('red', `\n✖ Error initializing project: ${error.message}`));
|
|
447
|
+
process.exit(1);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Install package command
|
|
452
|
+
async function installPackage(packageName) {
|
|
453
|
+
ensureDirs();
|
|
454
|
+
const spinner = new Spinner(`Checking for ${packageName}...`);
|
|
455
|
+
|
|
456
|
+
const cachePath = path.join(CACHE_DIR, packageName);
|
|
457
|
+
const localPath = path.join(LOCAL_DIR, packageName);
|
|
458
|
+
|
|
459
|
+
try {
|
|
460
|
+
if (fs.existsSync(cachePath)) {
|
|
461
|
+
spinner.text = `Using cached version of ${packageName}...`;
|
|
462
|
+
if (!fs.existsSync(LOCAL_DIR)) fs.mkdirSync(LOCAL_DIR);
|
|
463
|
+
if (fs.existsSync(localPath)) fs.rmSync(localPath, { recursive: true, force: true });
|
|
464
|
+
fs.renameSync(cachePath, localPath);
|
|
465
|
+
spinner.succeed(`Package ${packageName} installed from cache.`);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
spinner.text = `Downloading ${packageName} from GitHub...`;
|
|
470
|
+
if (!fs.existsSync(LOCAL_DIR)) fs.mkdirSync(LOCAL_DIR);
|
|
471
|
+
if (fs.existsSync(localPath)) fs.rmSync(localPath, { recursive: true, force: true });
|
|
472
|
+
await downloadDirectoryFromRepo(REPO_OWNER, REPO_NAME, `packages/${packageName}`, localPath);
|
|
473
|
+
|
|
474
|
+
spinner.stop();
|
|
475
|
+
console.log(colorize('blue', `\n--- Building ${packageName} ---`));
|
|
476
|
+
const buildRes = runCmd('make', localPath, false);
|
|
477
|
+
if (!buildRes.success) {
|
|
478
|
+
await partialCleanup(localPath);
|
|
479
|
+
console.log(colorize('red', `\n✖ Build failed for ${packageName}`));
|
|
480
|
+
process.exit(1);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
console.log(colorize('blue', `\n--- Testing ${packageName} ---`));
|
|
484
|
+
const testRes = runCmd('make test', localPath, false);
|
|
485
|
+
if (!testRes.success) {
|
|
486
|
+
await partialCleanup(localPath);
|
|
487
|
+
console.log(colorize('red', `\n✖ Test failed for ${packageName}`));
|
|
488
|
+
process.exit(1);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
spinner.start(`Caching ${packageName}...`);
|
|
492
|
+
fs.renameSync(localPath, cachePath);
|
|
493
|
+
|
|
494
|
+
spinner.succeed(`Package ${packageName} installed successfully.`);
|
|
495
|
+
} catch (error) {
|
|
496
|
+
spinner.fail(`Error installing ${packageName}: ${error.message}`);
|
|
497
|
+
if (fs.existsSync(localPath)) await partialCleanup(localPath);
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// List packages command
|
|
503
|
+
async function listPackages(options) {
|
|
504
|
+
const spinner = new Spinner('Fetching list...');
|
|
505
|
+
try {
|
|
506
|
+
if (options.local) {
|
|
507
|
+
ensureDirs();
|
|
508
|
+
const files = fs.readdirSync(CACHE_DIR);
|
|
509
|
+
spinner.stop();
|
|
510
|
+
console.log(colorize('bold', 'Local cached packages (~/.aurora_austral/packages):'));
|
|
511
|
+
if (files.length === 0) console.log(' (none)');
|
|
512
|
+
files.forEach(f => console.log(` - ${f}`));
|
|
513
|
+
} else {
|
|
514
|
+
const response = await fetch(API_URL, { headers: { 'User-Agent': 'aurora-npm' } });
|
|
515
|
+
if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
516
|
+
const items = await response.json();
|
|
517
|
+
const packages = items.filter(item => item.type === 'dir').map(item => item.name);
|
|
518
|
+
spinner.stop();
|
|
519
|
+
console.log(colorize('bold', 'Remote packages (GitHub):'));
|
|
520
|
+
packages.forEach(p => console.log(` - ${p}`));
|
|
521
|
+
}
|
|
522
|
+
} catch (error) {
|
|
523
|
+
spinner.fail(`Error: ${error.message}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Find package command
|
|
528
|
+
async function findPackage(packageName) {
|
|
529
|
+
const spinner = new Spinner(`Searching for ${packageName}...`);
|
|
530
|
+
try {
|
|
531
|
+
const response = await fetch(API_URL, { headers: { 'User-Agent': 'aurora-npm' } });
|
|
532
|
+
if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);
|
|
533
|
+
const items = await response.json();
|
|
534
|
+
const packages = items.filter(item => item.type === 'dir').map(item => item.name);
|
|
535
|
+
const filtered = packages.filter(p => p.toLowerCase().includes(packageName.toLowerCase()));
|
|
536
|
+
spinner.stop();
|
|
537
|
+
if (filtered.length > 0) {
|
|
538
|
+
console.log(colorize('bold', `Found packages matching "${packageName}":`));
|
|
539
|
+
filtered.forEach(p => console.log(` - ${p}`));
|
|
540
|
+
} else {
|
|
541
|
+
console.log(colorize('yellow', `No packages found matching "${packageName}".`));
|
|
542
|
+
}
|
|
543
|
+
} catch (error) {
|
|
544
|
+
spinner.fail(`Error: ${error.message}`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Uninstall package command
|
|
549
|
+
async function uninstallPackage(packageName) {
|
|
550
|
+
const spinner = new Spinner(`Uninstalling ${packageName}...`);
|
|
551
|
+
try {
|
|
552
|
+
const localPath = path.join(LOCAL_DIR, packageName);
|
|
553
|
+
const cachePath = path.join(CACHE_DIR, packageName);
|
|
554
|
+
|
|
555
|
+
let removed = false;
|
|
556
|
+
if (fs.existsSync(localPath)) {
|
|
557
|
+
fs.rmSync(localPath, { recursive: true, force: true });
|
|
558
|
+
removed = true;
|
|
559
|
+
}
|
|
560
|
+
if (fs.existsSync(cachePath)) {
|
|
561
|
+
fs.rmSync(cachePath, { recursive: true, force: true });
|
|
562
|
+
removed = true;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (removed) {
|
|
566
|
+
spinner.succeed(`Package ${packageName} removed from local and cache.`);
|
|
567
|
+
} else {
|
|
568
|
+
spinner.info(`Package ${packageName} was not found.`);
|
|
569
|
+
}
|
|
570
|
+
} catch (error) {
|
|
571
|
+
spinner.fail(`Error uninstalling ${packageName}: ${error.message}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Test package command
|
|
576
|
+
async function testPackage(packageName) {
|
|
577
|
+
const localPath = path.join(LOCAL_DIR, packageName);
|
|
578
|
+
if (!fs.existsSync(localPath)) {
|
|
579
|
+
console.log(colorize('red', `Package ${packageName} is not installed in aurora_packages/.`));
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
console.log(colorize('blue', `Running "make test" in ${localPath}...`));
|
|
584
|
+
const res = runCmd('make test', localPath);
|
|
585
|
+
if (res.success) {
|
|
586
|
+
console.log(colorize('green', `Tests passed for ${packageName}.`));
|
|
587
|
+
} else {
|
|
588
|
+
console.log(colorize('red', `Tests failed for ${packageName}.`));
|
|
589
|
+
console.log(res.message);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Update package command
|
|
594
|
+
async function updatePackage(packageName) {
|
|
595
|
+
ensureDirs();
|
|
596
|
+
const packagesToUpdate = [];
|
|
597
|
+
|
|
598
|
+
if (packageName) {
|
|
599
|
+
packagesToUpdate.push(packageName);
|
|
600
|
+
} else {
|
|
601
|
+
if (fs.existsSync(LOCAL_DIR)) {
|
|
602
|
+
packagesToUpdate.push(...fs.readdirSync(LOCAL_DIR));
|
|
603
|
+
}
|
|
604
|
+
if (fs.existsSync(CACHE_DIR)) {
|
|
605
|
+
packagesToUpdate.push(...fs.readdirSync(CACHE_DIR));
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const uniquePackages = [...new Set(packagesToUpdate)];
|
|
610
|
+
if (uniquePackages.length === 0) {
|
|
611
|
+
console.log(colorize('yellow', 'No packages found to update.'));
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
for (const pkg of uniquePackages) {
|
|
616
|
+
const spinner = new Spinner(`Updating ${pkg}...`);
|
|
617
|
+
try {
|
|
618
|
+
const localPath = path.join(LOCAL_DIR, pkg);
|
|
619
|
+
const cachePath = path.join(CACHE_DIR, pkg);
|
|
620
|
+
|
|
621
|
+
spinner.text = `Downloading latest ${pkg}...`;
|
|
622
|
+
const tempDir = path.join(os.tmpdir(), `aurora-update-${pkg}-${Date.now()}`);
|
|
623
|
+
await downloadDirectoryFromRepo(REPO_OWNER, REPO_NAME, `packages/${pkg}`, tempDir);
|
|
624
|
+
|
|
625
|
+
spinner.stop();
|
|
626
|
+
console.log(colorize('blue', `\n--- Building ${pkg} ---`));
|
|
627
|
+
const buildRes = runCmd('make', tempDir, false);
|
|
628
|
+
if (!buildRes.success) {
|
|
629
|
+
console.log(colorize('red', `\n✖ Update failed for ${pkg} (build error)`));
|
|
630
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
console.log(colorize('blue', `\n--- Testing ${pkg} ---`));
|
|
635
|
+
const testRes = runCmd('make test', tempDir, false);
|
|
636
|
+
if (!testRes.success) {
|
|
637
|
+
console.log(colorize('red', `\n✖ Update failed for ${pkg} (test error)`));
|
|
638
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
spinner.start(`Updating ${pkg}...`);
|
|
643
|
+
|
|
644
|
+
if (fs.existsSync(localPath)) {
|
|
645
|
+
fs.rmSync(localPath, { recursive: true, force: true });
|
|
646
|
+
}
|
|
647
|
+
fs.renameSync(tempDir, localPath);
|
|
648
|
+
|
|
649
|
+
if (fs.existsSync(cachePath)) {
|
|
650
|
+
fs.rmSync(cachePath, { recursive: true, force: true });
|
|
651
|
+
}
|
|
652
|
+
fs.renameSync(localPath, cachePath);
|
|
653
|
+
|
|
654
|
+
spinner.succeed(`Package ${pkg} updated.`);
|
|
655
|
+
} catch (error) {
|
|
656
|
+
spinner.fail(`Error updating ${pkg}: ${error.message}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
program
|
|
662
|
+
.name('aurora')
|
|
663
|
+
.description('Aurora Package Manager')
|
|
664
|
+
.version('0.1.0');
|
|
665
|
+
|
|
666
|
+
program
|
|
667
|
+
.command('init')
|
|
668
|
+
.description('Initialize a new Aurora project')
|
|
669
|
+
.option('--no-binary', 'Skip downloading compiler binary')
|
|
670
|
+
.action(initCommand);
|
|
671
|
+
|
|
672
|
+
program
|
|
673
|
+
.command('install <package-name>')
|
|
674
|
+
.description('Install a package')
|
|
675
|
+
.action(installPackage);
|
|
676
|
+
|
|
677
|
+
program
|
|
678
|
+
.command('list')
|
|
679
|
+
.description('List packages')
|
|
680
|
+
.option('--local', 'List locally cached packages')
|
|
681
|
+
.action(listPackages);
|
|
682
|
+
|
|
683
|
+
program
|
|
684
|
+
.command('find <package-name>')
|
|
685
|
+
.description('Find a package')
|
|
686
|
+
.action(findPackage);
|
|
687
|
+
|
|
688
|
+
program
|
|
689
|
+
.command('uninstall <package-name>')
|
|
690
|
+
.description('Uninstall a package from project and cache')
|
|
691
|
+
.action(uninstallPackage);
|
|
692
|
+
|
|
693
|
+
program
|
|
694
|
+
.command('test <package-name>')
|
|
695
|
+
.description('Run tests for a package')
|
|
696
|
+
.action(testPackage);
|
|
697
|
+
|
|
698
|
+
program
|
|
699
|
+
.command('update [package-name]')
|
|
700
|
+
.description('Update packages (project and cache)')
|
|
701
|
+
.action(updatePackage);
|
|
702
|
+
|
|
703
|
+
program.parse(process.argv);
|