Skip to content

Commit

Permalink
Add dynamic loader to compiled autocomplete specs (#360)
Browse files Browse the repository at this point in the history
  • Loading branch information
grant0417 authored Jan 7, 2025
1 parent 14d7cf8 commit 104377c
Show file tree
Hide file tree
Showing 19 changed files with 388 additions and 171 deletions.
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

0 comments on commit 104377c

Please sign in to comment.