Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic loader to compiled autocomplete specs #360

Merged
merged 1 commit into from
Jan 7, 2025
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
2 changes: 0 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

pnpm pre-commit
2 changes: 1 addition & 1 deletion cli/publish-spec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"homepage": "https://github.com/withfig/autocomplete-tools#readme",
"dependencies": {
"commander": "^11.1.0",
"esbuild": "^0.23.1",
"esbuild": "^0.24.2",
"node-fetch": "^3.3.2",
"prettier": "^3.3.3",
"prompts": "^2.4.2"
Expand Down
5 changes: 5 additions & 0 deletions cli/tools-cli/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
rules: {
"import/no-unresolved": "off",
},
};
85 changes: 2 additions & 83 deletions cli/tools-cli/README.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,3 @@
<p align="center">
<img width="300" src="https://github.com/withfig/fig/blob/main/static/FigBanner.png?raw=true"/>
</p>
# `@withfig/autocomplete-tools`

---

![os](https://img.shields.io/badge/os-%20macOS-light)
[![Signup](https://img.shields.io/badge/signup-private%20beta-blueviolet)](https://fig.io?ref=github_autocomplete)
[![Documentation](https://img.shields.io/badge/documentation-black)](https://fig.io/docs/)
[![Discord](https://img.shields.io/discord/837809111248535583?color=768ad4&label=discord)](https://fig.io/community)
[![Twitter](https://img.shields.io/twitter/follow/fig.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=fig)


# Fig Autocomplete Boilerplate Repo

Looking to build [Fig](https://fig.io) autocomplete for private CLI tools, scripts, or NPM packages? This npx module makes it easy to **build** [Fig autocomplete specs](https://fig.io/docs) and **share** them specs with your team.

This repo is similar to a minimal version of our public specs repo,
[withfig/autocomplete](https://github.com/withfig/autocomplete), except with an empty `src/` folder.



## Usage

### Init the .fig folder

Go to the directory that contains your CLI tool, script, or NPM package and run the following

```bash
npx @withfig/autocomplete-tools init
```
This will create initialise a `.fig/` folder in your current working directory like the following
```bash
cli/
├── .fig/
│   └── autocomplete/
│   ├── src/ # where you edit your completion specs
│   ├── build/ # where your specs compile to
│   ├── .eslintrc.js
│   ├── README.md
│   ├── package-lock.json
│   ├── package.json
│   └── tsconfig.json
├── node_mod/
└── my_cli_tool.sh
```

### Create, test, and compile specs

`cd` into the `.fig/autocomplete/` folder and run the remaining commands as package.json scripts

```bash
# Make a new empty completion spec object in src/
npm run create-spec

# Start dev mode to see live updates to your spec in your terminal as you edit.
npm run dev

# Compile your specs from the src/ folder to build/
npm run build
```

### Push Specs to Fig's Cloud
Coming soon

## Documentation

- [Building your first autocomplete spec](https://fig.io/docs/)
- [Personal shortcut autocomplete](https://fig.io/docs/tutorials/visual-shortcuts)
- [Autocomplete for teams / internal CLI tools](https://fig.io/docs/tutorials/building-internal-clis)
- [Autocomplete for local scripts](https://fig.io/docs/tutorials/autocomplete-for-internal-scripts)


## 😊 Need Help?

Email [[email protected]](mailto:[email protected])

<p align="center">
Join our community
<br/>
<a href="https://fig.io/community">
<img src="http://fig.io/icons/discord-logo-square.png" width="80px" height="80px" />
</a>
</p>
The `@withfig/autocomplete-tools` is a CLI used to build and manage the withfig/autocomplete repo.
11 changes: 6 additions & 5 deletions cli/tools-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
{
"name": "@withfig/autocomplete-tools",
"version": "2.10.0",
"version": "2.11.0",
"description": "Command line tools for working with fig autocomplete specs",
"author": "The Fig Team",
"scripts": {
"build": "rm -rf build/ && pnpm run build:bin && pnpm run build:lib",
"build:bin": "esbuild src/bin.ts --bundle --platform=node --packages=external --outdir=build --minify",
"build:bin": "esbuild src/bin.ts --bundle --platform=node --packages=external --outdir=build --minify --format=esm",
"build:lib": "tsc",
"test": "tsx test/index.ts",
"test:overwrite": "OVERWRITE=true pnpm test",
"prepack": "pnpm build",
"generate-spec": "tsx generate-spec.ts generate-fig-spec"
},
"license": "MIT",
"type": "module",
"bin": "./build/bin.js",
"main": "./build/index.js",
"types": "./build/index.d.ts",
Expand All @@ -24,11 +25,11 @@
"@fig/autocomplete-helpers": "workspace:^",
"@fig/autocomplete-merge": "workspace:^",
"@types/semver": "^7.5.8",
"chalk": "^4.1.2",
"chalk": "^5.4.1",
"chokidar": "^4.0.1",
"commander": "^11.1.0",
"commander": "^13.0.0",
"create-completion-spec": "workspace:^",
"esbuild": "^0.23.1",
"esbuild": "^0.24.2",
"fast-glob": "^3.3.2",
"module-from-string": "^3.3.1",
"prettier": "^3.3.3",
Expand Down
75 changes: 49 additions & 26 deletions cli/tools-cli/src/scripts/compile.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import fs from "node:fs/promises";
import fsSync from "node:fs";
import path from "node:path";
import { build } from "esbuild";
import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill";
import chokidar from "chokidar";
import { Command } from "commander";
import glob from "fast-glob";
import fs from "node:fs/promises";
import path from "node:path";
import SpecLogger, { Level } from "./log";
import { setSetting } from "./settings";

Expand Down Expand Up @@ -33,33 +34,55 @@ async function generateIndex(outdir: string, files: string[]) {
.concat(diffVersionedSpecNames);
specNames.sort();

await fs.mkdir(outdir, { recursive: true });
const modules = files
.filter((p) => fsSync.statSync(p).isFile())
.map(path.parse)
.map((p) => `${p.dir}/${p.name}`.replace(/^src\//, ""));

Promise.all([
// index.js
await fs.writeFile(
path.join(outdir, "index.js"),
`var e=${JSON.stringify(specNames)},diffVersionedCompletions=${JSON.stringify(
diffVersionedSpecNames
)};export{e as default,diffVersionedCompletions};`
),
// index.json
fs.writeFile(
path.join(outdir, "index.json"),
JSON.stringify({
completions: specNames,
diffVersionedCompletions: diffVersionedSpecNames,
})
),
// index.d.ts
fs.writeFile(
path.join(outdir, "index.d.ts"),
`declare const completions: string[]
await fs.mkdir(outdir, { recursive: true });
await fs.mkdir(path.join(outdir, "dynamic"), { recursive: true });

// index.js
await fs.writeFile(
path.join(outdir, "index.js"),
`var e=${JSON.stringify(specNames)},diffVersionedCompletions=${JSON.stringify(
diffVersionedSpecNames
)};export{e as default,diffVersionedCompletions};`
);
// index.json
await fs.writeFile(
path.join(outdir, "index.json"),
JSON.stringify({
completions: specNames,
diffVersionedCompletions: diffVersionedSpecNames,
})
);
// index.d.ts
await fs.writeFile(
path.join(outdir, "index.d.ts"),
`declare const completions: string[]
declare const diffVersionedCompletions: string[]
export { completions as default, diffVersionedCompletions }
`
),
]);
`
);
// dynamic/index.js
await fs.writeFile(
path.join(outdir, "dynamic/index.js"),
`var e={${modules
.map((mod) => `${JSON.stringify(mod)}:()=>import(${JSON.stringify(`../${mod}.js`)})`)
.join(",")}};export{e as default};`
);
// dynamic/index.d.ts
await fs.writeFile(
path.join(outdir, "dynamic/index.d.ts"),
`declare const completions: {
[key: string]: () => Promise<{
default: any;
}>
}
export { completions as default }
`
);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions cli/tools-cli/src/scripts/create-spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from "node:path";
import readline from "node:readline";
import { createCompletionSpec } from "create-completion-spec";
import { Command } from "commander";
import readline from "readline";
import path from "path";
import chalk from "chalk";

const program = new Command("create-spec")
Expand Down
6 changes: 3 additions & 3 deletions cli/tools-cli/src/scripts/dev.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os from "os";
import fs from "fs";
import path from "path";
import os from "node:os";
import fs from "node:fs";
import path from "node:path";
import chalk from "chalk";
import { Command } from "commander";
import { runCompiler } from "./compile";
Expand Down
2 changes: 1 addition & 1 deletion cli/tools-cli/src/scripts/merge.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from "fs";
import fs from "node:fs";
import { Command, Option } from "commander";
import { merge, presets, PresetName } from "@fig/autocomplete-merge";

Expand Down
4 changes: 2 additions & 2 deletions cli/tools-cli/src/scripts/version.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import fs from "node:fs";
import path from "node:path";
import { Command } from "commander";
import semver from "semver";
import { applySpecDiff, diffSpecs } from "@fig/autocomplete-helpers";
import { importFromStringSync } from "module-from-string";
import prettier from "prettier";
import fs from "fs";
import ts from "typescript";
import { build } from "esbuild";
import path from "path";

export const copyDirectorySync = (oldPath: string, newPath: string) => {
if (!fs.existsSync(newPath)) {
Expand Down
14 changes: 8 additions & 6 deletions cli/tools-cli/test/versioning/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import fs from "fs";
import child from "child_process";
import path from "path";
import fs from "node:fs";
import child from "node:child_process";
import path from "node:path";
import url from "node:url";
import { copyDirectorySync } from "../../src/scripts/version";

const cliPath = path.join(__dirname, "..", "..", "src", "bin.ts");
const fixturesPath = path.join(__dirname, "fixtures");
const dirname = path.dirname(url.fileURLToPath(import.meta.url));
const cliPath = path.join(dirname, "..", "..", "src", "bin.ts");
const fixturesPath = path.join(dirname, "fixtures");
const dirs = fs
.readdirSync(fixturesPath, { withFileTypes: true })
.filter((file) => file.isDirectory() && file.name !== ".DS_Store");
Expand Down Expand Up @@ -58,7 +60,7 @@ export function runFixtures() {
}

fs.rmSync(updatedSpecPath, { recursive: true, force: true });
const cmd = `node -r tsx/cjs ${cliPath} version add-diff old-spec ${newSpecPath} ${newVersion} --cwd ${fixtureDirPath} --new-path ${updatedSpecPath}`;
const cmd = `tsx ${cliPath} version add-diff old-spec ${newSpecPath} ${newVersion} --cwd ${fixtureDirPath} --new-path ${updatedSpecPath}`;

try {
child.execSync(cmd);
Expand Down
5 changes: 5 additions & 0 deletions helpers/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
rules: {
"import/no-unresolved": "off",
},
};
1 change: 0 additions & 1 deletion helpers/index.ts

This file was deleted.

19 changes: 6 additions & 13 deletions helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
{
"name": "@fig/autocomplete-helpers",
"version": "1.0.7",
"version": "2.0.0",
"description": "Helper functions for fig completion specs",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"typings": "./dist/cjs/index.d.ts",
"exports": {
"require": "./dist/cjs/index.js",
"import": "./dist/esm/index.js"
},
"type": "module",
"exports": "./dist/index.js",
"files": [
"dist/"
],
"scripts": {
"clean": "rm -rf dist/",
"build": "pnpm clean && pnpm build:cjs && pnpm build:esm",
"build:cjs": "tsc --declaration --outDir dist/cjs",
"build:esm": "tsc --declaration --module esnext --outDir dist/esm",
"build": "pnpm clean && tsc",
"prepack": "pnpm build",
"test": "tsx test/index.ts && vitest --run"
},
"author": "Fig Team",
"dependencies": {
"semver": "^7.6.3",
"typescript": "^5.5.4"
"semver": "^7.6.3"
},
"devDependencies": {
"@tsconfig/recommended": "^1.0.7",
Expand All @@ -32,6 +24,7 @@
"@withfig/autocomplete-types": "workspace:^",
"prettier": "^3.3.3",
"tsx": "^4.19.2",
"typescript": "^5.5.4",
"vitest": "^2.1.4"
},
"publishConfig": {
Expand Down
1 change: 1 addition & 0 deletions helpers/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./versions.js";
3 changes: 1 addition & 2 deletions helpers/test/fixtures/fig-cli/spec/1.0.0.js
Original file line number Diff line number Diff line change
Expand Up @@ -1911,5 +1911,4 @@ versions["1.3.1"] = {
],
};

exports.versions = versions;
exports.completion = completion;
export { versions, completion };
8 changes: 5 additions & 3 deletions helpers/test/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import fs from "fs";
import path from "path";
import fs from "node:fs";
import path from "node:path";
import url from "node:url";
import prettier from "prettier";
import { getVersionFromVersionedSpec } from "../src/versions";

const fixturesPath = path.join(__dirname, "fixtures");
const dirname = path.dirname(url.fileURLToPath(import.meta.url));
const fixturesPath = path.join(dirname, "fixtures");
const dirs = fs
.readdirSync(fixturesPath, { withFileTypes: true })
.filter((file) => file.isDirectory() && file.name !== ".DS_Store");
Expand Down
Loading
Loading