fvtt-world-cli 1.2.0 → 1.3.0
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/dist/index.js +645 -167
- package/docs/commands.md +18 -9
- package/docs/compatibility.md +2 -0
- package/docs/protocol.md +45 -15
- package/package.json +2 -2
- package/skills/foundry-world-editor/SKILL.md +25 -12
- package/skills/foundry-world-editor/SKILL.md.sha256 +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { readFileSync as readFileSync2 } from "node:fs";
|
|
|
10
10
|
import { createHash as createHash2, randomBytes as randomBytes2, randomUUID as randomUUID2, timingSafeEqual } from "node:crypto";
|
|
11
11
|
|
|
12
12
|
// ../protocol/src/constants.js
|
|
13
|
-
var PROTOCOL_VERSION = "1.
|
|
13
|
+
var PROTOCOL_VERSION = "1.3.0";
|
|
14
14
|
var PROTOCOL_COMPONENTS = Object.freeze({
|
|
15
15
|
MODULE: "module",
|
|
16
16
|
CLI_DAEMON: "cli-daemon",
|
|
@@ -76,6 +76,9 @@ function resolveEffectiveLimits(uploadLimitBytes = DEFAULT_UPLOAD_SIZE_LIMIT_BYT
|
|
|
76
76
|
wsMaxPayloadBytes: Math.max(wsMaxPayloadForUploadLimit(uploadLimitBytes), DEFAULT_WS_MAX_PAYLOAD_BYTES)
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
+
var BROWSER_STRING_MAX_LENGTH = 536870888;
|
|
80
|
+
var READ_RESPONSE_ENVELOPE_RESERVE_CHARS = 1024 * 1024;
|
|
81
|
+
var READ_ENCODING_CEILING_BYTES = Math.floor((BROWSER_STRING_MAX_LENGTH - READ_RESPONSE_ENVELOPE_RESERVE_CHARS) / 4) * 3;
|
|
79
82
|
var BATCH_GET_MAX_IDS = 100;
|
|
80
83
|
var BATCH_WRITE_MAX_ITEMS = 100;
|
|
81
84
|
var BATCH_WRITE_STATUSES = Object.freeze([
|
|
@@ -102,6 +105,7 @@ var SCENE_THUMBNAIL_MAX_BYTES = 2 * 1024 * 1024;
|
|
|
102
105
|
var SCENE_THUMBNAIL_RESPONSE_MAX_BYTES = 1024 * 1024;
|
|
103
106
|
var TABLE_DRAW_MAX_COUNT = 100;
|
|
104
107
|
var SETTING_VALUE_MAX_BYTES = 256 * 1024;
|
|
108
|
+
var SERIALIZE_OMISSIONS_MAX = 100;
|
|
105
109
|
var MACRO_EXECUTE_TIMEOUT_DEFAULT_MS = 3e4;
|
|
106
110
|
var MACRO_EXECUTE_TIMEOUT_MAX_MS = 3e5;
|
|
107
111
|
var SEARCH_MODES = Object.freeze(["name", "full"]);
|
|
@@ -189,6 +193,7 @@ var ERROR_CODES = Object.freeze({
|
|
|
189
193
|
PLAYLIST_NOT_FOUND: "PLAYLIST_NOT_FOUND",
|
|
190
194
|
PLAYLIST_SOUND_NOT_FOUND: "PLAYLIST_SOUND_NOT_FOUND",
|
|
191
195
|
JOURNAL_CATEGORY_NOT_FOUND: "JOURNAL_CATEGORY_NOT_FOUND",
|
|
196
|
+
JOURNAL_PAGE_NOT_FOUND: "JOURNAL_PAGE_NOT_FOUND",
|
|
192
197
|
CHAT_MESSAGE_NOT_FOUND: "CHAT_MESSAGE_NOT_FOUND",
|
|
193
198
|
TABLE_NOT_FOUND: "TABLE_NOT_FOUND",
|
|
194
199
|
TABLE_RESULT_NOT_FOUND: "TABLE_RESULT_NOT_FOUND",
|
|
@@ -204,7 +209,6 @@ var ERROR_CODES = Object.freeze({
|
|
|
204
209
|
FOLDER_NOT_FOUND: "FOLDER_NOT_FOUND",
|
|
205
210
|
SETTING_NOT_FOUND: "SETTING_NOT_FOUND",
|
|
206
211
|
SETTING_READ_FAILED: "SETTING_READ_FAILED",
|
|
207
|
-
SETTING_VALUE_NOT_SERIALIZABLE: "SETTING_VALUE_NOT_SERIALIZABLE",
|
|
208
212
|
SETTING_PROTECTED: "SETTING_PROTECTED",
|
|
209
213
|
SETTING_UNREGISTERED: "SETTING_UNREGISTERED",
|
|
210
214
|
MACRO_TIMEOUT: "MACRO_TIMEOUT",
|
|
@@ -312,7 +316,10 @@ var batchIdsProperty = {
|
|
|
312
316
|
}
|
|
313
317
|
};
|
|
314
318
|
var tokenIncludeProperty = {
|
|
315
|
-
include: { type: "array", items: { type: "string", enum: ["prepared"] } }
|
|
319
|
+
include: { type: "array", items: { type: "string", enum: ["prepared", "delta"] } }
|
|
320
|
+
};
|
|
321
|
+
var tokenListIncludeProperty = {
|
|
322
|
+
include: { type: "array", items: { type: "string", enum: ["delta"] } }
|
|
316
323
|
};
|
|
317
324
|
var compendiumIncludeProperty = {
|
|
318
325
|
include: { type: "array", items: { type: "string", enum: ["effects"] } }
|
|
@@ -812,6 +819,11 @@ var actorCommands = {
|
|
|
812
819
|
},
|
|
813
820
|
{ mutation: true }
|
|
814
821
|
),
|
|
822
|
+
...batchWriteCommands("actor.item", {
|
|
823
|
+
scopeProperties: actorScopeProperties,
|
|
824
|
+
createSchema: embeddedItemDataSchema,
|
|
825
|
+
patchSchema: itemPatchSchema
|
|
826
|
+
}),
|
|
815
827
|
...batchWriteCommands("actor", {
|
|
816
828
|
scopeProperties: emptyScopeProperties,
|
|
817
829
|
patchSchema: actorPatchSchema,
|
|
@@ -1757,6 +1769,16 @@ var compendiumCommands = {
|
|
|
1757
1769
|
...compendiumIncludeProperty
|
|
1758
1770
|
},
|
|
1759
1771
|
additionalProperties: false
|
|
1772
|
+
}),
|
|
1773
|
+
"compendium.get-many": cmd({
|
|
1774
|
+
type: "object",
|
|
1775
|
+
required: ["pack", "ids"],
|
|
1776
|
+
properties: {
|
|
1777
|
+
pack: { type: "string", minLength: 1 },
|
|
1778
|
+
...batchIdsProperty,
|
|
1779
|
+
...compendiumIncludeProperty
|
|
1780
|
+
},
|
|
1781
|
+
additionalProperties: false
|
|
1760
1782
|
})
|
|
1761
1783
|
};
|
|
1762
1784
|
|
|
@@ -1797,6 +1819,22 @@ var auditFilesSchema = {
|
|
|
1797
1819
|
},
|
|
1798
1820
|
additionalProperties: false
|
|
1799
1821
|
};
|
|
1822
|
+
var REFERENCE_SCOPES = deepFreeze([...AUDIT_FILE_SCOPES, "folder", "setting", "chat"]);
|
|
1823
|
+
var REFERENCE_DEFAULT_SCOPES = deepFreeze(REFERENCE_SCOPES.filter((scope) => scope !== "chat"));
|
|
1824
|
+
var worldReferencesSchema = {
|
|
1825
|
+
type: "object",
|
|
1826
|
+
required: ["uuid"],
|
|
1827
|
+
properties: {
|
|
1828
|
+
uuid: { type: "string", minLength: 1 },
|
|
1829
|
+
scope: {
|
|
1830
|
+
type: "array",
|
|
1831
|
+
minItems: 1,
|
|
1832
|
+
items: { type: "string", enum: [...REFERENCE_SCOPES] }
|
|
1833
|
+
},
|
|
1834
|
+
...paginationProperties
|
|
1835
|
+
},
|
|
1836
|
+
additionalProperties: false
|
|
1837
|
+
};
|
|
1800
1838
|
var fileCommands = {
|
|
1801
1839
|
"file.list": cmd({
|
|
1802
1840
|
type: "object",
|
|
@@ -1884,7 +1922,8 @@ var fileCommands = {
|
|
|
1884
1922
|
)
|
|
1885
1923
|
};
|
|
1886
1924
|
var worldAuditCommands = {
|
|
1887
|
-
"world.audit-files": cmd(auditFilesSchema)
|
|
1925
|
+
"world.audit-files": cmd(auditFilesSchema),
|
|
1926
|
+
"world.references": cmd(worldReferencesSchema)
|
|
1888
1927
|
};
|
|
1889
1928
|
|
|
1890
1929
|
// ../protocol/src/schemas/folder.js
|
|
@@ -2240,6 +2279,16 @@ var journalPageCreateSchema = {
|
|
|
2240
2279
|
var journalPagePatchSchema = patchFrom(journalPageCreateSchema, {
|
|
2241
2280
|
prepend: { id: { type: "string", minLength: 1 } }
|
|
2242
2281
|
});
|
|
2282
|
+
var journalPageOwnPatchSchema = patchFrom(journalPageCreateSchema);
|
|
2283
|
+
var journalPageIdSchema = {
|
|
2284
|
+
type: "object",
|
|
2285
|
+
required: ["journalId", "pageId"],
|
|
2286
|
+
properties: {
|
|
2287
|
+
journalId: { type: "string", minLength: 1 },
|
|
2288
|
+
pageId: { type: "string", minLength: 1 }
|
|
2289
|
+
},
|
|
2290
|
+
additionalProperties: false
|
|
2291
|
+
};
|
|
2243
2292
|
var journalDataSchema = {
|
|
2244
2293
|
type: "object",
|
|
2245
2294
|
required: ["name"],
|
|
@@ -2407,6 +2456,58 @@ var journalCommands = {
|
|
|
2407
2456
|
patchSchema: journalDocumentPatchSchema,
|
|
2408
2457
|
verbs: ["update-many", "delete-many"]
|
|
2409
2458
|
}),
|
|
2459
|
+
"journal.page.list": cmd({
|
|
2460
|
+
type: "object",
|
|
2461
|
+
required: ["journalId"],
|
|
2462
|
+
properties: {
|
|
2463
|
+
journalId: { type: "string", minLength: 1 },
|
|
2464
|
+
...nameFilterProperty,
|
|
2465
|
+
...paginationProperties
|
|
2466
|
+
},
|
|
2467
|
+
additionalProperties: false
|
|
2468
|
+
}),
|
|
2469
|
+
"journal.page.get": cmd(journalPageIdSchema),
|
|
2470
|
+
"journal.page.create": cmd(
|
|
2471
|
+
{
|
|
2472
|
+
type: "object",
|
|
2473
|
+
required: ["journalId", "data"],
|
|
2474
|
+
properties: {
|
|
2475
|
+
journalId: { type: "string", minLength: 1 },
|
|
2476
|
+
data: journalPageCreateSchema,
|
|
2477
|
+
...dryRunProperty,
|
|
2478
|
+
...idempotencyKeyProperty
|
|
2479
|
+
},
|
|
2480
|
+
additionalProperties: false
|
|
2481
|
+
},
|
|
2482
|
+
{ mutation: true }
|
|
2483
|
+
),
|
|
2484
|
+
"journal.page.update": cmd(
|
|
2485
|
+
{
|
|
2486
|
+
type: "object",
|
|
2487
|
+
required: ["journalId", "pageId", "patch"],
|
|
2488
|
+
properties: {
|
|
2489
|
+
journalId: { type: "string", minLength: 1 },
|
|
2490
|
+
pageId: { type: "string", minLength: 1 },
|
|
2491
|
+
patch: journalPageOwnPatchSchema,
|
|
2492
|
+
...dryRunProperty
|
|
2493
|
+
},
|
|
2494
|
+
additionalProperties: false
|
|
2495
|
+
},
|
|
2496
|
+
{ mutation: true }
|
|
2497
|
+
),
|
|
2498
|
+
"journal.page.delete": cmd(
|
|
2499
|
+
{
|
|
2500
|
+
type: "object",
|
|
2501
|
+
required: ["journalId", "pageId"],
|
|
2502
|
+
properties: {
|
|
2503
|
+
journalId: { type: "string", minLength: 1 },
|
|
2504
|
+
pageId: { type: "string", minLength: 1 },
|
|
2505
|
+
...dryRunProperty
|
|
2506
|
+
},
|
|
2507
|
+
additionalProperties: false
|
|
2508
|
+
},
|
|
2509
|
+
{ mutation: true }
|
|
2510
|
+
),
|
|
2410
2511
|
"journal.category.list": cmd({
|
|
2411
2512
|
type: "object",
|
|
2412
2513
|
required: ["journalId"],
|
|
@@ -3223,7 +3324,8 @@ var sceneEmbeddedCommands = {
|
|
|
3223
3324
|
properties: {
|
|
3224
3325
|
sceneId: { type: "string", minLength: 1 },
|
|
3225
3326
|
...nameFilterProperty,
|
|
3226
|
-
...paginationProperties
|
|
3327
|
+
...paginationProperties,
|
|
3328
|
+
...tokenListIncludeProperty
|
|
3227
3329
|
},
|
|
3228
3330
|
additionalProperties: false
|
|
3229
3331
|
}),
|
|
@@ -3293,6 +3395,19 @@ var sceneEmbeddedCommands = {
|
|
|
3293
3395
|
},
|
|
3294
3396
|
{ mutation: true }
|
|
3295
3397
|
),
|
|
3398
|
+
"scene.token.restore-delta": cmd(
|
|
3399
|
+
{
|
|
3400
|
+
type: "object",
|
|
3401
|
+
required: ["sceneId", "tokenId"],
|
|
3402
|
+
properties: {
|
|
3403
|
+
sceneId: { type: "string", minLength: 1 },
|
|
3404
|
+
tokenId: { type: "string", minLength: 1 },
|
|
3405
|
+
...dryRunProperty
|
|
3406
|
+
},
|
|
3407
|
+
additionalProperties: false
|
|
3408
|
+
},
|
|
3409
|
+
{ mutation: true }
|
|
3410
|
+
),
|
|
3296
3411
|
...batchWriteCommands("scene.token", {
|
|
3297
3412
|
scopeProperties: sceneScopeProperties,
|
|
3298
3413
|
createSchema: tokenCreateSchema,
|
|
@@ -5356,6 +5471,7 @@ var DEFAULT_COMMAND_PROFILE = deepFreeze({
|
|
|
5356
5471
|
"scene.token.update": "allow",
|
|
5357
5472
|
"scene.token.delete": "approve",
|
|
5358
5473
|
"scene.token.clone": "allow",
|
|
5474
|
+
"scene.token.restore-delta": "approve",
|
|
5359
5475
|
"scene.token.create-many": "allow",
|
|
5360
5476
|
"scene.token.update-many": "allow",
|
|
5361
5477
|
"scene.token.delete-many": "approve",
|
|
@@ -5506,6 +5622,11 @@ var DEFAULT_COMMAND_PROFILE = deepFreeze({
|
|
|
5506
5622
|
"journal.ownership.set": "allow",
|
|
5507
5623
|
"journal.update-many": "allow",
|
|
5508
5624
|
"journal.delete-many": "approve",
|
|
5625
|
+
"journal.page.list": "allow",
|
|
5626
|
+
"journal.page.get": "allow",
|
|
5627
|
+
"journal.page.create": "allow",
|
|
5628
|
+
"journal.page.update": "allow",
|
|
5629
|
+
"journal.page.delete": "approve",
|
|
5509
5630
|
"journal.category.list": "allow",
|
|
5510
5631
|
"journal.category.get": "allow",
|
|
5511
5632
|
"journal.category.create": "allow",
|
|
@@ -5622,6 +5743,9 @@ var DEFAULT_COMMAND_PROFILE = deepFreeze({
|
|
|
5622
5743
|
"actor.item.delete": "approve",
|
|
5623
5744
|
"actor.item.clone": "allow",
|
|
5624
5745
|
"actor.item.import-from-compendium": "allow",
|
|
5746
|
+
"actor.item.create-many": "allow",
|
|
5747
|
+
"actor.item.update-many": "allow",
|
|
5748
|
+
"actor.item.delete-many": "approve",
|
|
5625
5749
|
"actor.update-many": "allow",
|
|
5626
5750
|
"actor.delete-many": "approve",
|
|
5627
5751
|
"actor.effect.list": "allow",
|
|
@@ -5653,6 +5777,7 @@ var DEFAULT_COMMAND_PROFILE = deepFreeze({
|
|
|
5653
5777
|
"compendium.list": "allow",
|
|
5654
5778
|
"compendium.index": "allow",
|
|
5655
5779
|
"compendium.get": "allow",
|
|
5780
|
+
"compendium.get-many": "allow",
|
|
5656
5781
|
"folder.list": "allow",
|
|
5657
5782
|
"folder.get": "allow",
|
|
5658
5783
|
"folder.create": "allow",
|
|
@@ -5674,6 +5799,7 @@ var DEFAULT_COMMAND_PROFILE = deepFreeze({
|
|
|
5674
5799
|
"setting.set-many": "deny",
|
|
5675
5800
|
"actor.import-from-compendium": "allow",
|
|
5676
5801
|
"world.audit-files": "allow",
|
|
5802
|
+
"world.references": "allow",
|
|
5677
5803
|
"world.search": "allow",
|
|
5678
5804
|
"approval.await": "allow",
|
|
5679
5805
|
"approval.cancel": "allow",
|
|
@@ -5682,7 +5808,12 @@ var DEFAULT_COMMAND_PROFILE = deepFreeze({
|
|
|
5682
5808
|
|
|
5683
5809
|
// ../protocol/src/command-risk.js
|
|
5684
5810
|
var DESTRUCTIVE_VERBS = Object.freeze(["delete", "delete-many"]);
|
|
5685
|
-
var DESTRUCTIVE_COMMANDS = Object.freeze([
|
|
5811
|
+
var DESTRUCTIVE_COMMANDS = Object.freeze([
|
|
5812
|
+
"chat.flush",
|
|
5813
|
+
"file.move",
|
|
5814
|
+
"scene.fog.reset",
|
|
5815
|
+
"scene.token.restore-delta"
|
|
5816
|
+
]);
|
|
5686
5817
|
var APPROVE_EXTRA_COMMANDS = Object.freeze(["system.reload", "user.create"]);
|
|
5687
5818
|
var DENIED_BY_DEFAULT_COMMANDS = Object.freeze([
|
|
5688
5819
|
"macro.execute",
|
|
@@ -5747,6 +5878,17 @@ function editDistance(a, b) {
|
|
|
5747
5878
|
}
|
|
5748
5879
|
return previous[cols - 1];
|
|
5749
5880
|
}
|
|
5881
|
+
function childPath(path, key) {
|
|
5882
|
+
return key.includes(".") ? `${path}[${JSON.stringify(key)}]` : `${path}.${key}`;
|
|
5883
|
+
}
|
|
5884
|
+
function describeDottedKey(key, properties) {
|
|
5885
|
+
const root = key.split(".")[0];
|
|
5886
|
+
if (!key.includes(".") || !Object.hasOwn(properties, root)) {
|
|
5887
|
+
return "";
|
|
5888
|
+
}
|
|
5889
|
+
const nested = key.split(".").reduceRight((inner, segment) => `{${JSON.stringify(segment)}: ${inner}}`, "...");
|
|
5890
|
+
return `; a key at this level must be one of the listed field names, so nest the rest of the path inside "${root}": ${nested}`;
|
|
5891
|
+
}
|
|
5750
5892
|
function describeAllowedFields(key, allowedFields) {
|
|
5751
5893
|
if (allowedFields.length === 0) {
|
|
5752
5894
|
return "";
|
|
@@ -5796,7 +5938,7 @@ function validateObjectSchema(schema, value, path, errors) {
|
|
|
5796
5938
|
const additionalProperties = schema.additionalProperties ?? true;
|
|
5797
5939
|
for (const key of required) {
|
|
5798
5940
|
if (!Object.hasOwn(value, key)) {
|
|
5799
|
-
errors.push(`${path
|
|
5941
|
+
errors.push(`${childPath(path, key)} is required`);
|
|
5800
5942
|
}
|
|
5801
5943
|
}
|
|
5802
5944
|
const ownKeys = Object.keys(value);
|
|
@@ -5808,25 +5950,27 @@ function validateObjectSchema(schema, value, path, errors) {
|
|
|
5808
5950
|
for (const key of ownKeys) {
|
|
5809
5951
|
if (namePattern === null) {
|
|
5810
5952
|
errors.push(
|
|
5811
|
-
`${path
|
|
5953
|
+
`${childPath(path, key)} cannot be validated: ${schema.propertyNames.pattern} is not a valid unicode-mode pattern`
|
|
5812
5954
|
);
|
|
5813
5955
|
} else if (!namePattern.test(key)) {
|
|
5814
|
-
errors.push(`${path
|
|
5956
|
+
errors.push(`${childPath(path, key)} is not an allowed property name`);
|
|
5815
5957
|
}
|
|
5816
5958
|
}
|
|
5817
5959
|
}
|
|
5818
5960
|
for (const [key, propertyValue] of Object.entries(value)) {
|
|
5819
5961
|
const propertySchema = properties[key];
|
|
5820
5962
|
if (propertySchema) {
|
|
5821
|
-
validateSchema(propertySchema, propertyValue,
|
|
5963
|
+
validateSchema(propertySchema, propertyValue, childPath(path, key), errors);
|
|
5822
5964
|
continue;
|
|
5823
5965
|
}
|
|
5824
5966
|
if (additionalProperties === false) {
|
|
5825
|
-
errors.push(
|
|
5967
|
+
errors.push(
|
|
5968
|
+
`${childPath(path, key)} is not allowed${describeAllowedFields(key, Object.keys(properties))}` + describeDottedKey(key, properties)
|
|
5969
|
+
);
|
|
5826
5970
|
continue;
|
|
5827
5971
|
}
|
|
5828
5972
|
if (isPlainObject(additionalProperties)) {
|
|
5829
|
-
validateSchema(additionalProperties, propertyValue,
|
|
5973
|
+
validateSchema(additionalProperties, propertyValue, childPath(path, key), errors);
|
|
5830
5974
|
}
|
|
5831
5975
|
}
|
|
5832
5976
|
}
|
|
@@ -8833,7 +8977,10 @@ function parseActorIncludeFields(value) {
|
|
|
8833
8977
|
]);
|
|
8834
8978
|
}
|
|
8835
8979
|
function parseTokenIncludeFields(value) {
|
|
8836
|
-
return parseAllowedIncludeFields(value, ["prepared"]);
|
|
8980
|
+
return parseAllowedIncludeFields(value, ["prepared", "delta"]);
|
|
8981
|
+
}
|
|
8982
|
+
function parseTokenListIncludeFields(value) {
|
|
8983
|
+
return parseAllowedIncludeFields(value, ["delta"]);
|
|
8837
8984
|
}
|
|
8838
8985
|
function parseSystemInfoIncludeFields(value) {
|
|
8839
8986
|
return parseAllowedIncludeFields(value, ["modules"]);
|
|
@@ -8990,7 +9137,10 @@ function createSceneCreateParams(options) {
|
|
|
8990
9137
|
function createSceneCloneParams(options) {
|
|
8991
9138
|
return {
|
|
8992
9139
|
sceneId: options.sceneId,
|
|
8993
|
-
...optionalPatch(
|
|
9140
|
+
...optionalPatch({
|
|
9141
|
+
...buildScenePatch(options),
|
|
9142
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9143
|
+
})
|
|
8994
9144
|
};
|
|
8995
9145
|
}
|
|
8996
9146
|
function createItemCloneParams(options) {
|
|
@@ -8999,7 +9149,8 @@ function createItemCloneParams(options) {
|
|
|
8999
9149
|
...stringField("img", options.img),
|
|
9000
9150
|
...folderField(options),
|
|
9001
9151
|
...numberField("sort", options.sort),
|
|
9002
|
-
...jsonObjectField("system", options.systemJson, "--system-json")
|
|
9152
|
+
...jsonObjectField("system", options.systemJson, "--system-json"),
|
|
9153
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9003
9154
|
};
|
|
9004
9155
|
return {
|
|
9005
9156
|
itemId: options.itemId,
|
|
@@ -9010,7 +9161,8 @@ function createJournalCloneParams(options) {
|
|
|
9010
9161
|
const patch = {
|
|
9011
9162
|
...stringField("name", options.name),
|
|
9012
9163
|
...folderField(options),
|
|
9013
|
-
...numberField("sort", options.sort)
|
|
9164
|
+
...numberField("sort", options.sort),
|
|
9165
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9014
9166
|
};
|
|
9015
9167
|
return {
|
|
9016
9168
|
journalId: options.journalId,
|
|
@@ -9096,7 +9248,8 @@ function createMacroCloneParams(options) {
|
|
|
9096
9248
|
...stringField("command", options.command),
|
|
9097
9249
|
...stringField("img", options.img),
|
|
9098
9250
|
...folderField(options),
|
|
9099
|
-
...stringField("scope", options.scope)
|
|
9251
|
+
...stringField("scope", options.scope),
|
|
9252
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9100
9253
|
};
|
|
9101
9254
|
return {
|
|
9102
9255
|
macroId: options.macroId,
|
|
@@ -9219,6 +9372,34 @@ function createJournalCategoryUpdateParams(options) {
|
|
|
9219
9372
|
})
|
|
9220
9373
|
};
|
|
9221
9374
|
}
|
|
9375
|
+
function buildJournalPageFields(options) {
|
|
9376
|
+
return {
|
|
9377
|
+
...stringField("name", options.name),
|
|
9378
|
+
...stringField("type", options.type),
|
|
9379
|
+
...numberField("sort", options.sort),
|
|
9380
|
+
...options.clearCategory ? { category: null } : stringField("category", options.category),
|
|
9381
|
+
...stringField("src", options.src)
|
|
9382
|
+
};
|
|
9383
|
+
}
|
|
9384
|
+
function createJournalPageCreateParams(options) {
|
|
9385
|
+
return {
|
|
9386
|
+
journalId: options.journalId,
|
|
9387
|
+
data: {
|
|
9388
|
+
...buildJournalPageFields(options),
|
|
9389
|
+
...optionalJsonObject(options.dataJson, "--data-json") ?? {}
|
|
9390
|
+
}
|
|
9391
|
+
};
|
|
9392
|
+
}
|
|
9393
|
+
function createJournalPageUpdateParams(options) {
|
|
9394
|
+
return {
|
|
9395
|
+
journalId: options.journalId,
|
|
9396
|
+
pageId: options.pageId,
|
|
9397
|
+
patch: assertNonEmptyPatch({
|
|
9398
|
+
...buildJournalPageFields(options),
|
|
9399
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9400
|
+
})
|
|
9401
|
+
};
|
|
9402
|
+
}
|
|
9222
9403
|
function buildTableFields(options) {
|
|
9223
9404
|
return {
|
|
9224
9405
|
...stringField("description", options.description),
|
|
@@ -9531,7 +9712,8 @@ function createActorItemCloneParams(options) {
|
|
|
9531
9712
|
...stringField("name", options.name),
|
|
9532
9713
|
...stringField("img", options.img),
|
|
9533
9714
|
...numberField("sort", options.sort),
|
|
9534
|
-
...jsonObjectField("system", options.systemJson, "--system-json")
|
|
9715
|
+
...jsonObjectField("system", options.systemJson, "--system-json"),
|
|
9716
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9535
9717
|
};
|
|
9536
9718
|
return {
|
|
9537
9719
|
actorId: options.actorId,
|
|
@@ -9610,7 +9792,10 @@ function createActorUpdateParams(options) {
|
|
|
9610
9792
|
function createActorCloneParams(options) {
|
|
9611
9793
|
return {
|
|
9612
9794
|
actorId: options.actorId,
|
|
9613
|
-
...optionalPatch(
|
|
9795
|
+
...optionalPatch({
|
|
9796
|
+
...buildActorPatch(options),
|
|
9797
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
9798
|
+
})
|
|
9614
9799
|
};
|
|
9615
9800
|
}
|
|
9616
9801
|
function createActorImportParams(options) {
|
|
@@ -10366,8 +10551,11 @@ function renderBroadcastLines(result) {
|
|
|
10366
10551
|
`dispatched: ${Boolean(result?.dispatched)} \u2014 a broadcast writes nothing, so there is no state to confirm afterwards`
|
|
10367
10552
|
];
|
|
10368
10553
|
}
|
|
10369
|
-
function
|
|
10370
|
-
return
|
|
10554
|
+
function renderProvenanceLines(document) {
|
|
10555
|
+
return [
|
|
10556
|
+
...document?.compendiumSource ? [`compendiumSource: ${document.compendiumSource}`] : [],
|
|
10557
|
+
...document?.duplicateSource ? [`duplicateSource: ${document.duplicateSource}`] : []
|
|
10558
|
+
];
|
|
10371
10559
|
}
|
|
10372
10560
|
function renderOwnershipLines(ownership) {
|
|
10373
10561
|
if (!ownership || typeof ownership !== "object") {
|
|
@@ -10479,7 +10667,7 @@ function renderItemDetails(item, prefixLines = []) {
|
|
|
10479
10667
|
if (item && Object.hasOwn(item, "effects")) {
|
|
10480
10668
|
lines.push(`effects: ${JSON.stringify(item.effects ?? [], null, 2)}`);
|
|
10481
10669
|
}
|
|
10482
|
-
lines.push(...
|
|
10670
|
+
lines.push(...renderProvenanceLines(item));
|
|
10483
10671
|
if (item && Object.hasOwn(item, "ownership")) {
|
|
10484
10672
|
lines.push(...renderOwnershipLines(item.ownership));
|
|
10485
10673
|
}
|
|
@@ -10505,7 +10693,7 @@ function renderActorDetails(actor) {
|
|
|
10505
10693
|
if (actor && Object.hasOwn(actor, "effects")) {
|
|
10506
10694
|
lines.push(`effects: ${JSON.stringify(actor.effects ?? [], null, 2)}`);
|
|
10507
10695
|
}
|
|
10508
|
-
lines.push(...
|
|
10696
|
+
lines.push(...renderProvenanceLines(actor));
|
|
10509
10697
|
if (actor && Object.hasOwn(actor, "ownership")) {
|
|
10510
10698
|
lines.push(...renderOwnershipLines(actor.ownership));
|
|
10511
10699
|
}
|
|
@@ -10551,7 +10739,7 @@ function renderCardsDetails(cards) {
|
|
|
10551
10739
|
`cards: ${rows.length}`,
|
|
10552
10740
|
...rows.map((card) => ` ${renderCardLine(card)}`)
|
|
10553
10741
|
];
|
|
10554
|
-
lines.push(...
|
|
10742
|
+
lines.push(...renderProvenanceLines(cards));
|
|
10555
10743
|
if (cards && Object.hasOwn(cards, "ownership")) {
|
|
10556
10744
|
lines.push(...renderOwnershipLines(cards.ownership));
|
|
10557
10745
|
}
|
|
@@ -11090,7 +11278,7 @@ function renderJournalDetails(journal) {
|
|
|
11090
11278
|
`sort: ${journal?.sort ?? 0}`,
|
|
11091
11279
|
`pages: ${pages.length}`
|
|
11092
11280
|
];
|
|
11093
|
-
lines.push(...
|
|
11281
|
+
lines.push(...renderProvenanceLines(journal));
|
|
11094
11282
|
if (journal && Object.hasOwn(journal, "ownership")) {
|
|
11095
11283
|
lines.push(...renderOwnershipLines(journal.ownership));
|
|
11096
11284
|
}
|
|
@@ -11102,55 +11290,7 @@ function renderJournalDetails(journal) {
|
|
|
11102
11290
|
});
|
|
11103
11291
|
}
|
|
11104
11292
|
pages.forEach((page, index) => {
|
|
11105
|
-
|
|
11106
|
-
lines.push(`page ${pageNumber}: ${page?.id ?? ""} ${page?.name ?? ""} ${page?.type ?? ""}`);
|
|
11107
|
-
const type = page?.type;
|
|
11108
|
-
if (type === "image") {
|
|
11109
|
-
if (page?.src) {
|
|
11110
|
-
lines.push(`page ${pageNumber} src: ${page.src}`);
|
|
11111
|
-
}
|
|
11112
|
-
const caption = page?.image?.caption;
|
|
11113
|
-
if (typeof caption === "string" && caption.length > 0) {
|
|
11114
|
-
const shown = caption.length > 60 ? `${caption.slice(0, 60)}\u2026` : caption;
|
|
11115
|
-
lines.push(`page ${pageNumber} caption: ${shown}`);
|
|
11116
|
-
} else {
|
|
11117
|
-
lines.push(`page ${pageNumber} caption: (none)`);
|
|
11118
|
-
}
|
|
11119
|
-
} else if (type === "video") {
|
|
11120
|
-
if (page?.src) {
|
|
11121
|
-
lines.push(`page ${pageNumber} src: ${page.src}`);
|
|
11122
|
-
}
|
|
11123
|
-
} else if (type === "pdf") {
|
|
11124
|
-
if (page?.src) {
|
|
11125
|
-
lines.push(`page ${pageNumber} src: ${page.src}`);
|
|
11126
|
-
}
|
|
11127
|
-
} else {
|
|
11128
|
-
const format = page?.text?.format;
|
|
11129
|
-
if (format === 2) {
|
|
11130
|
-
lines.push(`page ${pageNumber} format: markdown`);
|
|
11131
|
-
} else if (format === 1) {
|
|
11132
|
-
lines.push(`page ${pageNumber} format: html`);
|
|
11133
|
-
}
|
|
11134
|
-
if (page?.text?.content) {
|
|
11135
|
-
lines.push(`page ${pageNumber} text: ${page.text.content}`);
|
|
11136
|
-
}
|
|
11137
|
-
if (page?.src) {
|
|
11138
|
-
lines.push(`page ${pageNumber} src: ${page.src}`);
|
|
11139
|
-
}
|
|
11140
|
-
}
|
|
11141
|
-
const title = page?.title;
|
|
11142
|
-
if (title && (title.show === false || typeof title.level === "number" && title.level !== 1)) {
|
|
11143
|
-
const bits = [];
|
|
11144
|
-
if (title.show === false) bits.push("show=false");
|
|
11145
|
-
if (typeof title.level === "number" && title.level !== 1) bits.push(`level=${title.level}`);
|
|
11146
|
-
lines.push(`page ${pageNumber} title: ${bits.join(" ")}`);
|
|
11147
|
-
}
|
|
11148
|
-
if (page?.category) {
|
|
11149
|
-
lines.push(`page ${pageNumber} category: ${page.category}`);
|
|
11150
|
-
}
|
|
11151
|
-
if (page && Object.hasOwn(page, "ownership")) {
|
|
11152
|
-
lines.push(...renderOwnershipLines(page.ownership).map((line) => `page ${pageNumber} ${line}`));
|
|
11153
|
-
}
|
|
11293
|
+
lines.push(...renderJournalPageLines(page, `page ${index + 1}`));
|
|
11154
11294
|
});
|
|
11155
11295
|
return lines.join("\n");
|
|
11156
11296
|
}
|
|
@@ -11163,6 +11303,143 @@ function renderJournalCategoryDetails(journalId, category) {
|
|
|
11163
11303
|
`sort: ${category?.sort ?? 0}`
|
|
11164
11304
|
].join("\n");
|
|
11165
11305
|
}
|
|
11306
|
+
function renderJournalPageLines(page, label) {
|
|
11307
|
+
const lines = [];
|
|
11308
|
+
lines.push(`${label}: ${page?.id ?? ""} ${page?.name ?? ""} ${page?.type ?? ""}`);
|
|
11309
|
+
const type = page?.type;
|
|
11310
|
+
if (type === "image") {
|
|
11311
|
+
if (page?.src) {
|
|
11312
|
+
lines.push(`${label} src: ${page.src}`);
|
|
11313
|
+
}
|
|
11314
|
+
const caption = page?.image?.caption;
|
|
11315
|
+
if (typeof caption === "string" && caption.length > 0) {
|
|
11316
|
+
const shown = caption.length > 60 ? `${caption.slice(0, 60)}\u2026` : caption;
|
|
11317
|
+
lines.push(`${label} caption: ${shown}`);
|
|
11318
|
+
} else {
|
|
11319
|
+
lines.push(`${label} caption: (none)`);
|
|
11320
|
+
}
|
|
11321
|
+
} else if (type === "video") {
|
|
11322
|
+
if (page?.src) {
|
|
11323
|
+
lines.push(`${label} src: ${page.src}`);
|
|
11324
|
+
}
|
|
11325
|
+
} else if (type === "pdf") {
|
|
11326
|
+
if (page?.src) {
|
|
11327
|
+
lines.push(`${label} src: ${page.src}`);
|
|
11328
|
+
}
|
|
11329
|
+
} else {
|
|
11330
|
+
const format = page?.text?.format;
|
|
11331
|
+
if (format === 2) {
|
|
11332
|
+
lines.push(`${label} format: markdown`);
|
|
11333
|
+
} else if (format === 1) {
|
|
11334
|
+
lines.push(`${label} format: html`);
|
|
11335
|
+
}
|
|
11336
|
+
if (page?.text?.content) {
|
|
11337
|
+
lines.push(`${label} text: ${page.text.content}`);
|
|
11338
|
+
}
|
|
11339
|
+
if (page?.src) {
|
|
11340
|
+
lines.push(`${label} src: ${page.src}`);
|
|
11341
|
+
}
|
|
11342
|
+
}
|
|
11343
|
+
const title = page?.title;
|
|
11344
|
+
if (title && (title.show === false || typeof title.level === "number" && title.level !== 1)) {
|
|
11345
|
+
const bits = [];
|
|
11346
|
+
if (title.show === false) bits.push("show=false");
|
|
11347
|
+
if (typeof title.level === "number" && title.level !== 1) bits.push(`level=${title.level}`);
|
|
11348
|
+
lines.push(`${label} title: ${bits.join(" ")}`);
|
|
11349
|
+
}
|
|
11350
|
+
if (page?.category) {
|
|
11351
|
+
lines.push(`${label} category: ${page.category}`);
|
|
11352
|
+
}
|
|
11353
|
+
if (page && Object.hasOwn(page, "ownership")) {
|
|
11354
|
+
lines.push(...renderOwnershipLines(page.ownership).map((line) => `${label} ${line}`));
|
|
11355
|
+
}
|
|
11356
|
+
return lines;
|
|
11357
|
+
}
|
|
11358
|
+
function renderJournalPageDetails(journalId, page) {
|
|
11359
|
+
return [`journal: ${journalId}`, ...renderJournalPageLines(page, "page")].join("\n");
|
|
11360
|
+
}
|
|
11361
|
+
|
|
11362
|
+
// src/render/settings.ts
|
|
11363
|
+
function renderSettingSummaryLine(setting) {
|
|
11364
|
+
const label = setting?.nameLocalized && setting.nameLocalized !== setting.name ? `${setting.nameLocalized} [${setting.name}]` : setting?.nameLocalized ?? setting?.name ?? "(unnamed)";
|
|
11365
|
+
return [
|
|
11366
|
+
setting?.id ?? `${setting?.namespace ?? "?"}.${setting?.key ?? "?"}`,
|
|
11367
|
+
label,
|
|
11368
|
+
`scope=${setting?.scope ?? "?"}`,
|
|
11369
|
+
`type=${setting?.type?.kind ?? "-"}`,
|
|
11370
|
+
`config=${Boolean(setting?.config)}`,
|
|
11371
|
+
`reload=${Boolean(setting?.requiresReload)}`,
|
|
11372
|
+
...setting?.metadataReadFailed ? ["metadata=UNREADABLE"] : [],
|
|
11373
|
+
...setting?.unaddressable ? ["address=UNADDRESSABLE"] : [],
|
|
11374
|
+
...setting?.valueRedacted ? ["value=REDACTED"] : []
|
|
11375
|
+
].join(" ");
|
|
11376
|
+
}
|
|
11377
|
+
function renderSettingValue(value) {
|
|
11378
|
+
return JSON.stringify(value ?? null, null, 2);
|
|
11379
|
+
}
|
|
11380
|
+
function renderOmissionLines(label, omissions, truncated) {
|
|
11381
|
+
if (!Array.isArray(omissions) || omissions.length === 0) return [];
|
|
11382
|
+
return [
|
|
11383
|
+
`${label} incomplete: ${omissions.length}${truncated ? "+" : ""} node(s) replaced by {"$unserializable": <reason>}`,
|
|
11384
|
+
...omissions.map((omission) => ` ${omission?.path ?? "?"} ${omission?.reason ?? "?"}`)
|
|
11385
|
+
];
|
|
11386
|
+
}
|
|
11387
|
+
function renderSettingWriteLines(row, dryRun) {
|
|
11388
|
+
const verb = dryRun ? "would write" : row?.changed ? "wrote" : "left unchanged";
|
|
11389
|
+
return [
|
|
11390
|
+
`${verb}: ${row?.id ?? `${row?.namespace}.${row?.key}`} (scope: ${row?.scope ?? "?"})`,
|
|
11391
|
+
`previous: ${renderSettingValue(row?.previous)}`,
|
|
11392
|
+
...renderOmissionLines("previous", row?.previousOmissions, row?.previousOmissionsTruncated),
|
|
11393
|
+
`${dryRun ? "requested" : "value"}: ${renderSettingValue(row?.value)}`,
|
|
11394
|
+
...renderOmissionLines("value", row?.valueOmissions, row?.valueOmissionsTruncated),
|
|
11395
|
+
`changed: ${Boolean(row?.changed)} / validated: ${Boolean(row?.validated)}`,
|
|
11396
|
+
...row?.requiresReload ? ["requiresReload: true \u2014 Foundry acts on this only after `system reload` or a manual browser reload"] : ["requiresReload: false"]
|
|
11397
|
+
];
|
|
11398
|
+
}
|
|
11399
|
+
function renderSettingWriteResult(result) {
|
|
11400
|
+
return renderSettingWriteLines(result, Boolean(result?.dryRun)).join("\n");
|
|
11401
|
+
}
|
|
11402
|
+
function renderSettingWriteOutcomes(result) {
|
|
11403
|
+
const outcomes = result?.outcomes ?? [];
|
|
11404
|
+
const dryRun = Boolean(result?.dryRun);
|
|
11405
|
+
const lines = [
|
|
11406
|
+
`${dryRun ? "Would write" : "Wrote"} settings (${outcomes.length}) \u2014 complete: ${Boolean(result?.complete)}`,
|
|
11407
|
+
...outcomes.flatMap(
|
|
11408
|
+
(outcome) => outcome?.status === "updated" || outcome?.status === "unchanged" ? [
|
|
11409
|
+
`[${outcome.index}] ${outcome.status}`,
|
|
11410
|
+
...renderSettingWriteLines(outcome, dryRun).map((line) => ` ${line}`)
|
|
11411
|
+
] : [`[${outcome?.index}] ${outcome?.status} ${outcome?.id ?? ""}`]
|
|
11412
|
+
)
|
|
11413
|
+
];
|
|
11414
|
+
if (result?.failure) {
|
|
11415
|
+
lines.push(`failure: ${result.failure.code} \u2014 ${result.failure.message}`);
|
|
11416
|
+
}
|
|
11417
|
+
return lines.join("\n");
|
|
11418
|
+
}
|
|
11419
|
+
function renderSettingBatchRows(setting) {
|
|
11420
|
+
return [
|
|
11421
|
+
renderSettingSummaryLine(setting),
|
|
11422
|
+
...setting?.error ? [` error: ${setting.error.code} \u2014 ${setting.error.message}`] : [
|
|
11423
|
+
` value: ${renderSettingValue(setting?.value)}`,
|
|
11424
|
+
...renderOmissionLines("value", setting?.valueOmissions, setting?.valueOmissionsTruncated).map(
|
|
11425
|
+
(line) => ` ${line}`
|
|
11426
|
+
)
|
|
11427
|
+
]
|
|
11428
|
+
];
|
|
11429
|
+
}
|
|
11430
|
+
function renderSettingDetails(setting) {
|
|
11431
|
+
return [
|
|
11432
|
+
`setting: ${setting?.id ?? `${setting?.namespace}.${setting?.key}`}`,
|
|
11433
|
+
`name: ${setting?.nameLocalized ?? "(none)"}${setting?.name && setting.name !== setting.nameLocalized ? ` (raw: ${setting.name})` : ""}`,
|
|
11434
|
+
`hint: ${setting?.hintLocalized ?? "(none)"}${setting?.hint && setting.hint !== setting.hintLocalized ? ` (raw: ${setting.hint})` : ""}`,
|
|
11435
|
+
`scope: ${setting?.scope ?? "?"}`,
|
|
11436
|
+
`type: ${setting?.type?.kind ?? "(untyped)"}`,
|
|
11437
|
+
`config: ${Boolean(setting?.config)} / requiresReload: ${Boolean(setting?.requiresReload)}`,
|
|
11438
|
+
...setting?.metadataReadFailed ? [`metadata: UNREADABLE (${setting.metadataReadError ?? "unknown error"})`] : [],
|
|
11439
|
+
setting?.valueRedacted ? "value: null (REDACTED \u2014 authorization settings are never exposed through setting commands)" : `value: ${JSON.stringify(setting?.value ?? null, null, 2)}`,
|
|
11440
|
+
...renderOmissionLines("value", setting?.valueOmissions, setting?.valueOmissionsTruncated)
|
|
11441
|
+
].join("\n");
|
|
11442
|
+
}
|
|
11166
11443
|
|
|
11167
11444
|
// src/render/macros.ts
|
|
11168
11445
|
var CHAT_CAPTURE_NOTES = {
|
|
@@ -11185,6 +11462,9 @@ function renderMacroExecuteResult(result) {
|
|
|
11185
11462
|
`type: ${result?.type ?? "(unknown)"}`,
|
|
11186
11463
|
`returned: ${JSON.stringify(result?.returned ?? null, null, 2)}`
|
|
11187
11464
|
];
|
|
11465
|
+
lines.push(
|
|
11466
|
+
...renderOmissionLines("returned", result?.returnedOmissions, result?.returnedOmissionsTruncated)
|
|
11467
|
+
);
|
|
11188
11468
|
if (result?.returnedOmitted) {
|
|
11189
11469
|
lines.push(`returned omitted: ${result.returnedOmitted.code} \u2014 ${result.returnedOmitted.message}`);
|
|
11190
11470
|
}
|
|
@@ -11206,7 +11486,7 @@ function renderMacroDetails(macro) {
|
|
|
11206
11486
|
`flags: ${JSON.stringify(macro?.flags ?? {}, null, 2)}`,
|
|
11207
11487
|
`command: ${macro?.command ?? ""}`
|
|
11208
11488
|
];
|
|
11209
|
-
lines.push(...
|
|
11489
|
+
lines.push(...renderProvenanceLines(macro));
|
|
11210
11490
|
if (macro && Object.hasOwn(macro, "ownership")) {
|
|
11211
11491
|
lines.push(...renderOwnershipLines(macro.ownership));
|
|
11212
11492
|
}
|
|
@@ -11229,7 +11509,7 @@ function renderPlaylistDetails(playlist) {
|
|
|
11229
11509
|
`flags: ${JSON.stringify(playlist?.flags ?? {}, null, 2)}`,
|
|
11230
11510
|
`sounds: ${playlist?.sounds?.length ?? 0}`
|
|
11231
11511
|
];
|
|
11232
|
-
lines.push(...
|
|
11512
|
+
lines.push(...renderProvenanceLines(playlist));
|
|
11233
11513
|
if (playlist && Object.hasOwn(playlist, "ownership")) {
|
|
11234
11514
|
lines.push(...renderOwnershipLines(playlist.ownership));
|
|
11235
11515
|
}
|
|
@@ -11288,7 +11568,7 @@ function renderSceneDetails(scene) {
|
|
|
11288
11568
|
for (const level of Array.isArray(scene?.levels) ? scene.levels : []) {
|
|
11289
11569
|
lines.push(`level: ${renderLevelRow(level)}`);
|
|
11290
11570
|
}
|
|
11291
|
-
lines.push(...
|
|
11571
|
+
lines.push(...renderProvenanceLines(scene));
|
|
11292
11572
|
if (scene && Object.hasOwn(scene, "ownership")) {
|
|
11293
11573
|
lines.push(...renderOwnershipLines(scene.ownership));
|
|
11294
11574
|
}
|
|
@@ -11328,11 +11608,29 @@ function renderTokenDetails(sceneId, token) {
|
|
|
11328
11608
|
`disposition: ${token?.disposition ?? ""}`,
|
|
11329
11609
|
`texture: ${JSON.stringify(token?.texture ?? null)}`
|
|
11330
11610
|
];
|
|
11611
|
+
if (token && Object.hasOwn(token, "delta")) {
|
|
11612
|
+
lines.push(`delta: ${token.delta === null ? "none" : "stored (use --json for values)"}`);
|
|
11613
|
+
}
|
|
11331
11614
|
if (token && Object.hasOwn(token, "prepared")) {
|
|
11332
11615
|
lines.push(`prepared: ${Object.keys(token.prepared ?? {}).join(", ")} (use --json for values)`);
|
|
11333
11616
|
}
|
|
11334
11617
|
return lines.join("\n");
|
|
11335
11618
|
}
|
|
11619
|
+
function tokenDeltaSummaryCell(token) {
|
|
11620
|
+
if (!token || !Object.hasOwn(token, "deltaSummary")) return "";
|
|
11621
|
+
const summary = token.deltaSummary;
|
|
11622
|
+
if (summary === null) return " overrides=none";
|
|
11623
|
+
return ` overrides=${(summary.overriddenKeys ?? []).join(",")} (item entries ${summary.itemEntries}, effect entries ${summary.effectEntries})`;
|
|
11624
|
+
}
|
|
11625
|
+
function renderTokenDeltaRestore(result) {
|
|
11626
|
+
const discarded = result.discarded;
|
|
11627
|
+
const verb = result.dryRun ? "[dry-run] would discard" : "Discarded";
|
|
11628
|
+
return [
|
|
11629
|
+
`scene: ${result.sceneId}`,
|
|
11630
|
+
`token: ${result.tokenId}`,
|
|
11631
|
+
result.changed ? `${verb} token overrides: ${(discarded?.overriddenKeys ?? []).join(", ")} (item entries ${discarded?.itemEntries ?? 0}, effect entries ${discarded?.effectEntries ?? 0})` : "No token-level overrides; nothing to restore."
|
|
11632
|
+
].join("\n");
|
|
11633
|
+
}
|
|
11336
11634
|
function tokenItemPrefix(result) {
|
|
11337
11635
|
const lines = [
|
|
11338
11636
|
`scene: ${result.sceneId}`,
|
|
@@ -11520,73 +11818,6 @@ function renderRegionBehaviorDetails(sceneId, regionId, behavior) {
|
|
|
11520
11818
|
].join("\n");
|
|
11521
11819
|
}
|
|
11522
11820
|
|
|
11523
|
-
// src/render/settings.ts
|
|
11524
|
-
function renderSettingSummaryLine(setting) {
|
|
11525
|
-
const label = setting?.nameLocalized && setting.nameLocalized !== setting.name ? `${setting.nameLocalized} [${setting.name}]` : setting?.nameLocalized ?? setting?.name ?? "(unnamed)";
|
|
11526
|
-
return [
|
|
11527
|
-
setting?.id ?? `${setting?.namespace ?? "?"}.${setting?.key ?? "?"}`,
|
|
11528
|
-
label,
|
|
11529
|
-
`scope=${setting?.scope ?? "?"}`,
|
|
11530
|
-
`type=${setting?.type?.kind ?? "-"}`,
|
|
11531
|
-
`config=${Boolean(setting?.config)}`,
|
|
11532
|
-
`reload=${Boolean(setting?.requiresReload)}`,
|
|
11533
|
-
...setting?.metadataReadFailed ? ["metadata=UNREADABLE"] : [],
|
|
11534
|
-
...setting?.unaddressable ? ["address=UNADDRESSABLE"] : [],
|
|
11535
|
-
...setting?.valueRedacted ? ["value=REDACTED"] : []
|
|
11536
|
-
].join(" ");
|
|
11537
|
-
}
|
|
11538
|
-
function renderSettingValue(value) {
|
|
11539
|
-
return JSON.stringify(value ?? null, null, 2);
|
|
11540
|
-
}
|
|
11541
|
-
function renderSettingWriteLines(row, dryRun) {
|
|
11542
|
-
const verb = dryRun ? "would write" : row?.changed ? "wrote" : "left unchanged";
|
|
11543
|
-
return [
|
|
11544
|
-
`${verb}: ${row?.id ?? `${row?.namespace}.${row?.key}`} (scope: ${row?.scope ?? "?"})`,
|
|
11545
|
-
`previous: ${renderSettingValue(row?.previous)}`,
|
|
11546
|
-
`${dryRun ? "requested" : "value"}: ${renderSettingValue(row?.value)}`,
|
|
11547
|
-
`changed: ${Boolean(row?.changed)} / validated: ${Boolean(row?.validated)}`,
|
|
11548
|
-
...row?.requiresReload ? ["requiresReload: true \u2014 Foundry acts on this only after `system reload` or a manual browser reload"] : ["requiresReload: false"]
|
|
11549
|
-
];
|
|
11550
|
-
}
|
|
11551
|
-
function renderSettingWriteResult(result) {
|
|
11552
|
-
return renderSettingWriteLines(result, Boolean(result?.dryRun)).join("\n");
|
|
11553
|
-
}
|
|
11554
|
-
function renderSettingWriteOutcomes(result) {
|
|
11555
|
-
const outcomes = result?.outcomes ?? [];
|
|
11556
|
-
const dryRun = Boolean(result?.dryRun);
|
|
11557
|
-
const lines = [
|
|
11558
|
-
`${dryRun ? "Would write" : "Wrote"} settings (${outcomes.length}) \u2014 complete: ${Boolean(result?.complete)}`,
|
|
11559
|
-
...outcomes.flatMap(
|
|
11560
|
-
(outcome) => outcome?.status === "updated" || outcome?.status === "unchanged" ? [
|
|
11561
|
-
`[${outcome.index}] ${outcome.status}`,
|
|
11562
|
-
...renderSettingWriteLines(outcome, dryRun).map((line) => ` ${line}`)
|
|
11563
|
-
] : [`[${outcome?.index}] ${outcome?.status} ${outcome?.id ?? ""}`]
|
|
11564
|
-
)
|
|
11565
|
-
];
|
|
11566
|
-
if (result?.failure) {
|
|
11567
|
-
lines.push(`failure: ${result.failure.code} \u2014 ${result.failure.message}`);
|
|
11568
|
-
}
|
|
11569
|
-
return lines.join("\n");
|
|
11570
|
-
}
|
|
11571
|
-
function renderSettingBatchRows(setting) {
|
|
11572
|
-
return [
|
|
11573
|
-
renderSettingSummaryLine(setting),
|
|
11574
|
-
...setting?.error ? [` error: ${setting.error.code} \u2014 ${setting.error.message}`] : [` value: ${renderSettingValue(setting?.value)}`]
|
|
11575
|
-
];
|
|
11576
|
-
}
|
|
11577
|
-
function renderSettingDetails(setting) {
|
|
11578
|
-
return [
|
|
11579
|
-
`setting: ${setting?.id ?? `${setting?.namespace}.${setting?.key}`}`,
|
|
11580
|
-
`name: ${setting?.nameLocalized ?? "(none)"}${setting?.name && setting.name !== setting.nameLocalized ? ` (raw: ${setting.name})` : ""}`,
|
|
11581
|
-
`hint: ${setting?.hintLocalized ?? "(none)"}${setting?.hint && setting.hint !== setting.hintLocalized ? ` (raw: ${setting.hint})` : ""}`,
|
|
11582
|
-
`scope: ${setting?.scope ?? "?"}`,
|
|
11583
|
-
`type: ${setting?.type?.kind ?? "(untyped)"}`,
|
|
11584
|
-
`config: ${Boolean(setting?.config)} / requiresReload: ${Boolean(setting?.requiresReload)}`,
|
|
11585
|
-
...setting?.metadataReadFailed ? [`metadata: UNREADABLE (${setting.metadataReadError ?? "unknown error"})`] : [],
|
|
11586
|
-
setting?.valueRedacted ? "value: null (REDACTED \u2014 authorization settings are never exposed through setting commands)" : `value: ${JSON.stringify(setting?.value ?? null, null, 2)}`
|
|
11587
|
-
].join("\n");
|
|
11588
|
-
}
|
|
11589
|
-
|
|
11590
11821
|
// src/render/tables.ts
|
|
11591
11822
|
function renderTableResultLine(result, ownerColumns = []) {
|
|
11592
11823
|
const range = Array.isArray(result?.range) ? result.range.join("-") : "";
|
|
@@ -11617,7 +11848,7 @@ function renderTableDetails(table) {
|
|
|
11617
11848
|
`results: ${results.length}`,
|
|
11618
11849
|
...results.map((result) => ` ${renderTableResultLine(result)}`)
|
|
11619
11850
|
];
|
|
11620
|
-
lines.push(...
|
|
11851
|
+
lines.push(...renderProvenanceLines(table));
|
|
11621
11852
|
if (table && Object.hasOwn(table, "ownership")) {
|
|
11622
11853
|
lines.push(...renderOwnershipLines(table.ownership));
|
|
11623
11854
|
}
|
|
@@ -11892,6 +12123,28 @@ var RENDERERS = registerRenderers([
|
|
|
11892
12123
|
}
|
|
11893
12124
|
return lines.join("\n");
|
|
11894
12125
|
}),
|
|
12126
|
+
customRenderer("world.references", (result, offset) => {
|
|
12127
|
+
const references = result.references ?? [];
|
|
12128
|
+
const target = result.target ?? {};
|
|
12129
|
+
const lines = [
|
|
12130
|
+
`target: ${target.uuid ?? ""} ${humanCell(target.name)} exists=${target.exists === null ? "unknown" : String(target.exists)}`
|
|
12131
|
+
];
|
|
12132
|
+
if (references.length) {
|
|
12133
|
+
lines.push(
|
|
12134
|
+
`References (${references.length})`,
|
|
12135
|
+
...references.map(
|
|
12136
|
+
(ref) => `${ref.uuid} ${humanCell(ref.name)} ${ref.field} ${ref.match}${ref.matchedUuid ? ` ${ref.matchedUuid}` : ""}`
|
|
12137
|
+
)
|
|
12138
|
+
);
|
|
12139
|
+
} else {
|
|
12140
|
+
lines.push("No stored references found.");
|
|
12141
|
+
}
|
|
12142
|
+
lines.push(...listFooterLines(result, references.length, offset));
|
|
12143
|
+
lines.push(
|
|
12144
|
+
`summary: references=${result.total ?? references.length} scannedDocuments=${result.scannedDocuments ?? 0} selfReferences=${result.selfReferences ?? 0} scopes=${(result.scopes ?? []).join(",")}`
|
|
12145
|
+
);
|
|
12146
|
+
return lines.join("\n");
|
|
12147
|
+
}),
|
|
11895
12148
|
listRenderer("scene.list", {
|
|
11896
12149
|
key: "scenes",
|
|
11897
12150
|
empty: "No scenes found.",
|
|
@@ -12256,6 +12509,21 @@ var RENDERERS = registerRenderers([
|
|
|
12256
12509
|
}),
|
|
12257
12510
|
deleteRenderer("journal.delete", "journal"),
|
|
12258
12511
|
detailRenderer("journal.show", (result) => renderJournalShowResult(result)),
|
|
12512
|
+
listRenderer("journal.page.list", {
|
|
12513
|
+
key: "pages",
|
|
12514
|
+
empty: "No pages found.",
|
|
12515
|
+
heading: "Pages",
|
|
12516
|
+
prefix: (result) => [`journal: ${result.journalId}`],
|
|
12517
|
+
row: (page) => `${page.id} ${page.name ?? ""} ${page.type ?? ""} sort=${page.sort ?? 0}${page.textFormat === 2 ? " format=markdown" : page.textFormat === 1 ? " format=html" : ""}`
|
|
12518
|
+
}),
|
|
12519
|
+
detailRenderer(
|
|
12520
|
+
["journal.page.get", "journal.page.create", "journal.page.update"],
|
|
12521
|
+
(result) => renderJournalPageDetails(result.journalId, result.page)
|
|
12522
|
+
),
|
|
12523
|
+
detailRenderer(
|
|
12524
|
+
"journal.page.delete",
|
|
12525
|
+
(result) => result.deleted ? `Deleted journal page ${result.id} from journal ${result.journalId}` : `Would delete journal page ${result.id} from journal ${result.journalId}`
|
|
12526
|
+
),
|
|
12259
12527
|
listRenderer("journal.category.list", {
|
|
12260
12528
|
key: "categories",
|
|
12261
12529
|
empty: "No categories found.",
|
|
@@ -12407,6 +12675,17 @@ var RENDERERS = registerRenderers([
|
|
|
12407
12675
|
`document: ${JSON.stringify(result.document ?? null, null, 2)}`
|
|
12408
12676
|
].join("\n")
|
|
12409
12677
|
),
|
|
12678
|
+
customRenderer("compendium.get-many", (result) => {
|
|
12679
|
+
const entries = result.entries ?? [];
|
|
12680
|
+
return [
|
|
12681
|
+
`pack: ${result.pack}`,
|
|
12682
|
+
`Entries (${entries.length})`,
|
|
12683
|
+
...entries.map(
|
|
12684
|
+
(entry) => `${entry.entryId} ${entry.documentName ?? ""} ${entry.document?.name ?? ""}${Array.isArray(entry.effects) ? ` effects=${entry.effects.length}` : ""}`
|
|
12685
|
+
),
|
|
12686
|
+
"(use --json for the documents)"
|
|
12687
|
+
].join("\n");
|
|
12688
|
+
}),
|
|
12410
12689
|
listRenderer("folder.list", {
|
|
12411
12690
|
key: "folders",
|
|
12412
12691
|
empty: "No folders found.",
|
|
@@ -12540,13 +12819,14 @@ var RENDERERS = registerRenderers([
|
|
|
12540
12819
|
empty: "No tokens found.",
|
|
12541
12820
|
heading: "Tokens",
|
|
12542
12821
|
prefix: scenePrefix,
|
|
12543
|
-
row: (token) => `${token.id} ${token.name} actor=${token.actorId ?? "-"} linked=${String(Boolean(token.actorLink))} (${token.x},${token.y})${levelMembershipCell(token)}`
|
|
12822
|
+
row: (token) => `${token.id} ${token.name} actor=${token.actorId ?? "-"} linked=${String(Boolean(token.actorLink))} (${token.x},${token.y})${levelMembershipCell(token)}${tokenDeltaSummaryCell(token)}`
|
|
12544
12823
|
}),
|
|
12545
12824
|
detailRenderer(
|
|
12546
12825
|
["scene.token.get", "scene.token.create", "scene.token.update", "scene.token.clone"],
|
|
12547
12826
|
(result) => renderTokenDetails(result.sceneId, result.token)
|
|
12548
12827
|
),
|
|
12549
12828
|
deleteRenderer("scene.token.delete", "token", { suffix: sceneSuffix }),
|
|
12829
|
+
detailRenderer("scene.token.restore-delta", (result) => renderTokenDeltaRestore(result)),
|
|
12550
12830
|
listRenderer("scene.token.item.list", {
|
|
12551
12831
|
key: "items",
|
|
12552
12832
|
empty: "No items found.",
|
|
@@ -13384,6 +13664,28 @@ function addJournalCategoryFieldOptions(command, verb) {
|
|
|
13384
13664
|
const ordered = verb === "create" ? [JOURNAL_CATEGORY_SORT_FIELD] : [JOURNAL_CATEGORY_NAME_FIELD, JOURNAL_CATEGORY_SORT_FIELD];
|
|
13385
13665
|
return addFieldOptions(command, verb, ordered);
|
|
13386
13666
|
}
|
|
13667
|
+
var JOURNAL_PAGE_FIELDS = [
|
|
13668
|
+
{
|
|
13669
|
+
flag: "--sort <sort>",
|
|
13670
|
+
help: { create: "Page sort value", update: "New page sort value" },
|
|
13671
|
+
parser: parseNumber
|
|
13672
|
+
},
|
|
13673
|
+
{
|
|
13674
|
+
flag: "--category <categoryId>",
|
|
13675
|
+
help: {
|
|
13676
|
+
create: "Category id from journal category list",
|
|
13677
|
+
update: "New category id from journal category list"
|
|
13678
|
+
}
|
|
13679
|
+
},
|
|
13680
|
+
{ flag: "--clear-category", help: "Explicitly set category to null", conflicts: "category" },
|
|
13681
|
+
{
|
|
13682
|
+
flag: "--src <src>",
|
|
13683
|
+
help: { create: "Media path of an image, pdf or video page", update: "New media path" }
|
|
13684
|
+
}
|
|
13685
|
+
];
|
|
13686
|
+
function addJournalPageFieldOptions(command, verb) {
|
|
13687
|
+
return addFieldOptions(command, verb, JOURNAL_PAGE_FIELDS);
|
|
13688
|
+
}
|
|
13387
13689
|
var PLAYLIST_FIELDS = [
|
|
13388
13690
|
{
|
|
13389
13691
|
flag: "--description <description>",
|
|
@@ -14248,7 +14550,7 @@ function registerActor({ program, dependencies }) {
|
|
|
14248
14550
|
addActorFieldOptions(
|
|
14249
14551
|
addIdempotencyKeyOption(actor.command("clone")).requiredOption("--actor-id <actorId>", "Source actor id").option("--name <name>", "Name override for the clone"),
|
|
14250
14552
|
"clone"
|
|
14251
|
-
).action(async function cloneActorCommand(options) {
|
|
14553
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneActorCommand(options) {
|
|
14252
14554
|
await executeRemoteCommand({
|
|
14253
14555
|
commandName: "actor.clone",
|
|
14254
14556
|
params: createActorCloneParams(options),
|
|
@@ -14273,6 +14575,12 @@ function registerActor({ program, dependencies }) {
|
|
|
14273
14575
|
});
|
|
14274
14576
|
});
|
|
14275
14577
|
const actorItem = actor.command("item").description("Foundry actor embedded item commands");
|
|
14578
|
+
registerBatchWriteCommands(actorItem, {
|
|
14579
|
+
prefix: "actor.item",
|
|
14580
|
+
noun: "item",
|
|
14581
|
+
scope: "actor",
|
|
14582
|
+
dataHelp: "Item data as a JSON ARRAY of objects; each element takes what `actor item create --data-json` takes plus name and type"
|
|
14583
|
+
});
|
|
14276
14584
|
addNameFilterOption(
|
|
14277
14585
|
addPaginationOptions(actorItem.command("list").requiredOption("--actor-id <actorId>", "Actor id")).option(
|
|
14278
14586
|
"--include <fields>",
|
|
@@ -14338,7 +14646,7 @@ function registerActor({ program, dependencies }) {
|
|
|
14338
14646
|
addEmbeddedItemFieldOptions(
|
|
14339
14647
|
addIdempotencyKeyOption(actorItem.command("clone")).requiredOption("--actor-id <actorId>", "Actor id").requiredOption("--item-id <itemId>", "Source item id").option("--name <name>", "Name override for the clone"),
|
|
14340
14648
|
"clone"
|
|
14341
|
-
).action(async function cloneActorItem(options) {
|
|
14649
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneActorItem(options) {
|
|
14342
14650
|
await executeRemoteCommand({
|
|
14343
14651
|
commandName: "actor.item.clone",
|
|
14344
14652
|
params: createActorItemCloneParams(options),
|
|
@@ -14996,7 +15304,7 @@ function registerBridge({ program, dependencies }) {
|
|
|
14996
15304
|
});
|
|
14997
15305
|
bridge.command("serve").description("Start the local bridge daemon").option("--request-timeout-ms <ms>", "Response timeout for forwarded Foundry requests", parsePositiveInt).option(
|
|
14998
15306
|
"--upload-limit-bytes <size>",
|
|
14999
|
-
"Override the file.upload size limit as bytes or a size like 100MiB (max 512MiB)"
|
|
15307
|
+
"Override the file.upload and file.read size limit for this run, as bytes or a size like 100MiB (max 512MiB)"
|
|
15000
15308
|
).action(async function serveBridge(options) {
|
|
15001
15309
|
const bridgeConfig = getBridgeDaemonConfig(this, options, dependencies);
|
|
15002
15310
|
const flagUploadLimitBytes = typeof options.uploadLimitBytes === "string" ? parseUploadLimitBytes(options.uploadLimitBytes) : void 0;
|
|
@@ -15684,11 +15992,18 @@ function registerCombat({ program, dependencies }) {
|
|
|
15684
15992
|
}
|
|
15685
15993
|
|
|
15686
15994
|
// src/commands/compendium.ts
|
|
15995
|
+
function addCompendiumIncludeOption(command) {
|
|
15996
|
+
return command.option(
|
|
15997
|
+
"--include <fields>",
|
|
15998
|
+
"Comma-separated extra fields to include (allowed: effects)",
|
|
15999
|
+
parseCompendiumIncludeFields
|
|
16000
|
+
);
|
|
16001
|
+
}
|
|
15687
16002
|
function registerCompendium({ program, dependencies }) {
|
|
15688
16003
|
const compendium = program.command("compendium").description("Foundry compendium pack commands (read)");
|
|
15689
16004
|
compendium.addHelpText(
|
|
15690
16005
|
"after",
|
|
15691
|
-
"\nResult key (--json): .result.packs[] (list), .result.entries[] (index), .result.document (get \u2014 Foundry's raw source object)."
|
|
16006
|
+
"\nResult key (--json): .result.packs[] (list), .result.entries[] (index), .result.document (get \u2014 Foundry's raw source object plus id, compendiumSource and duplicateSource), .result.entries[] (get-many \u2014 one get result per requested id, in request order)."
|
|
15692
16007
|
);
|
|
15693
16008
|
addPaginationOptions(compendium.command("list")).action(async function listCompendiums(options) {
|
|
15694
16009
|
await executeRemoteCommand({
|
|
@@ -15718,10 +16033,8 @@ function registerCompendium({ program, dependencies }) {
|
|
|
15718
16033
|
dependencies
|
|
15719
16034
|
});
|
|
15720
16035
|
});
|
|
15721
|
-
|
|
15722
|
-
"--
|
|
15723
|
-
"Comma-separated extra fields to include (allowed: effects)",
|
|
15724
|
-
parseCompendiumIncludeFields
|
|
16036
|
+
addCompendiumIncludeOption(
|
|
16037
|
+
compendium.command("get").requiredOption("--pack <pack>", "Compendium pack id").requiredOption("--entry-id <entryId>", "Compendium entry id")
|
|
15725
16038
|
).action(async function getCompendiumEntry(options) {
|
|
15726
16039
|
await executeRemoteCommand({
|
|
15727
16040
|
commandName: "compendium.get",
|
|
@@ -15734,6 +16047,20 @@ function registerCompendium({ program, dependencies }) {
|
|
|
15734
16047
|
dependencies
|
|
15735
16048
|
});
|
|
15736
16049
|
});
|
|
16050
|
+
addCompendiumIncludeOption(
|
|
16051
|
+
compendium.command("get-many").description("Read several entries of one compendium pack in a single call").requiredOption("--pack <pack>", "Compendium pack id").requiredOption("--ids <list>", "Comma-separated entry ids (atomic: all must exist)", parseIdList)
|
|
16052
|
+
).action(async function getManyCompendiumEntries(options) {
|
|
16053
|
+
await executeRemoteCommand({
|
|
16054
|
+
commandName: "compendium.get-many",
|
|
16055
|
+
params: {
|
|
16056
|
+
pack: options.pack,
|
|
16057
|
+
ids: options.ids,
|
|
16058
|
+
...options.include ? { include: options.include } : {}
|
|
16059
|
+
},
|
|
16060
|
+
command: this,
|
|
16061
|
+
dependencies
|
|
16062
|
+
});
|
|
16063
|
+
});
|
|
15737
16064
|
}
|
|
15738
16065
|
|
|
15739
16066
|
// src/commands/config.ts
|
|
@@ -15756,7 +16083,9 @@ function registerConfig({ program, dependencies }) {
|
|
|
15756
16083
|
write(dependencies.stdout, `${renderConfigGetHumanOutput(configPath, displayConfig)}
|
|
15757
16084
|
`);
|
|
15758
16085
|
});
|
|
15759
|
-
config.command("set-upload-limit").description(
|
|
16086
|
+
config.command("set-upload-limit").description(
|
|
16087
|
+
"Persist the file.upload and file.read size limit (raw bytes, pre-base64) for the daemon and CLI"
|
|
16088
|
+
).argument("<size>", "Upload size limit as bytes or a size like 100MiB (max 512MiB)").action(function setUploadLimit(size) {
|
|
15760
16089
|
const uploadLimitBytes = parseUploadLimitBytes(size);
|
|
15761
16090
|
writeCliConfigUpdate(dependencies.configStore, { uploadLimitBytes });
|
|
15762
16091
|
const payload = {
|
|
@@ -16027,8 +16356,13 @@ function registerFile({ program, dependencies }) {
|
|
|
16027
16356
|
dependencies
|
|
16028
16357
|
});
|
|
16029
16358
|
});
|
|
16030
|
-
file.command("read").
|
|
16359
|
+
file.command("read").description(
|
|
16360
|
+
`Read a file's content; a file over the upload limit (system info: limits.uploadBytes) or about ${Math.floor(READ_ENCODING_CEILING_BYTES / (1024 * 1024))} MiB returns PAYLOAD_TOO_LARGE`
|
|
16361
|
+
).requiredOption("--path <path>", "Data-relative file path").addOption(
|
|
16031
16362
|
new Option7("--encoding <encoding>", "Read encoding").choices(["text", "base64"]).makeOptionMandatory()
|
|
16363
|
+
).addHelpText(
|
|
16364
|
+
"after",
|
|
16365
|
+
"\nThe CLI's receive limit follows the persisted limit (config set-upload-limit), not bridge serve --upload-limit-bytes; a larger response closes this command's connection.\nText escapes control bytes in JSON; read a binary file as base64."
|
|
16032
16366
|
).action(async function readFileCommand(options) {
|
|
16033
16367
|
await executeRemoteCommand({
|
|
16034
16368
|
commandName: "file.read",
|
|
@@ -16303,7 +16637,7 @@ function registerItem({ program, dependencies }) {
|
|
|
16303
16637
|
addItemFieldOptions(
|
|
16304
16638
|
addIdempotencyKeyOption(item.command("clone")).requiredOption("--item-id <itemId>", "Source item id").option("--name <name>", "Name override for the clone"),
|
|
16305
16639
|
"clone"
|
|
16306
|
-
).action(async function cloneItem(options) {
|
|
16640
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneItem(options) {
|
|
16307
16641
|
await executeRemoteCommand({
|
|
16308
16642
|
commandName: "item.clone",
|
|
16309
16643
|
params: createItemCloneParams(options),
|
|
@@ -16474,7 +16808,7 @@ function registerJournal({ program, dependencies }) {
|
|
|
16474
16808
|
addJournalFieldOptions(
|
|
16475
16809
|
addIdempotencyKeyOption(journal.command("clone")).requiredOption("--journal-id <journalId>", "Source journal id").option("--name <name>", "Name override for the clone"),
|
|
16476
16810
|
"clone"
|
|
16477
|
-
).action(async function cloneJournal(options) {
|
|
16811
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneJournal(options) {
|
|
16478
16812
|
await executeRemoteCommand({
|
|
16479
16813
|
commandName: "journal.clone",
|
|
16480
16814
|
params: createJournalCloneParams(options),
|
|
@@ -16490,6 +16824,64 @@ function registerJournal({ program, dependencies }) {
|
|
|
16490
16824
|
dependencies
|
|
16491
16825
|
});
|
|
16492
16826
|
});
|
|
16827
|
+
const journalPage = journal.command("page").description("Journal-embedded page commands (one page at a time; journal update batches several)");
|
|
16828
|
+
journalPage.addHelpText(
|
|
16829
|
+
"after",
|
|
16830
|
+
`
|
|
16831
|
+
Result key (--json): .result.page (get and writes) / .result.pages[] (list), with .result.journalId.
|
|
16832
|
+
list returns summaries without text, system or flags, with textFormat (1 HTML, 2 Markdown, null on media pages); get returns the full page.
|
|
16833
|
+
Text fields belong to text pages, src to image, pdf and video pages, image.caption to image pages (schema journal.page.create).
|
|
16834
|
+
Text content goes through --data-json/--patch-json, e.g. --patch-json '{"text":{"content":"<p>\u2026</p>"}}'.
|
|
16835
|
+
Page ownership: journal ownership set --journal-id <id> --page-id <pageId>.`
|
|
16836
|
+
);
|
|
16837
|
+
addNameFilterOption(
|
|
16838
|
+
addPaginationOptions(journalPage.command("list").requiredOption("--journal-id <journalId>", "Journal id"))
|
|
16839
|
+
).action(async function listJournalPages(options) {
|
|
16840
|
+
await executeRemoteCommand({
|
|
16841
|
+
commandName: "journal.page.list",
|
|
16842
|
+
params: { journalId: options.journalId, ...nameFilterParams(options), ...paginationParams(options) },
|
|
16843
|
+
command: this,
|
|
16844
|
+
dependencies
|
|
16845
|
+
});
|
|
16846
|
+
});
|
|
16847
|
+
journalPage.command("get").requiredOption("--journal-id <journalId>", "Journal id").requiredOption("--page-id <pageId>", "Page id").action(async function getJournalPage(options) {
|
|
16848
|
+
await executeRemoteCommand({
|
|
16849
|
+
commandName: "journal.page.get",
|
|
16850
|
+
params: { journalId: options.journalId, pageId: options.pageId },
|
|
16851
|
+
command: this,
|
|
16852
|
+
dependencies
|
|
16853
|
+
});
|
|
16854
|
+
});
|
|
16855
|
+
addJournalPageFieldOptions(
|
|
16856
|
+
addIdempotencyKeyOption(journalPage.command("create")).requiredOption("--journal-id <journalId>", "Journal id").requiredOption("--name <name>", "Page name").requiredOption("--type <type>", "Page type (text, image, pdf, video, or a system page type)"),
|
|
16857
|
+
"create"
|
|
16858
|
+
).option("--data-json <json>", "Full/extra page data as a JSON object (merged last)").action(async function createJournalPage(options) {
|
|
16859
|
+
await executeRemoteCommand({
|
|
16860
|
+
commandName: "journal.page.create",
|
|
16861
|
+
params: createJournalPageCreateParams(options),
|
|
16862
|
+
command: this,
|
|
16863
|
+
dependencies
|
|
16864
|
+
});
|
|
16865
|
+
});
|
|
16866
|
+
addJournalPageFieldOptions(
|
|
16867
|
+
journalPage.command("update").requiredOption("--journal-id <journalId>", "Journal id").requiredOption("--page-id <pageId>", "Page id").option("--name <name>", "New page name").option("--type <type>", "New page type"),
|
|
16868
|
+
"update"
|
|
16869
|
+
).option("--patch-json <json>", "Full/extra page patch as a JSON object (merged last)").action(async function updateJournalPage(options) {
|
|
16870
|
+
await executeRemoteCommand({
|
|
16871
|
+
commandName: "journal.page.update",
|
|
16872
|
+
params: createJournalPageUpdateParams(options),
|
|
16873
|
+
command: this,
|
|
16874
|
+
dependencies
|
|
16875
|
+
});
|
|
16876
|
+
});
|
|
16877
|
+
journalPage.command("delete").requiredOption("--journal-id <journalId>", "Journal id").requiredOption("--page-id <pageId>", "Page id").action(async function deleteJournalPage(options) {
|
|
16878
|
+
await executeRemoteCommand({
|
|
16879
|
+
commandName: "journal.page.delete",
|
|
16880
|
+
params: { journalId: options.journalId, pageId: options.pageId },
|
|
16881
|
+
command: this,
|
|
16882
|
+
dependencies
|
|
16883
|
+
});
|
|
16884
|
+
});
|
|
16493
16885
|
const journalCategory = journal.command("category").description("Journal-embedded category commands (labels pages are grouped under)");
|
|
16494
16886
|
journalCategory.addHelpText(
|
|
16495
16887
|
"after",
|
|
@@ -16647,7 +17039,7 @@ function registerMacro({ program, dependencies }) {
|
|
|
16647
17039
|
addMacroFieldOptions(
|
|
16648
17040
|
addIdempotencyKeyOption(macro.command("clone")).requiredOption("--macro-id <macroId>", "Source macro id").option("--name <name>", "Name override for the clone"),
|
|
16649
17041
|
"clone"
|
|
16650
|
-
).action(async function cloneMacroCommand(options) {
|
|
17042
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneMacroCommand(options) {
|
|
16651
17043
|
const command = await resolveMacroCommandBody(options, dependencies);
|
|
16652
17044
|
await executeRemoteCommand({
|
|
16653
17045
|
commandName: "macro.clone",
|
|
@@ -16669,6 +17061,10 @@ function registerMacro({ program, dependencies }) {
|
|
|
16669
17061
|
"--macro-timeout-ms <ms>",
|
|
16670
17062
|
`How long the GM client waits for the macro, in ms (default ${MACRO_EXECUTE_TIMEOUT_DEFAULT_MS}, max ${MACRO_EXECUTE_TIMEOUT_MAX_MS}). Raise the global --timeout-ms above it, or the CLI stops waiting before MACRO_TIMEOUT can be reported.`
|
|
16671
17063
|
).argParser(parsePositiveInt)
|
|
17064
|
+
).addHelpText(
|
|
17065
|
+
"after",
|
|
17066
|
+
`
|
|
17067
|
+
A return value node with no JSON form (a function, an own accessor, a circular reference) comes back as {"$unserializable": "<reason>"} and is listed in .result.returnedOmissions (at most ${SERIALIZE_OMISSIONS_MAX} entries); a return value over the size limits is dropped and explained in .result.returnedOmitted.`
|
|
16672
17068
|
).action(async function executeMacroCommand(options) {
|
|
16673
17069
|
await executeRemoteCommand({
|
|
16674
17070
|
commandName: "macro.execute",
|
|
@@ -16954,7 +17350,7 @@ function registerScene({ program, dependencies }) {
|
|
|
16954
17350
|
addSceneFieldOptions(
|
|
16955
17351
|
addIdempotencyKeyOption(scene.command("clone")).requiredOption("--scene-id <sceneId>", "Source scene id").option("--name <name>", "Name override for the clone"),
|
|
16956
17352
|
"clone"
|
|
16957
|
-
).action(async function cloneScene(options) {
|
|
17353
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneScene(options) {
|
|
16958
17354
|
await executeRemoteCommand({
|
|
16959
17355
|
commandName: "scene.clone",
|
|
16960
17356
|
params: createSceneCloneParams(options),
|
|
@@ -17028,17 +17424,29 @@ function registerScene({ program, dependencies }) {
|
|
|
17028
17424
|
const sceneToken = scene.command("token").description("Scene-embedded token commands");
|
|
17029
17425
|
addNameFilterOption(
|
|
17030
17426
|
addPaginationOptions(sceneToken.command("list").requiredOption("--scene-id <sceneId>", "Scene id"))
|
|
17427
|
+
).option(
|
|
17428
|
+
"--include <fields>",
|
|
17429
|
+
"Comma-separated extra fields to include (allowed: delta \u2014 a derived per-token summary of the token-level overrides, null when there are none)",
|
|
17430
|
+
parseTokenListIncludeFields
|
|
17431
|
+
).addHelpText(
|
|
17432
|
+
"after",
|
|
17433
|
+
"\nThe tokens of one actor across all scenes: world references --uuid Actor.<actorId> --scope scene"
|
|
17031
17434
|
).action(async function listSceneTokens(options) {
|
|
17032
17435
|
await executeRemoteCommand({
|
|
17033
17436
|
commandName: "scene.token.list",
|
|
17034
|
-
params: {
|
|
17437
|
+
params: {
|
|
17438
|
+
sceneId: options.sceneId,
|
|
17439
|
+
...nameFilterParams(options),
|
|
17440
|
+
...paginationParams(options),
|
|
17441
|
+
...options.include ? { include: options.include } : {}
|
|
17442
|
+
},
|
|
17035
17443
|
command: this,
|
|
17036
17444
|
dependencies
|
|
17037
17445
|
});
|
|
17038
17446
|
});
|
|
17039
17447
|
sceneToken.command("get").requiredOption("--scene-id <sceneId>", "Scene id").requiredOption("--token-id <tokenId>", "Token id").option(
|
|
17040
17448
|
"--include <fields>",
|
|
17041
|
-
"Comma-separated extra fields to include (allowed: prepared)",
|
|
17449
|
+
"Comma-separated extra fields to include (allowed: prepared, delta \u2014 the stored ActorDelta source, null for a linked token or when none is stored)",
|
|
17042
17450
|
parseTokenIncludeFields
|
|
17043
17451
|
).action(async function getSceneToken(options) {
|
|
17044
17452
|
await executeRemoteCommand({
|
|
@@ -17066,7 +17474,11 @@ function registerScene({ program, dependencies }) {
|
|
|
17066
17474
|
addTokenFieldOptions(
|
|
17067
17475
|
sceneToken.command("update").requiredOption("--scene-id <sceneId>", "Scene id").requiredOption("--token-id <tokenId>", "Token id"),
|
|
17068
17476
|
"update"
|
|
17069
|
-
).option("--patch-json <json>", "Full/extra token patch as a JSON object (merged last)").
|
|
17477
|
+
).option("--patch-json <json>", "Full/extra token patch as a JSON object (merged last)").addHelpText(
|
|
17478
|
+
"after",
|
|
17479
|
+
`
|
|
17480
|
+
A patch with "delta": {"items": []} keeps the token's item overrides. scene token restore-delta drops every token override; scene token item update/delete changes single items.`
|
|
17481
|
+
).action(async function updateSceneToken(options) {
|
|
17070
17482
|
await executeRemoteCommand({
|
|
17071
17483
|
commandName: "scene.token.update",
|
|
17072
17484
|
params: createSceneTokenUpdateParams(options),
|
|
@@ -17093,6 +17505,16 @@ function registerScene({ program, dependencies }) {
|
|
|
17093
17505
|
dependencies
|
|
17094
17506
|
});
|
|
17095
17507
|
});
|
|
17508
|
+
sceneToken.command("restore-delta").description(
|
|
17509
|
+
"Discard every token-level override of an unlinked token (items, effects, system data, name, \u2026) so it follows its world actor again"
|
|
17510
|
+
).requiredOption("--scene-id <sceneId>", "Scene id").requiredOption("--token-id <tokenId>", "Unlinked token id").action(async function restoreSceneTokenDelta(options) {
|
|
17511
|
+
await executeRemoteCommand({
|
|
17512
|
+
commandName: "scene.token.restore-delta",
|
|
17513
|
+
params: { sceneId: options.sceneId, tokenId: options.tokenId },
|
|
17514
|
+
command: this,
|
|
17515
|
+
dependencies
|
|
17516
|
+
});
|
|
17517
|
+
});
|
|
17096
17518
|
registerBatchWriteCommands(sceneToken, {
|
|
17097
17519
|
prefix: "scene.token",
|
|
17098
17520
|
noun: "token",
|
|
@@ -17162,12 +17584,13 @@ function registerScene({ program, dependencies }) {
|
|
|
17162
17584
|
addEmbeddedItemFieldOptions(
|
|
17163
17585
|
addIdempotencyKeyOption(sceneTokenItem.command("clone")).requiredOption("--scene-id <sceneId>", "Scene id").requiredOption("--token-id <tokenId>", "Token id").requiredOption("--item-id <itemId>", "Source item id").option("--name <name>", "Name override for the clone"),
|
|
17164
17586
|
"clone"
|
|
17165
|
-
).action(async function cloneSceneTokenItem(options) {
|
|
17587
|
+
).option("--patch-json <json>", "Override fields for the clone as a JSON object (merged last)").action(async function cloneSceneTokenItem(options) {
|
|
17166
17588
|
const patch = {
|
|
17167
17589
|
...stringField("name", options.name),
|
|
17168
17590
|
...stringField("img", options.img),
|
|
17169
17591
|
...numberField("sort", options.sort),
|
|
17170
|
-
...jsonObjectField("system", options.systemJson, "--system-json")
|
|
17592
|
+
...jsonObjectField("system", options.systemJson, "--system-json"),
|
|
17593
|
+
...optionalJsonObject(options.patchJson, "--patch-json") ?? {}
|
|
17171
17594
|
};
|
|
17172
17595
|
await executeRemoteCommand({
|
|
17173
17596
|
commandName: "scene.token.item.clone",
|
|
@@ -18036,7 +18459,11 @@ function registerSetting({ program, dependencies }) {
|
|
|
18036
18459
|
});
|
|
18037
18460
|
}
|
|
18038
18461
|
);
|
|
18039
|
-
setting.command("get").requiredOption("--namespace <namespace>", 'Setting namespace (e.g. "core" or a module id)').requiredOption("--key <key>", "Setting key within the namespace").
|
|
18462
|
+
setting.command("get").requiredOption("--namespace <namespace>", 'Setting namespace (e.g. "core" or a module id)').requiredOption("--key <key>", "Setting key within the namespace").addHelpText(
|
|
18463
|
+
"after",
|
|
18464
|
+
`
|
|
18465
|
+
A value node with no JSON form (an accessor property, a function, a circular reference) comes back as {"$unserializable": "<reason>"} and is listed in .result.setting.valueOmissions (at most ${SERIALIZE_OMISSIONS_MAX} entries; valueOmissionsTruncated marks a longer list). Such a value is incomplete: writing it back with setting set stores the markers as data.`
|
|
18466
|
+
).action(async function getSetting(options) {
|
|
18040
18467
|
await executeRemoteCommand({
|
|
18041
18468
|
commandName: "setting.get",
|
|
18042
18469
|
params: { namespace: options.namespace, key: options.key },
|
|
@@ -18050,7 +18477,7 @@ function registerSetting({ program, dependencies }) {
|
|
|
18050
18477
|
"--ids <list>",
|
|
18051
18478
|
'Comma-separated setting ids in "namespace.key" form (e.g. core.chatBubbles,my-module.apiKey)',
|
|
18052
18479
|
parseIdList
|
|
18053
|
-
).action(async function getManySettings(options) {
|
|
18480
|
+
).addHelpText("after", "\nEach row reports omissions like setting get, in valueOmissions.").action(async function getManySettings(options) {
|
|
18054
18481
|
await executeRemoteCommand({
|
|
18055
18482
|
commandName: "setting.get-many",
|
|
18056
18483
|
params: { ids: options.ids },
|
|
@@ -18062,6 +18489,9 @@ function registerSetting({ program, dependencies }) {
|
|
|
18062
18489
|
"--value-json <json>",
|
|
18063
18490
|
'New value as a JSON literal \u2014 true, 42, "text", [..] or {..}; a quoted string stays distinct from a boolean or a number',
|
|
18064
18491
|
(value) => parseJsonValue(value, "--value-json")
|
|
18492
|
+
).addHelpText(
|
|
18493
|
+
"after",
|
|
18494
|
+
'\nprevious and value report omissions like setting get, in previousOmissions and valueOmissions. {"$unserializable": ...} markers in --value-json are stored as data.'
|
|
18065
18495
|
).action(async function setSetting(options) {
|
|
18066
18496
|
await executeRemoteCommand({
|
|
18067
18497
|
commandName: "setting.set",
|
|
@@ -18622,6 +19052,7 @@ function registerWorld({ program, dependencies }) {
|
|
|
18622
19052
|
"",
|
|
18623
19053
|
"Result key (--json): .result.broken[] (+ .result.checkedRefs / .result.checkedFiles / .result.skipped[], total/hasMore over broken) for audit-files.",
|
|
18624
19054
|
"Result key (--json): .result.results[] (+ .result.total / .result.hasMore / .result.index) for search.",
|
|
19055
|
+
"Result key (--json): .result.references[] (+ .result.target / .result.total / .result.hasMore / .result.scannedDocuments / .result.selfReferences / .result.scopes) for references.",
|
|
18625
19056
|
"",
|
|
18626
19057
|
"search: results are SECTIONED \u2014 world rows first, then pack rows, each ranked among itself.",
|
|
18627
19058
|
"`score` is comparable only WITHIN a section (the two corpora are separate indexes), so compare",
|
|
@@ -18653,6 +19084,53 @@ function registerWorld({ program, dependencies }) {
|
|
|
18653
19084
|
dependencies
|
|
18654
19085
|
});
|
|
18655
19086
|
});
|
|
19087
|
+
addPaginationOptions(
|
|
19088
|
+
world.command("references").description("Report where stored world data references a document, by its UUID").requiredOption(
|
|
19089
|
+
"--uuid <uuid>",
|
|
19090
|
+
"Target document UUID: Actor.<id>, Scene.<id>.Token.<id>, Compendium.<package>.<pack>.<Type>.<id>, \u2026"
|
|
19091
|
+
).option(
|
|
19092
|
+
"--scope <list>",
|
|
19093
|
+
`Comma-separated document families to scan: ${REFERENCE_SCOPES.join(",")} (default: ${REFERENCE_DEFAULT_SCOPES.join(",")}; chat only on request)`,
|
|
19094
|
+
parseScopeList
|
|
19095
|
+
).addHelpText(
|
|
19096
|
+
"after",
|
|
19097
|
+
[
|
|
19098
|
+
"",
|
|
19099
|
+
"Scans the stored data, flags and _stats included, of every world document in scope, its embedded",
|
|
19100
|
+
"documents, and every user. Each row names the owning document by UUID and the dotted field path in it;",
|
|
19101
|
+
"a match inside a token's delta is reported on the token (field delta.\u2026). An embedded target needs its",
|
|
19102
|
+
"full UUID (Scene.<s>.Token.<t>).",
|
|
19103
|
+
"match: uuid a field holds the target UUID",
|
|
19104
|
+
" link an @UUID[...] link or a legacy @Actor[<id>] / @Compendium[<pack>.<id>] link names the target",
|
|
19105
|
+
" embedded a field holds the UUID of a document embedded in the target (matchedUuid); deleting the",
|
|
19106
|
+
" target breaks it too",
|
|
19107
|
+
" key an object key names the target; a dotted key Foundry stored nested is reported at the",
|
|
19108
|
+
" target's id (flags.mod.Actor.<id>)",
|
|
19109
|
+
" relative a relative link (@UUID[.<id>], @Embed[.<id>]) in journal page text or a roll table or",
|
|
19110
|
+
" table result description resolves to the target or a document in it (matchedUuid)",
|
|
19111
|
+
" id a foreign-key field of the target's type (token actorId, note entryId, folder, setting user,",
|
|
19112
|
+
" chat speaker, \u2026) or a hotbar slot (hotbar.<slot>) holds the target's id; for an embedded",
|
|
19113
|
+
" target only where the record also names its parent or sits inside it, and never for a",
|
|
19114
|
+
" deeper target such as a token's actor",
|
|
19115
|
+
"setting: world and user settings, read as stored JSON (rows Setting.<id>, name = key, field value[.<path>]).",
|
|
19116
|
+
"Not found: compendium contents, client settings, bare ids outside foreign-key fields (system data, object",
|
|
19117
|
+
"keys, chat whisper lists) or in fields Foundry maintains itself (_stats.lastModifiedBy), name-based links",
|
|
19118
|
+
"(@Actor[Goblin]), relative links in other fields. References inside the target itself are counted in",
|
|
19119
|
+
"selfReferences. target.exists is null for a compendium target, whose pack is not loaded."
|
|
19120
|
+
].join("\n")
|
|
19121
|
+
)
|
|
19122
|
+
).action(async function findReferences(options) {
|
|
19123
|
+
await executeRemoteCommand({
|
|
19124
|
+
commandName: "world.references",
|
|
19125
|
+
params: {
|
|
19126
|
+
uuid: options.uuid,
|
|
19127
|
+
...options.scope ? { scope: options.scope } : {},
|
|
19128
|
+
...paginationParams(options)
|
|
19129
|
+
},
|
|
19130
|
+
command: this,
|
|
19131
|
+
dependencies
|
|
19132
|
+
});
|
|
19133
|
+
});
|
|
18656
19134
|
addPaginationOptions(
|
|
18657
19135
|
world.command("search").description("Search world (and optionally compendium) documents through the bridge index").requiredOption("--query <query>", "Search query (2-256 characters; terms are AND-combined)").addOption(
|
|
18658
19136
|
new Option15(
|