Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
4e98c39
first commit
pyramation Feb 28, 2018
2f3df76
remove bin
pyramation Feb 28, 2018
0133aa4
update tests, version bump
pyramation Feb 28, 2018
fa6a91c
readme
pyramation Feb 28, 2018
78edce1
readme
pyramation Feb 28, 2018
1670b8c
add npm install
pyramation Feb 28, 2018
dab03eb
update package
pyramation Jul 31, 2018
0e37ead
updated for filter function
pyramation Sep 24, 2018
b9ede69
Update readme.md
pyramation Mar 29, 2019
06bc4ce
Update readme.md
pyramation Mar 29, 2019
275efd8
first commit 📝
pyramation Apr 21, 2024
988db99
chore(release): publish
pyramation Apr 21, 2024
93ee9ca
checkbox
pyramation Apr 21, 2024
ff2a41e
key codes
pyramation Apr 21, 2024
6f2fe4c
autocomplete
pyramation Apr 21, 2024
e8fe766
scrolling
pyramation Apr 21, 2024
ddc64b4
colorize
pyramation Apr 21, 2024
fd18ab9
checkbox
pyramation Apr 21, 2024
8b50ef9
options
pyramation Apr 21, 2024
c85c831
opts
pyramation Apr 21, 2024
083084f
test with mocks
pyramation Apr 22, 2024
d20249f
test more events
pyramation Apr 22, 2024
b10ae84
autocomplete tests
pyramation Apr 22, 2024
05518ab
pkg
pyramation Apr 22, 2024
4170e05
pkg
pyramation Apr 22, 2024
27935b6
strip ansi for CI
pyramation Apr 22, 2024
022621c
inquirerer
pyramation Apr 22, 2024
4a28bd1
chore(release): publish
pyramation Apr 22, 2024
f8dab7d
type
pyramation Apr 22, 2024
e0e0688
pkg
pyramation Apr 22, 2024
a8472a9
chore(release): publish
pyramation Apr 22, 2024
e6fe13f
commander
pyramation Apr 22, 2024
c439f88
chore(release): publish
pyramation Apr 22, 2024
17439b7
commander and defaults
pyramation Apr 22, 2024
26c6d34
chore(release): publish
pyramation Apr 22, 2024
255a380
useDefaults
pyramation Apr 22, 2024
49eaa8d
chore(release): publish
pyramation Apr 22, 2024
4187ac0
useDefault
pyramation Apr 22, 2024
085d11b
chore(release): publish
pyramation Apr 22, 2024
19c0c92
defaults
pyramation Apr 22, 2024
622bb3b
index
pyramation Apr 22, 2024
3b4b7a1
chore(release): publish
pyramation Apr 22, 2024
bff3c4d
prompts and OptionValue[]
pyramation Apr 22, 2024
6c687ab
chore(release): publish
pyramation Apr 22, 2024
0a46466
prompt
pyramation Apr 22, 2024
b95bf2e
chore(release): publish
pyramation Apr 22, 2024
b405197
prompt
pyramation Apr 22, 2024
64d3b21
reorder
pyramation Apr 22, 2024
7acf30e
chore(release): publish
pyramation Apr 22, 2024
b1e14eb
fuzzy
pyramation Apr 22, 2024
b99717c
chore(release): publish
pyramation Apr 22, 2024
908300d
sanitize options
pyramation Apr 22, 2024
181e8fa
chore(release): publish
pyramation Apr 22, 2024
5178402
prompt
pyramation Apr 22, 2024
1f5c988
validations
pyramation Apr 22, 2024
9822897
usage
pyramation Apr 22, 2024
9393d09
chore(release): publish
pyramation Apr 22, 2024
cb1129b
defaults
pyramation Apr 22, 2024
df754ef
chore(release): publish
pyramation Apr 22, 2024
2e1881c
revert
pyramation Apr 22, 2024
fd80e23
chore(release): publish
pyramation Apr 22, 2024
e724a9a
cli
pyramation Apr 22, 2024
1c3d999
chore(release): publish
pyramation Apr 22, 2024
03f9d5f
noTty false
pyramation Apr 22, 2024
b782a9a
chore(release): publish
pyramation Apr 22, 2024
c9f278d
fixed fuzzy
pyramation Apr 22, 2024
6242063
chore(release): publish
pyramation Apr 22, 2024
56fa6a1
mutateArgs 🙏🏻
pyramation Apr 22, 2024
3944618
errors for nonsensical errors
pyramation Apr 22, 2024
7c0bfaa
chore(release): publish
pyramation Apr 22, 2024
a0eeecd
mutateArgs
pyramation Apr 22, 2024
25c70c8
chore(release): publish
pyramation Apr 22, 2024
451c13a
provided args used, not just defaults
pyramation Apr 24, 2024
273e730
chore(release): publish
pyramation Apr 24, 2024
8b841ea
handle overrides
pyramation Apr 24, 2024
b664b9a
chore(release): publish
pyramation Apr 24, 2024
8db8334
tty
pyramation Apr 30, 2024
9cda01f
chore(release): publish
pyramation Apr 30, 2024
4ebf045
add number
pyramation May 9, 2025
fb3f169
lerna
pyramation May 9, 2025
fd38ea8
lerna
pyramation May 9, 2025
8cd37ae
chore(release): publish
pyramation May 9, 2025
21b4c82
defaults for text/number
pyramation May 12, 2025
f4985e5
Defaults for checkbox
pyramation May 13, 2025
0161537
proper option values
pyramation May 13, 2025
aa6ac28
chore(release): publish
pyramation May 13, 2025
f6f0f50
handlers
pyramation May 13, 2025
b20090e
chore(release): publish
pyramation May 13, 2025
a1d5b4c
overrides coersion
pyramation May 13, 2025
09049ba
prompts
pyramation May 13, 2025
6aacc5c
comments
pyramation May 13, 2025
31272da
snap
pyramation May 13, 2025
fc307e6
test case
pyramation May 13, 2025
f98034d
chore(release): publish
pyramation May 13, 2025
1495040
keypress can be null
pyramation May 14, 2025
9f50b55
chore(release): publish
pyramation May 14, 2025
236da46
test prompt for overrides
pyramation May 14, 2025
fe5ce05
chore(release): publish
pyramation May 14, 2025
7eb4709
AllowCustomOptions
pyramation May 14, 2025
5302e9c
chore(release): publish
pyramation May 14, 2025
7169149
allowCustomOptions on list/autocomplete
pyramation May 14, 2025
e3b1d18
chore(release): publish
pyramation May 14, 2025
641ed48
Import inquirerer history into origin/
pyramation May 22, 2025
f502adc
saved
pyramation May 22, 2025
646165d
Merge pull request #1 from pyramation/feat/merge-history
pyramation May 22, 2025
2d42574
readme
pyramation May 22, 2025
7287f9c
chore(release): publish
pyramation May 22, 2025
9c77e90
when()
pyramation May 25, 2025
4758990
chore(release): publish
pyramation May 25, 2025
70221ca
lock
pyramation Nov 16, 2025
192eb9e
scaffold
pyramation Nov 16, 2025
bb0c24a
deps
pyramation Nov 16, 2025
228dce1
cga
pyramation Nov 16, 2025
695e1bf
ci
pyramation Nov 16, 2025
5ec77e0
Merge pull request #3 from pyramation/create-gen-app
pyramation Nov 16, 2025
e1b5c30
chore(release): publish
pyramation Nov 16, 2025
ae28783
Import inquirerer repository into inquirerer/
pyramation Nov 23, 2025
bc03c86
move inquirerer
pyramation Nov 23, 2025
c70f9e5
adding inquirerer
pyramation Nov 23, 2025
e7507e6
feat: Add appstash package for simple application directory resolution
pyramation Nov 23, 2025
053180b
ci
pyramation Nov 23, 2025
c4d9774
pkg
pyramation Nov 23, 2025
4732cd9
fix
pyramation Nov 23, 2025
1c3e8b0
lock
pyramation Nov 23, 2025
2195720
merged
pyramation Nov 23, 2025
d48c46f
cleaner tests
pyramation Nov 23, 2025
6a58601
swap out chalk — bye bye ESM only!
pyramation Nov 23, 2025
ae66ba9
updates
pyramation Nov 23, 2025
cecc6c5
strip-ansi
pyramation Nov 23, 2025
20e89df
keep it simple
pyramation Nov 23, 2025
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
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,21 @@ jobs:
fail-fast: false
matrix:
package:
- komoji
- appstash
- fetch-api-client
- find-pkg
- http-errors
- jsonld-tools
- komoji
- makage
- nested-obj
- node-api-client
- schema-sdk
- schema-typescript
- strfy-js
- yanse
- inquirerer
- create-gen-app

