get-codex-lost-world 1.0.3

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 ADDED
@@ -0,0 +1,105 @@
1
+ # Get Codex Lost World - Codex for Desktop
2
+
3
+ Bring Codex to **Intel Mac** and **Windows** with a simple CLI workflow for build, download, and packaging. 🚀
4
+
5
+ [![Build](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/0x0a0d/get-codex-lost-world)
6
+ [![Version](https://img.shields.io/badge/version-1.0.3-blue)](https://github.com/0x0a0d/get-codex-lost-world)
7
+ [![License: ISC](https://img.shields.io/badge/license-ISC-lightgrey)](./LICENSE)
8
+ [![GitHub Stars](https://img.shields.io/github/stars/0x0a0d/get-codex-lost-world?style=social)](https://github.com/0x0a0d/get-codex-lost-world)
9
+
10
+ ![Get Codex Lost World Screenshot](./codex.png)
11
+
12
+ ## Introduction
13
+
14
+ **Get Codex** is a desktop-focused toolchain that helps users on platforms often left behind by official releases:
15
+
16
+ - macOS Intel (`.dmg`)
17
+ - Windows x64 / arm64 (`.zip`)
18
+
19
+ It automates artifact resolution, local build flow, and optional signing steps.
20
+
21
+ ## Features
22
+
23
+ - ⚡ Build mode for Intel Mac and Windows targets
24
+ - 📦 Cache/download mode for latest release artifacts
25
+ - 🪟 Windows ZIP output (x64, arm64)
26
+ - 🍎 macOS Intel DMG output
27
+ - 🔐 Optional signing flow for macOS artifacts
28
+ - 🧩 Simple CLI flags for platform, arch, format, and workdir
29
+
30
+ ## Tech Stack
31
+
32
+ - **Runtime:** Node.js
33
+ - **Language:** JavaScript (CommonJS)
34
+ - **Testing:** Node.js built-in test runner (`node --test`)
35
+ - **Packaging Scripts:** Custom Node scripts for macOS/Windows build artifacts
36
+
37
+ ## Installation
38
+
39
+ ### Option 1: Run directly with NPX
40
+
41
+ ```bash
42
+ npx get-codex-lost-world --help
43
+ ```
44
+
45
+ ### Option 2: Clone and run locally
46
+
47
+ ```bash
48
+ git clone https://github.com/0x0a0d/get-codex-lost-world.git
49
+ cd get-codex-lost-world
50
+ npm install
51
+ npm test
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Show help
57
+
58
+ ```bash
59
+ npx get-codex-lost-world --help
60
+ ```
61
+
62
+ ### Build mode (default)
63
+
64
+ ```bash
65
+ npx get-codex-lost-world
66
+ ```
67
+
68
+ ```bash
69
+ npx get-codex-lost-world --build --workdir /absolute/path/to/workdir
70
+ ```
71
+
72
+ ### Build for Windows arm64 ZIP
73
+
74
+ ```bash
75
+ npx get-codex-lost-world --build --platform windows --arch arm64 --format zip --workdir /absolute/path/to/workdir
76
+ ```
77
+
78
+ ### Cache/download mode
79
+
80
+ ```bash
81
+ npx get-codex-lost-world --cache --platform windows --arch x64 --format zip
82
+ ```
83
+
84
+ ### Sign mode
85
+
86
+ ```bash
87
+ npx get-codex-lost-world --sign /Applications/Codex.app
88
+ ```
89
+
90
+ ## Contributing
91
+
92
+ Contributions are welcome! 🙌
93
+
94
+ ```bash
95
+ git checkout -b feat/your-feature
96
+ npm test
97
+ git commit -m "feat: add your feature"
98
+ git push origin feat/your-feature
99
+ ```
100
+
101
+ Then open a Pull Request.
102
+
103
+ ## License
104
+
105
+ Licensed under the **ISC** License.
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { runMain, usage } = require('../lib/get-codex-lost-world/main');
5
+
6
+ function printTargetShortcuts() {
7
+ const message = [
8
+ '',
9
+ 'Target shortcuts:',
10
+ ' --mac-silicon Build/download for Apple Silicon Mac (default source: original Codex.dmg on macOS arm64 host)',
11
+ ' --mac-intel Build/download for Intel Mac (.dmg)',
12
+ ' --windows-x64 Build/download for Windows x64 (.zip)',
13
+ ' --windows-arm64 Build/download for Windows arm64 (.zip)',
14
+ '',
15
+ 'Example:',
16
+ ' npx get-codex-lost-world --windows-x64 --workdir /tmp/codex',
17
+ ].join('\n');
18
+
19
+ process.stdout.write(`${message}\n`);
20
+ }
21
+
22
+ function remapShortcutArgs(argv = []) {
23
+ const targetShortcuts = {
24
+ '--mac-silicon': ['--platform', 'mac', '--format', 'dmg'],
25
+ '--mac-intel': ['--platform', 'mac', '--arch', 'x64', '--format', 'dmg'],
26
+ '--windows-x64': ['--platform', 'windows', '--arch', 'x64', '--format', 'zip'],
27
+ '--windows-arm64': ['--platform', 'windows', '--arch', 'arm64', '--format', 'zip'],
28
+ };
29
+
30
+ const selectedShortcuts = argv.filter((arg) => Object.prototype.hasOwnProperty.call(targetShortcuts, arg));
31
+ if (selectedShortcuts.length > 1) {
32
+ throw new Error(`Target shortcut conflict: ${selectedShortcuts.join(', ')}`);
33
+ }
34
+
35
+ const selected = selectedShortcuts[0];
36
+ const withoutShortcuts = argv.filter((arg) => !Object.prototype.hasOwnProperty.call(targetShortcuts, arg));
37
+
38
+ if (!selected) {
39
+ return withoutShortcuts;
40
+ }
41
+
42
+ return [...withoutShortcuts, ...targetShortcuts[selected]];
43
+ }
44
+
45
+ async function main() {
46
+ const argv = process.argv.slice(2);
47
+ if (argv.includes('--target-help')) {
48
+ process.stdout.write(`${usage()}\n`);
49
+ printTargetShortcuts();
50
+ return;
51
+ }
52
+
53
+ const remapped = remapShortcutArgs(argv);
54
+ await runMain(remapped);
55
+ }
56
+
57
+ main().catch((error) => {
58
+ const message = error && error.message ? error.message : String(error);
59
+ process.stderr.write(`${message}\n\n${usage()}\n`);
60
+ process.stderr.write('Use --target-help to see target shortcuts.\n');
61
+ process.exit(1);
62
+ });
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ function shouldBuild({ incomingLastModified, cachedLastModified, force }) {
4
+ if (force === true) {
5
+ return true;
6
+ }
7
+
8
+ if (incomingLastModified === cachedLastModified) {
9
+ return false;
10
+ }
11
+
12
+ return true;
13
+ }
14
+
15
+ module.exports = {
16
+ shouldBuild,
17
+ };
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+
3
+ function parseArgs(argv = []) {
4
+ const modeFlags = [];
5
+ let signPath;
6
+ let workdir;
7
+ let platform;
8
+ let arch;
9
+ let format;
10
+ let help = false;
11
+
12
+ for (let i = 0; i < argv.length; i += 1) {
13
+ const arg = argv[i];
14
+
15
+ if (arg === '--help' || arg === '-h') {
16
+ help = true;
17
+ continue;
18
+ }
19
+
20
+ if (arg === '--cache' || arg === '-c') {
21
+ modeFlags.push('cache');
22
+ continue;
23
+ }
24
+
25
+ if (arg === '--build' || arg === '-b') {
26
+ modeFlags.push('build');
27
+ continue;
28
+ }
29
+
30
+ if (arg === '--sign' || arg === '-s') {
31
+ modeFlags.push('sign');
32
+ const candidate = argv[i + 1];
33
+ if (typeof candidate !== 'string' || candidate.trim() === '' || candidate.startsWith('-')) {
34
+ throw new Error('--sign requires a path');
35
+ }
36
+ signPath = candidate;
37
+ i += 1;
38
+ continue;
39
+ }
40
+
41
+ if (arg === '--workdir' || arg === '-w') {
42
+ const candidate = argv[i + 1];
43
+ if (typeof candidate !== 'string' || candidate.trim() === '' || candidate.startsWith('-')) {
44
+ throw new Error('--workdir requires a path');
45
+ }
46
+ workdir = candidate;
47
+ i += 1;
48
+ continue;
49
+ }
50
+
51
+ if (arg === '--platform') {
52
+ const candidate = argv[i + 1];
53
+ if (typeof candidate !== 'string' || candidate.trim() === '' || candidate.startsWith('-')) {
54
+ throw new Error('--platform requires a value');
55
+ }
56
+ platform = candidate;
57
+ i += 1;
58
+ continue;
59
+ }
60
+
61
+ if (arg === '--arch') {
62
+ const candidate = argv[i + 1];
63
+ if (typeof candidate !== 'string' || candidate.trim() === '' || candidate.startsWith('-')) {
64
+ throw new Error('--arch requires a value');
65
+ }
66
+ arch = candidate;
67
+ i += 1;
68
+ continue;
69
+ }
70
+
71
+ if (arg === '--format') {
72
+ const candidate = argv[i + 1];
73
+ if (typeof candidate !== 'string' || candidate.trim() === '' || candidate.startsWith('-')) {
74
+ throw new Error('--format requires a value');
75
+ }
76
+ format = candidate;
77
+ i += 1;
78
+ continue;
79
+ }
80
+
81
+ if (arg.startsWith('-')) {
82
+ throw new Error(`Unknown option: ${arg}`);
83
+ }
84
+ }
85
+
86
+ const uniqueModes = [...new Set(modeFlags)];
87
+ if (uniqueModes.length > 1) {
88
+ throw new Error('mode flag conflict');
89
+ }
90
+
91
+ if (help) {
92
+ return { mode: 'help' };
93
+ }
94
+
95
+ const mode = uniqueModes[0] || 'build';
96
+ const result = { mode };
97
+
98
+ if (typeof platform === 'string') {
99
+ result.platform = platform;
100
+ }
101
+
102
+ if (typeof arch === 'string') {
103
+ result.arch = arch;
104
+ }
105
+
106
+ if (typeof format === 'string') {
107
+ result.format = format;
108
+ }
109
+
110
+ if (typeof workdir === 'string') {
111
+ result.workdir = workdir;
112
+ }
113
+
114
+ if (mode === 'sign') {
115
+ result.signPath = signPath;
116
+ return result;
117
+ }
118
+
119
+ return result;
120
+ }
121
+
122
+ module.exports = {
123
+ parseArgs,
124
+ };
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ function sanitizeVersion(version) {
4
+ return String(version || '')
5
+ .trim()
6
+ .replace(/\s+/g, '-')
7
+ .replace(/[^0-9A-Za-z._-]/g, '-');
8
+ }
9
+
10
+ function makeOutputName(version) {
11
+ return `CodexIntelMac_${sanitizeVersion(version)}.dmg`;
12
+ }
13
+
14
+ function makeOutputNameForTarget({ version, platform, arch, format }) {
15
+ const safeVersion = sanitizeVersion(version);
16
+ const normalizedPlatform = String(platform || '').trim().toLowerCase();
17
+ const normalizedArch = String(arch || '').trim().toLowerCase();
18
+ const normalizedFormat = String(format || '').trim().toLowerCase();
19
+
20
+ if (normalizedPlatform === 'windows') {
21
+ return `CodexWindows_${normalizedArch || 'x64'}_${safeVersion}.${normalizedFormat || 'zip'}`;
22
+ }
23
+
24
+ return `CodexIntelMac_${safeVersion}.${normalizedFormat || 'dmg'}`;
25
+ }
26
+
27
+ module.exports = {
28
+ sanitizeVersion,
29
+ makeOutputName,
30
+ makeOutputNameForTarget,
31
+ };
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ function resolveCacheDownload(location) {
4
+ const normalized = typeof location === 'string' ? location.trim() : '';
5
+
6
+ if (!normalized) {
7
+ return {
8
+ shouldDownload: false,
9
+ location: '',
10
+ };
11
+ }
12
+
13
+ return {
14
+ shouldDownload: true,
15
+ location: normalized,
16
+ };
17
+ }
18
+
19
+ module.exports = {
20
+ resolveCacheDownload,
21
+ };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { spawnSync } = require('node:child_process');
6
+
7
+ function createLocalBuilder(overrides = {}) {
8
+ const builderEntry = overrides.builderEntry || path.resolve(__dirname, '../../scripts/build-intel-dmg.js');
9
+ const windowsBuilderEntry = overrides.windowsBuilderEntry || path.resolve(__dirname, '../../scripts/build-windows-zip.js');
10
+ const fsApi = overrides.fsApi || fs;
11
+ const spawnSyncFn = overrides.spawnSync || spawnSync;
12
+ const nodeExecPath = overrides.nodeExecPath || process.execPath;
13
+
14
+ return {
15
+ async run({ location, downloadedPath, outputName, target }) {
16
+ const normalizedLocation = typeof location === 'string' ? location.trim() : '';
17
+ const normalizedSource = typeof downloadedPath === 'string' ? downloadedPath.trim() : '';
18
+ const normalizedOutputName = typeof outputName === 'string' ? outputName.trim() : '';
19
+
20
+ if (!normalizedLocation) {
21
+ throw new Error('build output location is required');
22
+ }
23
+ if (!normalizedSource) {
24
+ throw new Error('source Codex.dmg path is required to run the builder');
25
+ }
26
+ if (!normalizedOutputName) {
27
+ throw new Error('build output filename is required');
28
+ }
29
+ const platform = String(target && target.platform ? target.platform : 'mac').trim().toLowerCase();
30
+ const selectedEntry = platform === 'windows' ? windowsBuilderEntry : builderEntry;
31
+
32
+ if (!fsApi.existsSync(selectedEntry)) {
33
+ throw new Error(`Local builder entrypoint (${path.basename(selectedEntry)}) was not found`);
34
+ }
35
+
36
+ fsApi.mkdirSync(normalizedLocation, { recursive: true });
37
+ const outputPath = path.join(normalizedLocation, normalizedOutputName);
38
+ const result = spawnSyncFn(nodeExecPath, [
39
+ selectedEntry,
40
+ '--output',
41
+ outputPath,
42
+ normalizedSource,
43
+ ], {
44
+ stdio: 'inherit',
45
+ });
46
+
47
+ if (result.error) {
48
+ throw result.error;
49
+ }
50
+
51
+ if (result.status !== 0) {
52
+ throw new Error('Local builder failed (see logs above for details)');
53
+ }
54
+
55
+ return { outputPath };
56
+ },
57
+ };
58
+ }
59
+
60
+ module.exports = {
61
+ createLocalBuilder,
62
+ };