Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ node_modules
oclif.manifest.json
.env
.codify-files
.npm-readme-backup.md
2 changes: 1 addition & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
min-release-age=10080
min-release-age=7
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
> ⚠️ **This package has been migrated and re-purposed.** The original package by [Andrew Stone](https://www.npmjs.com/~andrewjstone)
> for transforming integers to base36 strings. To continue to use that functionality, please pin to version 0.3.0 or below.

# Codify - Your Development Environment as Code

**Stop manually setting up your development environment. Define it once, replicate it everywhere.**
Expand Down
2 changes: 2 additions & 0 deletions README.npm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
> ⚠️ **This package has been migrated and re-purposed.** The original package by [Andrew Stone](https://www.npmjs.com/~andrewjstone)
> for transforming integers to base36 strings. To continue to use that functionality, please pin to version 0.3.0 or below.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@
"start:dev": "./bin/dev.js",
"start:vm": "npm run build && npm run pack:macos && npm run start:vm",
"deploy": "npm run pkg && npm run notarize && npm run upload",
"prepublishOnly": "npm run build"
"build:npm": "tsx ./scripts/build-npm.ts",
"restore-npm": "tsx ./scripts/restore-npm.ts",
"prepublishOnly": "npm run build && npm run build:npm",
"postpublish": "npm run restore-npm"
},
"version": "1.2.2",
"bugs": "https://github.com/codifycli/codify/issues",
Expand Down
62 changes: 62 additions & 0 deletions scripts/build-npm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// npm-publish prep. Runs from `prepublishOnly` (after `npm run build`).
//
// Two npm-specific concerns the plain `tsc` build doesn't handle:
//
// 1. dist/patch-ink.mjs — the postinstall hook runs `node dist/patch-ink.mjs`
// to patch node_modules/ink at the user's install time (needed for the raw-PTY
// handoff, e.g. `gh auth login` — see scripts/patch-ink.ts). `tsc -b` only
// compiles src/**/*, so this file is otherwise absent from the npm tarball and
// the postinstall guard silently skips it. Compile it here (same command as
// scripts/pkg.ts uses for the binary build).
//
// 2. README.md — npm should show a "migrated and re-purposed" blurb that the
// git-tracked README must NOT carry. README.npm.md holds ONLY the blurb; we
// back up the real README and prepend the blurb to it (so the body is never
// duplicated). `npm run restore-npm` (via postpublish, and defensively on
// failure) restores it from the backup.
//
// The backup file (README.md.orig) is the single source of truth for restoration,
// so a failed publish never leaves README.md dirty.

import chalk from 'chalk'
import { execSync } from 'node:child_process'
import { existsSync } from 'node:fs'
import fs from 'node:fs/promises'

const README = 'README.md'
const README_BLURB = 'README.npm.md'
// The transient backup is intentionally NOT named README* and is a dotfile — npm
// force-includes any README* file into the tarball regardless of the `files`
// allowlist, and this backup is just build scratch that shouldn't ship.
const README_BACKUP = '.npm-readme-backup.md'

// ── 1. Compile patch-ink.ts → dist/patch-ink.mjs ─────────────────────────────
console.log(chalk.magenta('Compiling patch-ink.ts to dist/patch-ink.mjs'))
execSync(
'tsc --module nodenext --moduleResolution nodenext --target es2022 --outDir dist scripts/patch-ink.ts',
{ shell: 'zsh' },
)
await fs.rename('dist/patch-ink.js', 'dist/patch-ink.mjs')

// ── 2. Prepend the npm blurb to README.md ────────────────────────────────────
// README.npm.md holds ONLY the blurb; we prepend it to the real README so the
// body never has to be duplicated/kept in sync. `npm run restore-npm` puts the
// original README.md back from the backup.
if (!existsSync(README_BLURB)) {
console.error(chalk.red(`ERROR: ${README_BLURB} not found. Cannot build npm README.`))
process.exit(1)
}

// If a stale backup exists (previous publish aborted before restore), the real
// README was already saved there — use it as the base so we don't prepend twice.
if (!existsSync(README_BACKUP)) {
console.log(chalk.magenta(`Backing up ${README} → ${README_BACKUP}`))
await fs.copyFile(README, README_BACKUP)
} else {
console.log(chalk.yellow(`${README_BACKUP} already exists (stale?); using it as the base`))
}

console.log(chalk.magenta(`Prepending ${README_BLURB} to ${README}`))
const blurb = await fs.readFile(README_BLURB, 'utf8')
const body = await fs.readFile(README_BACKUP, 'utf8')
await fs.writeFile(README, `${blurb.trimEnd()}\n\n${body}`, 'utf8')
27 changes: 26 additions & 1 deletion scripts/patch-ink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,35 @@
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createRequire } from 'node:module';
import { existsSync } from 'node:fs';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const INK_DIR = path.join(__dirname, '../node_modules/ink/build');