steps:
- name: Checkout code
Expand Down
253 changes: 253 additions & 0 deletions packages/appstash/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
# appstash

Simple, clean application directory resolution for Node.js applications.

## Installation

```bash
npm install appstash
# or
pnpm add appstash
```

## Features

- **Simple API**: Just one function to get all your app directories
- **Clean structure**: `~/.<tool>/{config,cache,data,logs}` + `/tmp/<tool>`
- **Graceful fallback**: XDG directories → tmp if home fails
- **No throws**: Always returns valid paths, never throws errors
- **TypeScript**: Full type definitions included
- **Zero dependencies**: Pure Node.js implementation

## Usage

### Basic Usage

```typescript
import { appstash } from 'appstash';

// Get directories for your tool
const dirs = appstash('pgpm');

console.log(dirs.config); // ~/.pgpm/config
console.log(dirs.cache); // ~/.pgpm/cache
console.log(dirs.data); // ~/.pgpm/data
console.log(dirs.logs); // ~/.pgpm/logs
console.log(dirs.tmp); // /tmp/pgpm
```

### Create Directories

```typescript
import { appstash } from 'appstash';

// Get directories and create them
const dirs = appstash('pgpm', { ensure: true });

// All directories now exist
// dirs.usedFallback will be true if XDG or tmp fallback was used
```

