npm package: @funeste38/freeland
Description: Typed normalization hub for heterogeneous values across prefixes, files, runtimes and platforms (json:, b64:, file:, exe:, zip:, nez:, ...).
Author: jEFFLEZ
Latest version: 0.2.2

# freeland

Freeland is the neutral normalization layer of the Funesterie ecosystem.

`v1` was a prefix decoder.
`v2` keeps that compatibility, but upgrades Freeland into a typed hub:

```txt
heterogeneous input -> Freeland parse -> typed canonical object -> runtime adaptation
```

That means Freeland can now be the place where text, JSON, files, images, executables, archives, URLs and secrets all pass through the same language before they hit A11, Qflush, Spyder or deployment runtimes.

## Install

```bash
npm install @funeste38/freeland
```

The unscoped `freeland` package is deprecated. Use the scoped package directly.

## Legacy v1 API

The original API still works:

```ts
import { registerSystem, decodeSystemValue } from "@funeste38/freeland";

registerSystem("upper:", (raw) => raw.toUpperCase());

const shout = await decodeSystemValue("upper:funesterie");
```

Built-in legacy prefixes:

- `json:`
- `b64:` / `base64:`
- `file:`
- `nez:`

## Typed v2 API

The new API resolves an input into a canonical object:

```ts
import { resolveFreelandValue } from "@funeste38/freeland";

const value = await resolveFreelandValue("b64:SGVsbG8=");
```

Example result:

```json
{
  "kind": "text",
  "format": "base64",
  "encoding": "utf8",
  "value": "Hello",
  "state": "compatible",
  "runtime": "node",
  "platform": "linux"
}
```

### Main exported concepts

- `resolveFreelandValue(input, options)`
- `adaptFreelandValue(value, runtime)`
- `registerFormat(prefix, handler)`
- `registerAdapter(runtime, adapter)`
- `parseFreelandInput(input)`
- `toFreelandCube(value, runtime?)`

### Canonical value shape

```ts
type FreelandValue = {
  kind:
    | "text"
    | "json"
    | "binary"
    | "image"
    | "audio"
    | "executable"
    | "archive"
    | "path"
    | "url"
    | "secret"
    | "identifier"
    | "unknown";
  format?: string;
  platform?: "windows" | "linux" | "mac" | "any";
  runtime?: "windows" | "linux" | "mac" | "docker" | "railway" | "local" | "browser" | "node" | "any";
  mime?: string;
  encoding?: string;
  value: unknown;
  state?: "raw" | "decoded" | "normalized" | "resolved" | "compatible" | "incompatible";
  meta?: Record<string, unknown>;
};
```

## Composition

Freeland supports nested prefixes:

```txt
b64:file:./hello.b64.txt
exe:json:{"windows":"path:./bin/piper.exe","linux":"path:./bin/piper"}
zip:file:./artifacts/release.zip
manifest:json:{"kind":"executable","variants":{"windows":"path:./bin/piper.exe","linux":"path:./bin/piper"}}
```

Resolution happens from inside to outside:

- `file:` first
- then `b64:`
- then runtime adaptation if requested

## Built-in format families

- text: `text:`
- structured: `json:`
- binary: `b64:`, `base64:`, `hex:`, `bin:`
- filesystem: `file:`, `path:`
- identity/transport: `url:`, `id:`, `secret:`, `nez:`
- assets: `img:`, `image:`, `audio:`
- containers: `zip:`, `tar:`, `archive:`
- runtime artifacts: `exe:`

## Runtime-aware executables

Freeland now has a first-class way to describe executables by target:

```ts
const ffmpeg = await resolveFreelandValue(
  'exe:json:{"windows":"path:./bin/ffmpeg.exe","linux":"path:./bin/ffmpeg","default":"path:./bin/ffmpeg"}',
  { runtime: "railway" }
);
```

Freeland will:

- pick the best variant for the runtime/platform
- mark the result `compatible` or `incompatible`
- refuse browser execution targets for native executables

## Manifests

Freeland now supports lightweight manifests for runtime-aware resources:

```ts
const runtimeTool = await resolveFreelandValue(
  'manifest:json:{"kind":"executable","variants":{"windows":"path:./bin/piper.exe","linux":"path:./bin/piper"},"meta":{"name":"piper"}}',
  { runtime: "railway" }
);
```

This is the cleanest way to describe:

- runtime-specific executables
- portable bundles
- future image/audio/archive variants
- metadata-rich resources without inventing more one-off prefixes

## Zip and archive support

Yes: archives should be first-class.

Freeland should not treat zip as "just another string prefix". It should treat it as a container family:

- `zip:` for zip-specific tagging
- `archive:` as the neutral umbrella kind
- later: optional unpack/list/inspect adapters without bloating the core

That gives you room for:

- release bundles
- embedded assets
- portable module packs
- hand-off between local, CI and Railway

## RGBA / Rubik / Morphing

My recommendation:

- keep `freeland` as the typed normalization core
- keep `morphing` as the low-level 4-byte transport primitive
- keep RGBA / Rubik visualization as a separate layer above the core

In practice:

- `freeland` answers: "what is this value?"
- `morphing` answers: "how do I pack or move this compactly?"
- `freeland-bros` or another addon can answer: "how do I visualize or solve compatibility as RGBA / cube rotations?"

That is why `v2` exports `toFreelandCube()` already: it gives you a stable bridge toward the Rubik/RGBA idea without forcing the core to depend on image semantics too early.

## CLI

Freeland now ships a real CLI:

```bash
freeland --pretty "b64:SGVsbG8="
freeland --runtime railway --pretty "exe:json:{\"windows\":\"path:./bin/piper.exe\",\"linux\":\"path:./bin/piper\"}"
freeland --legacy "file:./.env"
```

## Suggestions for the next step

The best next upgrade is not "more prefixes". It is:

1. `freeland-core`
2. `freeland-adapters`
3. `freeland-bros`

Concretely:

1. Keep `freeland` small, typed and deterministic.
2. Put heavy or optional adapters behind opt-in packages.
3. Build RGBA / cube solving on top of the canonical object, not inside the parser.

## Development

```bash
npm install
npm run build
npm test
```

## License

MIT