Skip to content
Open
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
66 changes: 54 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const fillInTemplateValues = (filePath, templateData) => {
};
```

Values sourced from `modules/*/template-values.json`. Processed during sync and deploy.
Values sourced from `modules/*/template-values.json` (custom params) and `modules/*/pos-module.json` (identity scalars: `machine_name`, `version`, `name`). The two files are merged — `pos-module.json` is the base and `template-values.json` overlays on top. Processed during sync and deploy; never touched by the modules CLI.

#### 6. Authentication Flow
**Files**: `lib/environments.js`, `lib/envs/add.js`
Expand All @@ -247,26 +247,32 @@ Centralized error handling with specific handlers for different HTTP status code
#### Configuration Files
- `.pos` - Environment credentials (URL, token, email) as JSON
- `.posignore` - Files to exclude from sync/deploy (gitignore syntax)
- `app/pos-modules.json` - Installed modules list
- `modules/*/template-values.json` - Module configuration and dependencies
- `pos-module.json` - Universal platformOS project manifest (analogous to `package.json`). Its presence in a consuming app is normal — it lists `dependencies`. Publishable modules additionally have `machine_name`, `version`, and `name`. It is the **sole source** for all `modules` CLI commands (`install`, `update`, `push`, `version`, `migrate`).
- `pos-module.lock.json` - Resolved dependency versions (separate prod/dev sections) plus a `registries` map recording which registry each module was resolved from; makes the lock self-contained for `--frozen` mode
- `modules/*/template-values.json` - Optional: custom template substitution values **only** (e.g. `prefix`, `namespace`). Never contains metadata (`machine_name`, `version`, etc.) — those belong in `pos-module.json`. Read during sync/deploy; never read by the modules CLI.

Legacy (still read as a fallback, but never written):
- `app/pos-modules.json` - Old module list location; migrate with `pos-cli modules migrate`

#### platformOS Directory Structure
pos-cli expects projects to follow this structure:
```
project/
├── pos-module.json # Module manifest (replaces app/pos-modules.json)
├── pos-module.lock.json # Resolved dependency lock file
├── app/ (or marketplace_builder/) # Main application
│ ├── assets/ # Static assets
│ ├── views/ # Liquid templates
│ ├── graphql/ # GraphQL queries/mutations
│ ├── schema/ # Data models
│ ├── authorization_policies/ # Access control
│ ├── migrations/ # Database migrations
│ └── pos-modules.json # Module dependencies
│ └── migrations/ # Database migrations
├── modules/ # Installed/local modules
│ └── <module-name>/
│ ├── public/ # Public module files
│ ├── private/ # Private module files
│ └── template-values.json # Module config
│ ├── pos-module.json # Module identity (installed by pos-cli modules install)
│ └── template-values.json # Optional: custom template substitution values (no metadata)
├── .pos # Environment configuration
└── .posignore # Ignore patterns
```
Expand Down Expand Up @@ -307,26 +313,62 @@ Key variables that affect behavior:
- `DEBUG` - Enables debug logging
- `NO_COLOR` - Disables colored output
- `CONCURRENCY` - Override sync concurrency (default: 3)
- `PARTNER_PORTAL_HOST` - Override the module registry URL used by `modules install` and `modules update` (default: `https://partners.platformos.com`)

#### Module System
Complete lifecycle:
- **Init**: Create from template (github.com/Platform-OS/pos-module-template)
- **Install**: Add to app/pos-modules.json, resolve dependencies, update lock file, and automatically download all module files to `modules/`
- **Install**: Add to `pos-module.json`, resolve the full dependency tree, write `pos-module.lock.json`, and download all changed/missing modules to `modules/`
- **Install --frozen**: CI-safe install — uses the existing lock file as-is, never calls the registry for resolution, fails fast if the lock file is missing or stale
- **Publish**: Version and push to marketplace (requires Partner Portal account)
- **Pull**: Get deployed version from instance
- **Update**: Update version in pos-modules.json, resolve dependencies, update lock file, and automatically download updated module files to `modules/`
- **Update**: Update a module entry in `pos-module.json`, re-resolve the full tree, update the lock file, and download changed modules
- **Migrate**: `pos-cli modules migrate` runs two independent phases:
- **Phase A**: converts legacy `app/pos-modules.json` → `pos-module.json` (deps migration)
- **Phase B**: moves metadata fields (`machine_name`, `version`, `name`, `repository_url`) from any `template-values.json` → `pos-module.json`, stripping them from the source file. Use `--name <machine_name>` to target a specific `modules/<name>/template-values.json` when multiple exist.

Note: `pos-cli modules download` has been removed. `install` and `update` always download all module files and dependencies automatically.

Module dependencies specified in `template-values.json`:
Module manifest `pos-module.json` (unified format for both apps and publishable modules):
```json
{
"machine_name": "my-module",
"version": "1.0.0",
"dependencies": ["core", "admin"]
"name": "User",
"machine_name": "user",
"version": "5.1.2",
"repository_url": "https://partners.platformos.com",
"dependencies": {
"core": "^1.5.0"
},
"devDependencies": {
"tests": "1.0.1"
},
"registries": {
"private-module": "https://portal.private-stack.online"
}
}
```

`repository_url` is **publishing metadata only** — it tells `pos-cli modules push` where to publish the module. It has **no effect** on dependency resolution. The registry used for `install`/`update` is determined by `PARTNER_PORTAL_HOST` (env var) or the hardcoded fallback `https://partners.platformos.com`.

The optional `registries` map provides **per-module registry URL overrides** for private or custom registries. After each `install` or `update`, every resolved module gets an explicit entry stamped into the lock file's `registries` map, making `pos-module.lock.json` self-contained for `--frozen` mode. Old lock files without per-module entries fall back to the hardcoded default.

The `--dev` flag controls which section a named module is added to:
```
pos-cli modules install core # adds core to dependencies
pos-cli modules install tests --dev # adds tests to devDependencies
pos-cli modules install --dev # installs dependencies + devDependencies
pos-cli modules install --frozen # CI: use lock file as-is, no resolution
pos-cli modules install --frozen --dev # CI: same, including devDependencies
pos-cli modules update core # bumps core to latest stable
pos-cli modules update core@2.0.0 # pins core to exact version
pos-cli modules update --dev # re-resolves both sections
```

**Update semantics for exact pins**: `pos-cli modules update` (no name) does not bump exact-pinned
entries — it only re-resolves range constraints to the best available version within the range.
To bump an exact pin, name it explicitly: `pos-cli modules update core`.
This matches npm's behaviour where `npm update` does not modify exact pins.

#### GUI Server
Express server (`lib/server.js`) serves three pre-built web apps:
- Admin panel (port 3333, configurable with --port)
Expand Down
58 changes: 56 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,63 @@ After running the command, you can see the new module directory has been created

#### Installation

Install modules published in the modules marketplace. The `install` command adds the module to `app/pos-modules.json`, resolves all dependencies, updates `app/pos-modules.lock.json`, and downloads all module files into the `modules/` directory:
Install modules published in the modules marketplace. The `install` command adds the module to `pos-module.json`, resolves all transitive dependencies, writes `pos-module.lock.json`, and downloads all module files into the `modules/` directory.

**Two files, two purposes:**

- `pos-module.json` — your declared intent. Edit this file to express which modules you want and at what version constraints. Commit it to source control.
- `pos-module.lock.json` — auto-generated. Records the exact resolved version of every module and its transitive dependencies, plus the registry URL each module was resolved from. Commit this too so teammates and CI get identical installs.

**Installing a module**

# Install latest stable — stores a caret range (e.g. ^2.0.0) in pos-module.json
pos-cli modules install core

# Install with a caret range — allows any compatible 2.x release
pos-cli modules install core@^2.0.0

# Install with a tilde range — allows patch-level updates only (2.1.x)
pos-cli modules install core@~2.1.0

# Install an exact version — no automatic updates
pos-cli modules install core@2.1.5

# Re-resolve and download everything declared in pos-module.json (e.g. after cloning)
pos-cli modules install

**Version range syntax**

| Syntax | Example | What gets installed |
|--------|---------|---------------------|
| No version | `install core` | Latest stable; stores `^MAJOR.0.0` |
| Caret `^` | `^2.0.0` | Highest `2.x.x` release (`>=2.0.0 <3.0.0`) |
| Tilde `~` | `~2.1.0` | Highest `2.1.x` patch release (`>=2.1.0 <2.2.0`) |
| Exact | `2.1.5` | Exactly `2.1.5`, never updated automatically |
| Greater-or-equal | `>=2.0.0` | Highest stable `2.0.0` or above |
| Range | `>=2.0.0 <3.0.0` | Highest stable within the bounds |

**Updating modules**

# Re-resolve all modules — range entries re-resolve to latest within their range; exact pins are unchanged
pos-cli modules update

# Update a single module to its latest stable (or latest within its stored range)
pos-cli modules update core

# Change a module's constraint to a new range
pos-cli modules update core@^3.0.0

# Pin a module to a specific version
pos-cli modules update core@3.1.0

**Key difference between `install` and `update`:**

- `install core` when `core` is already in `pos-module.json` → **no-op** on the constraint; dependencies are still re-resolved and any missing files downloaded.
- `update core` when `core` has an exact pin → always fetches the latest stable release and updates the pin.
- `update core` when `core` has a range (e.g. `^2.0.0`) → re-resolves to the latest within that range; the range itself is unchanged in `pos-module.json`.

After installing or updating, deploy to apply the changes to your instance:

pos-cli modules install [module name]
pos-cli deploy <env>

#### Remove
Expand Down
91 changes: 0 additions & 91 deletions TESTING.md

This file was deleted.

Loading
Loading