### Resolve Paths

```typescript
import { appstash, resolve } from 'appstash';

const dirs = appstash('pgpm');

// Resolve paths within directories
const configFile = resolve(dirs, 'config', 'settings.json');
// Returns: ~/.pgpm/config/settings.json

const cacheDir = resolve(dirs, 'cache', 'repos', 'my-repo');
// Returns: ~/.pgpm/cache/repos/my-repo
```

### Manual Ensure

```typescript
import { appstash, ensure } from 'appstash';

const dirs = appstash('pgpm');

// Create directories later
const result = ensure(dirs);

console.log(result.created); // ['~/.pgpm', '~/.pgpm/config', ...]
console.log(result.usedFallback); // false (or true if fallback was used)
```

## API

### `appstash(tool, options?)`

Get application directories for a tool.

**Parameters:**
- `tool` (string): Tool name (e.g., 'pgpm', 'lql')
- `options` (object, optional):
- `baseDir` (string): Base directory (defaults to `os.homedir()`)
- `useXdgFallback` (boolean): Use XDG fallback if home fails (default: `true`)
- `ensure` (boolean): Automatically create directories (default: `false`)
- `tmpRoot` (string): Root for temp directory (defaults to `os.tmpdir()`)

**Returns:** `AppStashResult`
```typescript
{
root: string; // ~/.<tool>
config: string; // ~/.<tool>/config
cache: string; // ~/.<tool>/cache
data: string; // ~/.<tool>/data
logs: string; // ~/.<tool>/logs
tmp: string; // /tmp/<tool>
usedFallback?: boolean; // true if XDG or tmp fallback was used
}
```

### `ensure(dirs)`

Create directories if they don't exist. Never throws.

**Parameters:**
- `dirs` (AppStashResult): Directory paths from `appstash()`

**Returns:** `EnsureResult`
```typescript
{
created: string[]; // Directories that were created
usedFallback: boolean; // true if XDG or tmp fallback was used
}
```

### `resolve(dirs, kind, ...parts)`

Resolve a path within a specific directory.

**Parameters:**
- `dirs` (AppStashResult): Directory paths from `appstash()`
- `kind` ('config' | 'cache' | 'data' | 'logs' | 'tmp'): Directory kind
- `parts` (string[]): Path parts to join

**Returns:** `string` - Resolved path

## Directory Structure

### Primary (POSIX-style)

```
~/.<tool>/
├── config/ # Configuration files
├── cache/ # Cached data
├── data/ # Application data
└── logs/ # Log files

/tmp/<tool>/ # Temporary files
```

### Fallback (XDG)

If home directory is unavailable or creation fails, falls back to XDG:

```
~/.config/<tool>/ # Config
~/.cache/<tool>/ # Cache
~/.local/share/<tool>/ # Data
~/.local/state/<tool>/logs/ # Logs
```

### Final Fallback (tmp)

If XDG also fails, falls back to system temp:

```
/tmp/<tool>/
├── config/
├── cache/
├── data/
└── logs/
```

## Examples

### Configuration File

```typescript
import { appstash, resolve } from 'appstash';
import fs from 'fs';

const dirs = appstash('myapp', { ensure: true });
const configPath = resolve(dirs, 'config', 'settings.json');

// Write config
fs.writeFileSync(configPath, JSON.stringify({ theme: 'dark' }));

// Read config
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
```

### Cache Management

```typescript
import { appstash, resolve } from 'appstash';
import fs from 'fs';

const dirs = appstash('myapp', { ensure: true });
const cacheFile = resolve(dirs, 'cache', 'data.json');

// Check if cached
if (fs.existsSync(cacheFile)) {
const cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
console.log('Using cached data:', cached);
} else {
// Fetch and cache
const data = await fetchData();
fs.writeFileSync(cacheFile, JSON.stringify(data));
}
```

### Logging

```typescript
import { appstash, resolve } from 'appstash';
import fs from 'fs';

const dirs = appstash('myapp', { ensure: true });
const logFile = resolve(dirs, 'logs', 'app.log');

function log(message: string) {
const timestamp = new Date().toISOString();
fs.appendFileSync(logFile, `[${timestamp}] ${message}\n`);
}

log('Application started');
```

### Custom Base Directory

```typescript
import { appstash } from 'appstash';

// Use a custom base directory
const dirs = appstash('myapp', {
baseDir: '/opt/myapp',
ensure: true
});

console.log(dirs.config); // /opt/myapp/.myapp/config
```

## Design Philosophy

- **Simple**: One function, clear structure
- **Clean**: No pollution of exports, minimal API surface
- **Graceful**: Never throws, always returns valid paths
- **Fallback**: XDG only as absolute fallback, not primary
- **Focused**: Just directory resolution, no state management

## License

MIT

## Contributing

See the main [hyperweb-io/dev-utils repository](https://github.com/hyperweb-io/dev-utils) for contribution guidelines.
Loading