// Locate ink's install dir via Node module resolution rather than a fixed
// relative path. Under an npm install, ink is hoisted to the top-level
// node_modules (not nested under codify), so `../node_modules/ink` misses it and
// the patch silently skips. Resolve ink's entry point (ink/package.json can't be
// resolved directly — ink's "exports" map doesn't expose it) and walk up to the
// package root, which finds ink wherever npm/pnpm placed it (hoisted, nested, or
// symlinked). Falls back to the old relative path (used by the self-contained
// binary build) if resolution somehow fails.
function resolveInkDir(): string {
try {
const require = createRequire(import.meta.url);
let dir = path.dirname(require.resolve('ink')); // .../ink/build/index.js → .../ink/build
while (dir !== path.dirname(dir)) {
if (existsSync(path.join(dir, 'package.json'))) return path.join(dir, 'build');
dir = path.dirname(dir);
}
} catch {
// fall through to the relative-path default below
}

return path.join(__dirname, '../node_modules/ink/build');
}

const INK_DIR = resolveInkDir();
const APP_JS = path.join(INK_DIR, 'components/App.js');
const INK_JS = path.join(INK_DIR, 'ink.js');
const RENDER_JS = path.join(INK_DIR, 'render.js');
Expand Down
21 changes: 21 additions & 0 deletions scripts/restore-npm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Restores the git-tracked README.md after an npm publish.
//
// scripts/build-npm.ts swaps in README.npm.md and saves the real README to
// README.md.orig. This restores it from that backup and removes the backup.
// Runs via `postpublish` (success) and can be run manually if a publish aborts.
// Idempotent: a no-op if there's no backup to restore.

import chalk from 'chalk'
import { existsSync } from 'node:fs'
import fs from 'node:fs/promises'

const README = 'README.md'
const README_BACKUP = '.npm-readme-backup.md'

if (existsSync(README_BACKUP)) {
console.log(chalk.magenta(`Restoring ${README} from ${README_BACKUP}`))
await fs.copyFile(README_BACKUP, README)
await fs.rm(README_BACKUP)
} else {
console.log(chalk.gray(`No ${README_BACKUP} to restore; nothing to do.`))
}
5 changes: 3 additions & 2 deletions src/api/dashboard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ export const DashboardApiClient = {
throw new Error('Not logged in');
}

// The api worker owns the Yjs decode and returns { id, contents }.
const res = await fetch(
`${config.dashboardUrl}/api/v1/documents/${id}`,
`${config.apiUrl}/v1/documents/${id}/contents`,
{
method: 'GET',
headers: { 'Content-Type': 'application/json', 'authorization': `Bearer ${login.accessToken}` }
Expand All @@ -24,7 +25,7 @@ export const DashboardApiClient = {
}

const json = await res.json();
return json.defaultDocumentId;
return json as CloudDocument;
},

async getDefaultDocumentId(): Promise<null | string> {
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const config = {
],

dashboardUrl: 'https://dashboard.codifycli.com',
apiUrl: 'https://api.codifycli.com',
supabaseUrl: 'https://kdctbvqvqjfquplxhqrm.supabase.co',

isBeta: VERSION.includes('beta'),
Expand Down
Loading