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
10 changes: 10 additions & 0 deletions .changeset/warm-dodos-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@calycode/types": patch
"@calycode/utils": patch
"@calycode/core": patch
"@calycode/cli": patch
---

refactor: minor cleanup, removal of the linting command..
fix: make backup to be stream, to allow bigger workspaces
refactor: cleanup of fs / path imports in the cli
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ I have been astonished by the shadcn/ui CLI and the core principles of code dist
- [x] **Scaffolding a registry** of reusable Xano components
- [x] Exporting all available `xanoscript` from your instance via metadata API _*(important note: not all pieces of logic can be exported via metadata API, this especially is fragile on older and bigger instances)_.
- [x] Adding components to Xano from a registry (only functions, tables, queries for now)
- [ ] Automated test runner with assertion configuration
- [ ] Linting with custom rulesets
- [x] Automated test runner with assertion configuration

---

Expand Down
2 changes: 1 addition & 1 deletion eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default [
// TS/TSX files config
{
files: ['**/*.ts'],
ignores: ['node_modules/**', 'dist/**', 'output/**'],
ignores: ['node_modules/**', 'dist/**', 'output/**', 'scripts/**'],
languageOptions: {
parser: '@typescript-eslint/parser',
parserOptions: {
Expand Down
9 changes: 2 additions & 7 deletions packages/cli/esbuild.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@ import { cp, writeFile } from 'fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { build } from 'esbuild';
import { intro, outro, log } from '@clack/prompts';

const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = resolve(__dirname);
const distDir = resolve(__dirname, 'dist');

(async () => {
try {
intro('Bundling Caly with esbuild');

// Copy github actions
await cp(resolve(rootDir, 'src/actions'), resolve(distDir, 'actions'), {
recursive: true,
});
log.step('Copied and minified assets to dist.');

// Bundle the application with esbuild
const result = await build({
Expand All @@ -35,16 +31,15 @@ const distDir = resolve(__dirname, 'dist');
sourcemap: false,
metafile: true,
});
log.step('esbuild bundling complete.');

// Write the metafile for analysis
await writeFile(resolve(distDir, 'meta.json'), JSON.stringify(result.metafile, null, 2));

outro(
console.log(
'Build complete. You can analyze the bundle with https://esbuild.github.io/analyze/ by uploading dist/meta.json'
);
} catch (error) {
log.error(`Build failed: ${JSON.stringify(error, null, 2)}`);
console.error(`Build failed: ${JSON.stringify(error, null, 2)}`);
process.exit(1);
}
})();
14 changes: 7 additions & 7 deletions packages/cli/src/commands/analyze.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { mkdir } from 'fs/promises';
import { writeFileSync, existsSync, mkdirSync } from 'fs';
import { dirname, join } from 'path';
import { mkdir, writeFile, access } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { log, outro, intro, spinner } from '@clack/prompts';
import { metaApiGet, replacePlaceholders, sanitizeFileName } from '@calycode/utils';
import {
Expand All @@ -12,7 +11,6 @@ import {
import { resolveConfigs } from '../utils/commands/context-resolution';
import { findProjectRoot } from '../utils/commands/project-root-finder';

// [ ] CORE, but needs fs access.
async function fetchFunctionsInXanoScript(instance, workspace, branch, printOutput = false, core) {
intro('Starting to analyze functions.');
let branchFunctions = {};
Expand Down Expand Up @@ -81,12 +79,14 @@ async function fetchFunctionsInXanoScript(instance, workspace, branch, printOutp

// Ensure the parent directory exists
const parentDir = dirname(filePath);
if (!existsSync(parentDir)) {
mkdirSync(parentDir, { recursive: true });
try {
await access(parentDir);
} catch {
await mkdir(parentDir, { recursive: true });
}

// Write the file
writeFileSync(filePath, branchFunctions[item].script);
await writeFile(filePath, branchFunctions[item].script);
}
s.stop(`Xano Script files are ready -> ${outputDir}`);
} catch (err) {
Expand Down
8 changes: 4 additions & 4 deletions packages/cli/src/commands/backups.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path, { join } from 'path';
import { readdirSync } from 'fs';
import { basename, join } from 'node:path';
import { readdir } from 'node:fs/promises';
import { openAsBlob } from 'node:fs';
import { select, confirm, outro } from '@clack/prompts';
import { replacePlaceholders } from '@calycode/utils';
Expand Down Expand Up @@ -48,7 +48,7 @@ async function restorationWizard({ instance, workspace, sourceBackup, forceConfi

let availableBackups;
try {
availableBackups = readdirSync(backupsDir);
availableBackups = await readdir(backupsDir);
} catch {
outro(`No backups directory found for branch "${branchConfig.label}".`);
process.exit(1);
Expand Down Expand Up @@ -82,7 +82,7 @@ async function restorationWizard({ instance, workspace, sourceBackup, forceConfi
}

const formData = new FormData();
formData.append('file', await openAsBlob(backupFilePath), path.basename(backupFilePath));
formData.append('file', await openAsBlob(backupFilePath), basename(backupFilePath));
formData.append('password', '');

// Pass on the formdata to the core implementation
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/generate-code.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { log, outro, intro, spinner } from '@clack/prompts';
import { metaApiGet, normalizeApiGroupName, replacePlaceholders, dirname } from '@calycode/utils';
import { metaApiGet, normalizeApiGroupName, replacePlaceholders } from '@calycode/utils';
import {
addApiGroupOptions,
addFullContextOptions,
Expand Down
32 changes: 20 additions & 12 deletions packages/cli/src/commands/generate-repo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { existsSync, readdirSync, lstatSync, rmdirSync, unlinkSync } from 'fs';
import { mkdir, access, readdir, lstat, rm, unlink } from 'node:fs/promises';
import { log, intro, outro } from '@clack/prompts';
import { load } from 'js-yaml';
import { mkdir } from 'fs/promises';
import { joinPath, dirname, replacePlaceholders, fetchAndExtractYaml } from '@calycode/utils';
import {
addFullContextOptions,
Expand All @@ -14,21 +13,30 @@ import { resolveConfigs } from '../utils/commands/context-resolution';
import { findProjectRoot } from '../utils/commands/project-root-finder';

/**
* Clears the contents of a directory.
* Recursively removes all files and subdirectories in a directory.
* @param {string} directory - The directory to clear.
*/
function clearDirectory(directory) {
if (existsSync(directory)) {
readdirSync(directory).forEach((file) => {
async function clearDirectory(directory: string): Promise<void> {
try {
await access(directory);
} catch {
// Directory does not exist; nothing to clear
return;
}

const files = await readdir(directory);
await Promise.all(
files.map(async (file) => {
const curPath = joinPath(directory, file);
if (lstatSync(curPath).isDirectory()) {
clearDirectory(curPath);
rmdirSync(curPath);
const stat = await lstat(curPath);
if (stat.isDirectory()) {
await clearDirectory(curPath);
await rm(curPath, { recursive: true, force: true }); // removes the (now-empty) dir
} else {
unlinkSync(curPath);
await unlink(curPath);
}
});
}
})
);
}

async function generateRepo({
Expand Down
33 changes: 21 additions & 12 deletions packages/cli/src/commands/generate-xanoscript-repo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync, readdirSync, lstatSync, rmdirSync, unlinkSync, mkdirSync } from 'fs';
import { access, readdir, lstat, rm, unlink, mkdir } from 'node:fs/promises';
import { joinPath, dirname } from '@calycode/utils';
import { attachCliEventHandlers } from '../utils/event-listener';
import { replacePlaceholders } from '@calycode/utils';
Expand All @@ -8,21 +8,30 @@ import { resolveConfigs } from '../utils/commands/context-resolution';
import { findProjectRoot } from '../utils/commands/project-root-finder';

/**
* Clears the contents of a directory.
* Recursively removes all files and subdirectories in a directory.
* @param {string} directory - The directory to clear.
*/
function clearDirectory(directory) {
if (existsSync(directory)) {
readdirSync(directory).forEach((file) => {
async function clearDirectory(directory: string): Promise<void> {
try {
await access(directory);
} catch {
// Directory does not exist; nothing to clear
return;
}

const files = await readdir(directory);
await Promise.all(
files.map(async (file) => {
const curPath = joinPath(directory, file);
if (lstatSync(curPath).isDirectory()) {
clearDirectory(curPath);
rmdirSync(curPath);
const stat = await lstat(curPath);
if (stat.isDirectory()) {
await clearDirectory(curPath);
await rm(curPath, { recursive: true, force: true });
} else {
unlinkSync(curPath);
await unlink(curPath);
}
});
}
})
);
}

async function generateXanoscriptRepo({ instance, workspace, branch, core, printOutput = false }) {
Expand All @@ -46,7 +55,7 @@ async function generateXanoscriptRepo({ instance, workspace, branch, core, print
});

clearDirectory(outputDir);
mkdirSync(outputDir, { recursive: true });
await mkdir(outputDir, { recursive: true });

const plannedWrites: { path: string; content: string }[] = await core.buildXanoscriptRepo({
instance: context.instance,
Expand Down
70 changes: 0 additions & 70 deletions packages/cli/src/commands/run-lint.ts

This file was deleted.

8 changes: 4 additions & 4 deletions packages/cli/src/commands/run-tests.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from 'fs/promises';
import { readFile, writeFile, mkdir } from 'node:fs/promises';
import { intro, log, spinner } from '@clack/prompts';
import { normalizeApiGroupName, replacePlaceholders } from '@calycode/utils';
import {
Expand Down Expand Up @@ -52,7 +52,7 @@ async function runTest({

// Take the core implementation for test running:
// for now testconfig has to exist on the machine prior to running the tests.
const testConfigFileContent = await fs.readFile(testConfigPath, { encoding: 'utf-8' });
const testConfigFileContent = await readFile(testConfigPath, { encoding: 'utf-8' });
const testConfig = JSON.parse(testConfigFileContent);
const s = spinner();
s.start('Running tests based on the provided spec');
Expand Down Expand Up @@ -81,8 +81,8 @@ async function runTest({
api_group_normalized_name: normalizeApiGroupName(outcome.group.name),
});

await fs.mkdir(apiGroupTestPath, { recursive: true });
await fs.writeFile(
await mkdir(apiGroupTestPath, { recursive: true });
await writeFile(
`${apiGroupTestPath}/${testFileName}`,
JSON.stringify(outcome.results, null, 2)
);
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/serve.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { spawn } from 'child_process';
import { spawn } from 'node:child_process';
import { normalizeApiGroupName, replacePlaceholders } from '@calycode/utils';
import { addApiGroupOptions, addFullContextOptions, chooseApiGroupOrAll } from '../utils/index';
import { resolveConfigs } from '../utils/commands/context-resolution';
Expand Down
Loading