@ossy/cli 1.40.0 → 1.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -17
- package/package.json +4 -4
- package/src/app/publish.js +3 -3
- package/src/call/cli.js +15 -11
- package/src/index.js +6 -1
- package/src/upload-dir/cli.js +2 -2
package/README.md
CHANGED
|
@@ -23,8 +23,8 @@ For one-off use without installing, you can still run `npx @ossy/cli <command>`.
|
|
|
23
23
|
The contract for everything the platform can do is the **SDK action POJO** in [`@ossy/sdk`](../sdk) (`{ id, endpoint, method, payload }`). The CLI is one channel onto that catalog, organized in three layers:
|
|
24
24
|
|
|
25
25
|
1. **Local utilities** — no API call, or per-machine state. `auth`, `workspace`, `app init`, `app build`, `app validate`.
|
|
26
|
-
2. **Action dispatcher** — `
|
|
27
|
-
3. **High-level workflows** — verbs that wrap one or more actions and add value the dispatcher doesn't (reading `src/config.js`, formatting output for CI, multi-step pipelines). Each workflow's docs name the underlying action(s) so you can drop down to `ossy
|
|
26
|
+
2. **Action dispatcher** — `invoke <action.id>` invokes any action in the SDK catalog. New endpoints added to the SDK are callable from the terminal with no extra CLI wiring.
|
|
27
|
+
3. **High-level workflows** — verbs that wrap one or more actions and add value the dispatcher doesn't (reading `src/config.js`, formatting output for CI, multi-step pipelines). Each workflow's docs name the underlying action(s) so you can drop down to `ossy invoke` if you outgrow the verb.
|
|
28
28
|
|
|
29
29
|
| Layer | Command | Description |
|
|
30
30
|
|-------|---------|-------------|
|
|
@@ -33,12 +33,12 @@ The contract for everything the platform can do is the **SDK action POJO** in [`
|
|
|
33
33
|
| Local | `app init [dir]` | Scaffold a new Ossy app (default: current directory) |
|
|
34
34
|
| Local | `app build` | Production build of the app in the current directory |
|
|
35
35
|
| Local | `app validate` | Validate `src/config.js` (`workspaceId`, `resourceTemplates`) without calling the API |
|
|
36
|
-
| Dispatcher | `
|
|
36
|
+
| Dispatcher | `invoke <action.id>` | Invoke any Ossy SDK action by id (`ossy invoke --help` for the full catalog) |
|
|
37
37
|
| Workflow | `app upload` | Read `resourceTemplates` from `src/config.js` and call `workspaces.import-resource-templates` |
|
|
38
38
|
| Workflow | `app publish` | Upload resource templates and `build/` to the CMS (combines `app upload` + `upload-dir`) |
|
|
39
39
|
| Workflow | `upload-dir <dir> <location>` | Recursively mirror a local directory into the CMS (mkdir + upload per file) |
|
|
40
40
|
|
|
41
|
-
If you need an endpoint that no verb wraps, reach for `ossy
|
|
41
|
+
If you need an endpoint that no verb wraps, reach for `ossy invoke` — it's the universal channel.
|
|
42
42
|
|
|
43
43
|
## Auth and active workspace
|
|
44
44
|
|
|
@@ -65,34 +65,34 @@ Resolution order for the workspace id (when a command isn't reading it from `src
|
|
|
65
65
|
|
|
66
66
|
So existing CI scripts that set `OSSY_API_KEY` keep working unchanged; you only need `ossy auth login` for interactive use.
|
|
67
67
|
|
|
68
|
-
## Generic dispatcher: `ossy
|
|
68
|
+
## Generic dispatcher: `ossy invoke`
|
|
69
69
|
|
|
70
|
-
`ossy
|
|
70
|
+
`ossy invoke` invokes any Ossy API action by id. The action catalog comes from `@ossy/sdk`, so any new endpoint added to the SDK is callable from the terminal with no extra wiring.
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
73
|
# Discover what's available
|
|
74
|
-
ossy
|
|
75
|
-
ossy
|
|
74
|
+
ossy invoke --help # full catalog, grouped by domain
|
|
75
|
+
ossy invoke resources.create --help # one action's method, endpoint, default payload
|
|
76
76
|
|
|
77
77
|
# Read calls
|
|
78
|
-
ossy
|
|
79
|
-
ossy
|
|
78
|
+
ossy invoke workspaces.get-current
|
|
79
|
+
ossy invoke resources.list --search 'location=/docs'
|
|
80
80
|
|
|
81
81
|
# Write calls — flag names map to payload keys (--first-name -> firstName)
|
|
82
|
-
ossy
|
|
83
|
-
ossy
|
|
82
|
+
ossy invoke resources.create-directory --location /docs --name images
|
|
83
|
+
ossy invoke workspaces.invite-user --email teammate@example.com
|
|
84
84
|
|
|
85
85
|
# Use --json for nested or non-string payloads
|
|
86
|
-
ossy
|
|
86
|
+
ossy invoke resources.update-content --id res_abc --json '{"content":{"title":"Hi"}}'
|
|
87
87
|
|
|
88
88
|
# Upload a file: --file fills name/type/size as defaults, then PUTs the bytes
|
|
89
89
|
# when the response carries content.uploadUrl (works for resources.upload,
|
|
90
90
|
# resources.upload-named-version, etc.)
|
|
91
|
-
ossy
|
|
92
|
-
ossy
|
|
91
|
+
ossy invoke resources.upload --location /docs --file ./hero.jpg
|
|
92
|
+
ossy invoke resources.upload-named-version --id res_abc --name medium --file ./hero.jpg
|
|
93
93
|
|
|
94
94
|
# Per-call overrides (otherwise resolved from `ossy auth login` / `ossy workspace use`)
|
|
95
|
-
ossy
|
|
95
|
+
ossy invoke workspaces.get-all -a <jwt> --api-url http://localhost:3001/api/v0
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
Output is JSON pretty-printed to stdout on success. Errors go to stderr with a non-zero exit. Add `--raw` to get the response body verbatim (useful for piping non-JSON responses).
|
|
@@ -171,7 +171,7 @@ Upload resource templates to your workspace so they can be used in the UI.
|
|
|
171
171
|
Wraps the SDK action **`workspaces.import-resource-templates`** and adds: reading `resourceTemplates` and `workspaceId` from `src/config.js` (so you don't have to inline the templates JSON yourself). If you already have the templates as a JSON object, the equivalent dispatcher call is:
|
|
172
172
|
|
|
173
173
|
```bash
|
|
174
|
-
ossy
|
|
174
|
+
ossy invoke workspaces.import-resource-templates --json '{"templates":[…]}'
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
Prefer **`--authentication` / `-a`** for the **Ossy API JWT** (same as **`app publish`**); it matches **`OSSY_API_KEY`** in CI.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/cli",
|
|
3
|
-
"version": "1.40.
|
|
3
|
+
"version": "1.40.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/ossy-se/packages.git"
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@babel/parser": "^7.28.6",
|
|
23
|
-
"@ossy/app": "^1.40.
|
|
24
|
-
"@ossy/sdk": "^1.40.
|
|
23
|
+
"@ossy/app": "^1.40.1",
|
|
24
|
+
"@ossy/sdk": "^1.40.1",
|
|
25
25
|
"arg": "^5.0.2",
|
|
26
26
|
"glob": "^13.0.6"
|
|
27
27
|
},
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"/src",
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "c0ba5d90749690634e4dc2705178ff8d89dd3070"
|
|
37
37
|
}
|
package/src/app/publish.js
CHANGED
|
@@ -115,7 +115,7 @@ export async function publish (options) {
|
|
|
115
115
|
const parent = i === 0 ? '/' : '/' + destSegments.slice(0, i).join('/')
|
|
116
116
|
const name = destSegments[i]
|
|
117
117
|
try {
|
|
118
|
-
await sdk.
|
|
118
|
+
await sdk.invoke(createDir, { location: parent, name })
|
|
119
119
|
} catch (err) {
|
|
120
120
|
const status = err && err.status
|
|
121
121
|
if (status !== 409 && status !== 422) {
|
|
@@ -133,7 +133,7 @@ export async function publish (options) {
|
|
|
133
133
|
const parent = normaliseLoc(remoteDest + path.dirname(rel))
|
|
134
134
|
const name = path.basename(d)
|
|
135
135
|
try {
|
|
136
|
-
await sdk.
|
|
136
|
+
await sdk.invoke(createDir, { location: parent, name })
|
|
137
137
|
} catch (err) {
|
|
138
138
|
const status = err && err.status
|
|
139
139
|
if (status !== 409 && status !== 422) {
|
|
@@ -164,7 +164,7 @@ export async function publish (options) {
|
|
|
164
164
|
|
|
165
165
|
let result
|
|
166
166
|
try {
|
|
167
|
-
result = await sdk.
|
|
167
|
+
result = await sdk.invoke(uploadAction, {
|
|
168
168
|
location: remoteDir,
|
|
169
169
|
name: fileMeta.name,
|
|
170
170
|
type: fileMeta.type,
|
package/src/call/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Sdk from '@ossy/sdk'
|
|
2
|
+
import { resolveActionId } from '@ossy/sdk'
|
|
2
3
|
import { logError } from '../log.js'
|
|
3
4
|
import { getAuth, getApiUrl, getWorkspaceId } from '../state.js'
|
|
4
5
|
import { prepareFileUpload, uploadFileToUrl } from '../file.js'
|
|
@@ -8,16 +9,19 @@ const ACTIONS = Object.values(Sdk).filter(
|
|
|
8
9
|
v
|
|
9
10
|
&& typeof v === 'object'
|
|
10
11
|
&& typeof v.id === 'string'
|
|
11
|
-
&&
|
|
12
|
-
&& typeof v.method === 'string'
|
|
12
|
+
&& v.id.includes('/')
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
-
const ACTION_BY_ID = new Map(
|
|
15
|
+
const ACTION_BY_ID = new Map()
|
|
16
|
+
for (const action of ACTIONS) {
|
|
17
|
+
ACTION_BY_ID.set(action.id, action)
|
|
18
|
+
ACTION_BY_ID.set(action.id.replace(/\//g, '.'), action)
|
|
19
|
+
}
|
|
16
20
|
|
|
17
21
|
function listActionsByDomain () {
|
|
18
22
|
const grouped = new Map()
|
|
19
23
|
for (const action of ACTIONS) {
|
|
20
|
-
const domain = action.id.split('
|
|
24
|
+
const domain = action.id.split('/')[0]
|
|
21
25
|
if (!grouped.has(domain)) grouped.set(domain, [])
|
|
22
26
|
grouped.get(domain).push(action.id)
|
|
23
27
|
}
|
|
@@ -31,7 +35,7 @@ function buildHelp () {
|
|
|
31
35
|
for (const [domain, ids] of grouped) {
|
|
32
36
|
blocks.push(` ${domain}\n${ids.map((id) => ` ${id}`).join('\n')}`)
|
|
33
37
|
}
|
|
34
|
-
return `ossy
|
|
38
|
+
return `ossy invoke <action.id> [--key value]... [--json '{...}'] [options]
|
|
35
39
|
|
|
36
40
|
Generic dispatcher for any Ossy API action. Flags become payload fields
|
|
37
41
|
(--first-name -> firstName); --json '{...}' is merged on top.
|
|
@@ -46,7 +50,7 @@ Options:
|
|
|
46
50
|
--raw Print response body without JSON pretty-printing
|
|
47
51
|
|
|
48
52
|
Per-action help:
|
|
49
|
-
ossy
|
|
53
|
+
ossy invoke <action.id> --help
|
|
50
54
|
|
|
51
55
|
Available actions:
|
|
52
56
|
|
|
@@ -56,11 +60,11 @@ ${blocks.join('\n\n')}
|
|
|
56
60
|
|
|
57
61
|
function actionHelp (action) {
|
|
58
62
|
const def = action.payload ? `Default payload:\n ${JSON.stringify(action.payload)}\n\n` : ''
|
|
59
|
-
return `${action.id}
|
|
63
|
+
return `${action.id} POST /actions { action: "${action.id}", payload: … }
|
|
60
64
|
|
|
61
65
|
${def}Examples:
|
|
62
|
-
ossy
|
|
63
|
-
ossy
|
|
66
|
+
ossy invoke ${action.id} --key value --other value
|
|
67
|
+
ossy invoke ${action.id} --json '{"key":"value"}'
|
|
64
68
|
`
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -211,7 +215,7 @@ async function call (args) {
|
|
|
211
215
|
return
|
|
212
216
|
}
|
|
213
217
|
|
|
214
|
-
const action = ACTION_BY_ID.get(parsed.actionId)
|
|
218
|
+
const action = ACTION_BY_ID.get(parsed.actionId) ?? ACTION_BY_ID.get(resolveActionId(parsed.actionId))
|
|
215
219
|
if (!action) {
|
|
216
220
|
logError({
|
|
217
221
|
message: `[@ossy/cli] call: unknown action "${parsed.actionId}". Run \`ossy call --help\` for the list.`,
|
|
@@ -249,7 +253,7 @@ async function call (args) {
|
|
|
249
253
|
|
|
250
254
|
let result
|
|
251
255
|
try {
|
|
252
|
-
result = await sdk.
|
|
256
|
+
result = await sdk.invoke(action, parsed.payload)
|
|
253
257
|
} catch (err) {
|
|
254
258
|
if (isResponseLike(err)) {
|
|
255
259
|
const text = await err.text().catch(() => '')
|
package/src/index.js
CHANGED
|
@@ -25,7 +25,7 @@ Local utilities:
|
|
|
25
25
|
app <subcommand> App commands: init | build | upload | validate | publish
|
|
26
26
|
|
|
27
27
|
Action dispatcher (any Ossy SDK action, no per-action wiring needed):
|
|
28
|
-
|
|
28
|
+
invoke <action.id> Run \`ossy invoke --help\` for the full catalog
|
|
29
29
|
|
|
30
30
|
Workflows (wrap one or more actions with extra ergonomics):
|
|
31
31
|
upload-dir <dir> <loc> Recursively upload a local directory to the CMS
|
|
@@ -120,7 +120,12 @@ const run = async () => {
|
|
|
120
120
|
await Workspace.handler(restArgs)
|
|
121
121
|
return
|
|
122
122
|
}
|
|
123
|
+
if (command === 'invoke') {
|
|
124
|
+
await Call.handler(restArgs)
|
|
125
|
+
return
|
|
126
|
+
}
|
|
123
127
|
if (command === 'call') {
|
|
128
|
+
process.stderr.write('[@ossy/cli] `ossy call` is deprecated — use `ossy invoke` instead.\n')
|
|
124
129
|
await Call.handler(restArgs)
|
|
125
130
|
return
|
|
126
131
|
}
|
package/src/upload-dir/cli.js
CHANGED
|
@@ -198,7 +198,7 @@ export async function handler (args) {
|
|
|
198
198
|
const name = path.basename(d)
|
|
199
199
|
logInfo({ message: `[@ossy/cli] upload-dir: mkdir ${parent}/${name}` })
|
|
200
200
|
try {
|
|
201
|
-
await sdk.
|
|
201
|
+
await sdk.invoke(createDir, { location: parent, name })
|
|
202
202
|
dirsMade++
|
|
203
203
|
} catch (err) {
|
|
204
204
|
// Treat "already exists" (HTTP 409 / 422 / resource conflict) as success
|
|
@@ -231,7 +231,7 @@ export async function handler (args) {
|
|
|
231
231
|
|
|
232
232
|
let result
|
|
233
233
|
try {
|
|
234
|
-
result = await sdk.
|
|
234
|
+
result = await sdk.invoke(uploadAction, {
|
|
235
235
|
location: remoteDir,
|
|
236
236
|
name: fileMeta.name,
|
|
237
237
|
type: fileMeta.type,
|