@craftrpgs/cli 0.1.4 → 0.1.6
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/bin.js +187 -9
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -26939,6 +26939,22 @@ var imageObjectSchema = exports_external.preprocess((input) => normalizeImageInp
|
|
|
26939
26939
|
variations: exports_external.array(imageVariationSchema).max(MAX_FILE_TYPE_STATES).optional()
|
|
26940
26940
|
}).strict());
|
|
26941
26941
|
|
|
26942
|
+
// ../shared/src/projects/manual.ts
|
|
26943
|
+
var MANUAL_VERSION = 1;
|
|
26944
|
+
var MAX_MANUAL_CHAPTERS = 50;
|
|
26945
|
+
var MAX_MANUAL_TITLE_LENGTH = 120;
|
|
26946
|
+
var MAX_MANUAL_CONTENT_LENGTH = 1e5;
|
|
26947
|
+
var manualChapterSchema = exports_external.object({
|
|
26948
|
+
id: exports_external.string().min(1).max(64),
|
|
26949
|
+
title: exports_external.string().trim().min(1).max(MAX_MANUAL_TITLE_LENGTH),
|
|
26950
|
+
content: exports_external.string().max(MAX_MANUAL_CONTENT_LENGTH)
|
|
26951
|
+
});
|
|
26952
|
+
var manualSchema = exports_external.object({
|
|
26953
|
+
version: exports_external.literal(MANUAL_VERSION),
|
|
26954
|
+
updatedAt: exports_external.string().max(40).optional(),
|
|
26955
|
+
chapters: exports_external.array(manualChapterSchema).max(MAX_MANUAL_CHAPTERS)
|
|
26956
|
+
});
|
|
26957
|
+
|
|
26942
26958
|
// ../shared/src/projects/project-import.ts
|
|
26943
26959
|
var projectImportJsonValueSchema = exports_external.lazy(() => exports_external.union([
|
|
26944
26960
|
exports_external.string(),
|
|
@@ -27027,7 +27043,9 @@ var projectImportProjectSettingsSchema = exports_external.object({
|
|
|
27027
27043
|
gmToolSettings: gmToolSettingsInputSchema.optional(),
|
|
27028
27044
|
rootMapFileReferenceId: exports_external.string().uuid().nullable().optional(),
|
|
27029
27045
|
gm: projectImportGameMasterSettingsSchema.optional(),
|
|
27030
|
-
preludeFlow: exports_external.unknown().nullable().optional()
|
|
27046
|
+
preludeFlow: exports_external.unknown().nullable().optional(),
|
|
27047
|
+
playerHandbook: manualSchema.nullable().optional(),
|
|
27048
|
+
builderManual: manualSchema.nullable().optional()
|
|
27031
27049
|
}).strict();
|
|
27032
27050
|
var projectImportProjectSchema = exports_external.object({
|
|
27033
27051
|
name: exports_external.string().trim().min(1),
|
|
@@ -41882,7 +41900,7 @@ function describeRemoteSource(resolved) {
|
|
|
41882
41900
|
// package.json
|
|
41883
41901
|
var package_default = {
|
|
41884
41902
|
name: "@craftrpgs/cli",
|
|
41885
|
-
version: "0.1.
|
|
41903
|
+
version: "0.1.6",
|
|
41886
41904
|
description: "Sync Craft projects with a local folder — clone, edit with any coding agent, push back.",
|
|
41887
41905
|
license: "UNLICENSED",
|
|
41888
41906
|
homepage: "https://craftrpgs.com",
|
|
@@ -43819,7 +43837,8 @@ var LEADING_SLASH_RE = /^\//;
|
|
|
43819
43837
|
var CONTENT_EXTENSION_RE = /\.(json|md)$/i;
|
|
43820
43838
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
43821
43839
|
function entryName(entry) {
|
|
43822
|
-
const
|
|
43840
|
+
const livePath = entry.movedTo ?? entry.path;
|
|
43841
|
+
const base = (livePath.split("/").at(-1) ?? livePath).replace(CONTENT_EXTENSION_RE, "");
|
|
43823
43842
|
const suffix = `.${entry.fileType}`;
|
|
43824
43843
|
return base.endsWith(suffix) ? base.slice(0, -suffix.length) : base;
|
|
43825
43844
|
}
|
|
@@ -43871,6 +43890,13 @@ function resolveLink({
|
|
|
43871
43890
|
if (bySlug) {
|
|
43872
43891
|
return fromEntry(bySlug);
|
|
43873
43892
|
}
|
|
43893
|
+
const nameKey = generateSlug(trimmed.replace(/^<@|>$/g, ""));
|
|
43894
|
+
if (nameKey) {
|
|
43895
|
+
const byName = ledger.files.find((entry) => generateSlug(entryName(entry)) === nameKey);
|
|
43896
|
+
if (byName) {
|
|
43897
|
+
return fromEntry(byName);
|
|
43898
|
+
}
|
|
43899
|
+
}
|
|
43874
43900
|
return { status: "unknown" };
|
|
43875
43901
|
}
|
|
43876
43902
|
function referenceIdToPath({
|
|
@@ -44917,6 +44943,8 @@ var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V6 = "file-designation-metadata:v6"
|
|
|
44917
44943
|
var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V7 = "file-designation-metadata:v7";
|
|
44918
44944
|
var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V8 = "file-designation-metadata:v8";
|
|
44919
44945
|
var GAME_START_OPENING_MAX_LENGTH = 1e4;
|
|
44946
|
+
var GAME_START_MAX_OPENING_BEATS = 50;
|
|
44947
|
+
var GAME_START_MAX_CHARACTER_OPENINGS = 100;
|
|
44920
44948
|
var GM_INSTRUCTION_TRIGGER_PHASES = [
|
|
44921
44949
|
"post_player_message",
|
|
44922
44950
|
"post_gm_message"
|
|
@@ -45119,10 +45147,25 @@ var GmInstructionMetadataSchema = exports_external.union([
|
|
|
45119
45147
|
GmInstructionToolMetadataSchema,
|
|
45120
45148
|
GmInstructionNarrativeMetadataSchema
|
|
45121
45149
|
]);
|
|
45150
|
+
var GameStartOpeningBeatSpeakerSchema = exports_external.discriminatedUnion("kind", [
|
|
45151
|
+
exports_external.object({ kind: exports_external.literal("gm") }),
|
|
45152
|
+
exports_external.object({
|
|
45153
|
+
kind: exports_external.literal("character"),
|
|
45154
|
+
fileReferenceId: exports_external.string().uuid(),
|
|
45155
|
+
name: exports_external.string().trim().max(200).optional()
|
|
45156
|
+
})
|
|
45157
|
+
]);
|
|
45158
|
+
var GameStartOpeningBeatSchema = exports_external.object({
|
|
45159
|
+
id: exports_external.string().uuid(),
|
|
45160
|
+
speaker: GameStartOpeningBeatSpeakerSchema,
|
|
45161
|
+
text: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH),
|
|
45162
|
+
expression: exports_external.string().trim().max(80).nullish()
|
|
45163
|
+
});
|
|
45122
45164
|
var GameStartOpeningSchema = exports_external.discriminatedUnion("kind", [
|
|
45123
45165
|
exports_external.object({
|
|
45124
45166
|
kind: exports_external.literal("static"),
|
|
45125
|
-
message: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH)
|
|
45167
|
+
message: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH),
|
|
45168
|
+
beats: exports_external.array(GameStartOpeningBeatSchema).max(GAME_START_MAX_OPENING_BEATS).optional()
|
|
45126
45169
|
}),
|
|
45127
45170
|
exports_external.object({
|
|
45128
45171
|
kind: exports_external.literal("dynamic"),
|
|
@@ -45132,16 +45175,55 @@ var GameStartOpeningSchema = exports_external.discriminatedUnion("kind", [
|
|
|
45132
45175
|
var GameStartCharacterSchema = exports_external.object({
|
|
45133
45176
|
fileReferenceId: exports_external.string().uuid()
|
|
45134
45177
|
});
|
|
45135
|
-
var
|
|
45178
|
+
var GameStartCharacterOpeningSchema = exports_external.object({
|
|
45179
|
+
characterFileReferenceId: exports_external.string().uuid(),
|
|
45180
|
+
opening: GameStartOpeningSchema
|
|
45181
|
+
});
|
|
45182
|
+
function combinedOpeningLength(opening) {
|
|
45183
|
+
if (opening.kind !== "static" || !opening.beats) {
|
|
45184
|
+
return 0;
|
|
45185
|
+
}
|
|
45186
|
+
return opening.beats.reduce((total, beat) => total + beat.text.length, 0);
|
|
45187
|
+
}
|
|
45188
|
+
var GameStartMetadataObjectSchema = exports_external.object({
|
|
45136
45189
|
startingLocationFileReferenceId: exports_external.string().uuid().nullable().optional(),
|
|
45137
45190
|
startingCharacters: exports_external.array(GameStartCharacterSchema).default([]),
|
|
45138
45191
|
opening: GameStartOpeningSchema.default({
|
|
45139
45192
|
kind: "static",
|
|
45140
45193
|
message: "Welcome to the game. What would you like to do first?"
|
|
45141
45194
|
}),
|
|
45195
|
+
characterOpenings: exports_external.array(GameStartCharacterOpeningSchema).max(GAME_START_MAX_CHARACTER_OPENINGS).default([]),
|
|
45142
45196
|
displayOrder: exports_external.number().int().default(0),
|
|
45143
45197
|
openingInstructions: exports_external.string().max(GAME_START_OPENING_MAX_LENGTH).default("")
|
|
45144
45198
|
});
|
|
45199
|
+
var GameStartMetadataSchema = GameStartMetadataObjectSchema.superRefine((metadata, ctx) => {
|
|
45200
|
+
if (combinedOpeningLength(metadata.opening) > GAME_START_OPENING_MAX_LENGTH) {
|
|
45201
|
+
ctx.addIssue({
|
|
45202
|
+
code: "custom",
|
|
45203
|
+
path: ["opening", "beats"],
|
|
45204
|
+
message: `Combined opening beats must be at most ${GAME_START_OPENING_MAX_LENGTH} characters.`
|
|
45205
|
+
});
|
|
45206
|
+
}
|
|
45207
|
+
const seenCharacterReferenceIds = new Set;
|
|
45208
|
+
metadata.characterOpenings.forEach((characterOpening, index) => {
|
|
45209
|
+
const referenceId = characterOpening.characterFileReferenceId.toLowerCase();
|
|
45210
|
+
if (seenCharacterReferenceIds.has(referenceId)) {
|
|
45211
|
+
ctx.addIssue({
|
|
45212
|
+
code: "custom",
|
|
45213
|
+
path: ["characterOpenings", index, "characterFileReferenceId"],
|
|
45214
|
+
message: "Each character can only have one opening override."
|
|
45215
|
+
});
|
|
45216
|
+
}
|
|
45217
|
+
seenCharacterReferenceIds.add(referenceId);
|
|
45218
|
+
if (combinedOpeningLength(characterOpening.opening) > GAME_START_OPENING_MAX_LENGTH) {
|
|
45219
|
+
ctx.addIssue({
|
|
45220
|
+
code: "custom",
|
|
45221
|
+
path: ["characterOpenings", index, "opening", "beats"],
|
|
45222
|
+
message: `Combined opening beats must be at most ${GAME_START_OPENING_MAX_LENGTH} characters.`
|
|
45223
|
+
});
|
|
45224
|
+
}
|
|
45225
|
+
});
|
|
45226
|
+
});
|
|
45145
45227
|
var FileDesignationMetadataV1Schema = exports_external.object({
|
|
45146
45228
|
schemaVersionId: exports_external.literal(FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V1).default(FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V1),
|
|
45147
45229
|
map: MapDataV1Schema.optional(),
|
|
@@ -45651,7 +45733,12 @@ async function runMetaGet(argv) {
|
|
|
45651
45733
|
const gameStart = parsed?.gameStart ? {
|
|
45652
45734
|
...parsed.gameStart,
|
|
45653
45735
|
startingLocation: pathForReference(workspace, parsed.gameStart.startingLocationFileReferenceId),
|
|
45654
|
-
startingCharacters: parsed.gameStart.startingCharacters.map((character) => pathForReference(workspace, character.fileReferenceId) ?? character.fileReferenceId)
|
|
45736
|
+
startingCharacters: parsed.gameStart.startingCharacters.map((character) => pathForReference(workspace, character.fileReferenceId) ?? character.fileReferenceId),
|
|
45737
|
+
opening: projectOpeningForOutput(workspace, parsed.gameStart.opening),
|
|
45738
|
+
characterOpenings: parsed.gameStart.characterOpenings.map((characterOpening) => ({
|
|
45739
|
+
character: pathForReference(workspace, characterOpening.characterFileReferenceId) ?? characterOpening.characterFileReferenceId,
|
|
45740
|
+
opening: projectOpeningForOutput(workspace, characterOpening.opening)
|
|
45741
|
+
}))
|
|
45655
45742
|
} : null;
|
|
45656
45743
|
if (gameStart) {
|
|
45657
45744
|
gameStart.startingLocationFileReferenceId = undefined;
|
|
@@ -45672,6 +45759,24 @@ async function runMetaGet(argv) {
|
|
|
45672
45759
|
});
|
|
45673
45760
|
return 0;
|
|
45674
45761
|
}
|
|
45762
|
+
function projectOpeningForOutput(workspace, opening) {
|
|
45763
|
+
if (opening.kind !== "static" || !opening.beats?.length) {
|
|
45764
|
+
return opening;
|
|
45765
|
+
}
|
|
45766
|
+
return {
|
|
45767
|
+
kind: "static",
|
|
45768
|
+
beats: opening.beats.map((beat) => ({
|
|
45769
|
+
speaker: beat.speaker.kind === "gm" ? "gm" : pathForReference(workspace, beat.speaker.fileReferenceId) ?? beat.speaker.fileReferenceId,
|
|
45770
|
+
text: beat.text,
|
|
45771
|
+
...beat.expression ? { expression: beat.expression } : {}
|
|
45772
|
+
}))
|
|
45773
|
+
};
|
|
45774
|
+
}
|
|
45775
|
+
function speakerNameForLink(link) {
|
|
45776
|
+
const base = link.split("/").filter(Boolean).at(-1);
|
|
45777
|
+
const name = base?.split(".")[0]?.trim();
|
|
45778
|
+
return name || undefined;
|
|
45779
|
+
}
|
|
45675
45780
|
function translateGameStartInput(workspace, raw) {
|
|
45676
45781
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
45677
45782
|
throw new CliError("The game start JSON must be a single object.", 2);
|
|
@@ -45693,6 +45798,55 @@ function translateGameStartInput(workspace, raw) {
|
|
|
45693
45798
|
failures.push(resolution.status === "unpushed" ? `${where}: "${link}" has not been pushed yet — push it first` : `${where}: "${link}" does not resolve to a tracked file`);
|
|
45694
45799
|
return null;
|
|
45695
45800
|
};
|
|
45801
|
+
const translateOpening = (opening, where) => {
|
|
45802
|
+
if (typeof opening !== "object" || opening === null) {
|
|
45803
|
+
return opening;
|
|
45804
|
+
}
|
|
45805
|
+
const openingInput = { ...opening };
|
|
45806
|
+
if (!Array.isArray(openingInput.beats)) {
|
|
45807
|
+
return openingInput;
|
|
45808
|
+
}
|
|
45809
|
+
const beats = openingInput.beats.map((beat, index) => {
|
|
45810
|
+
if (typeof beat !== "object" || beat === null) {
|
|
45811
|
+
return beat;
|
|
45812
|
+
}
|
|
45813
|
+
const beatInput = { ...beat };
|
|
45814
|
+
if (typeof beatInput.id !== "string") {
|
|
45815
|
+
beatInput.id = crypto.randomUUID();
|
|
45816
|
+
}
|
|
45817
|
+
const speaker = beatInput.speaker;
|
|
45818
|
+
if (typeof speaker === "string" && speaker !== "gm") {
|
|
45819
|
+
beatInput.speaker = {
|
|
45820
|
+
kind: "character",
|
|
45821
|
+
fileReferenceId: resolve6(speaker, `${where}.beats[${index}].speaker`),
|
|
45822
|
+
name: speakerNameForLink(speaker)
|
|
45823
|
+
};
|
|
45824
|
+
} else if (speaker === "gm") {
|
|
45825
|
+
beatInput.speaker = { kind: "gm" };
|
|
45826
|
+
} else if (typeof speaker === "object" && speaker !== null && "character" in speaker) {
|
|
45827
|
+
const { character, ...speakerRest } = speaker;
|
|
45828
|
+
beatInput.speaker = {
|
|
45829
|
+
kind: "character",
|
|
45830
|
+
name: typeof character === "string" ? speakerNameForLink(character) : undefined,
|
|
45831
|
+
...speakerRest,
|
|
45832
|
+
fileReferenceId: resolve6(character, `${where}.beats[${index}].speaker.character`)
|
|
45833
|
+
};
|
|
45834
|
+
}
|
|
45835
|
+
return beatInput;
|
|
45836
|
+
});
|
|
45837
|
+
openingInput.beats = beats;
|
|
45838
|
+
if (typeof openingInput.message !== "string" && openingInput.kind === "static") {
|
|
45839
|
+
const projectable = beats.filter((beat) => typeof beat === "object" && beat !== null && typeof beat.text === "string");
|
|
45840
|
+
openingInput.message = projectable.map((beat) => {
|
|
45841
|
+
const speaker = beat.speaker;
|
|
45842
|
+
const name = speaker && speaker.kind === "character" && typeof speaker.name === "string" ? speaker.name : null;
|
|
45843
|
+
return name ? `${name}: ${beat.text}` : beat.text;
|
|
45844
|
+
}).join(`
|
|
45845
|
+
|
|
45846
|
+
`).slice(0, GAME_START_OPENING_MAX_LENGTH);
|
|
45847
|
+
}
|
|
45848
|
+
return openingInput;
|
|
45849
|
+
};
|
|
45696
45850
|
if ("startingLocation" in input) {
|
|
45697
45851
|
input.startingLocationFileReferenceId = resolve6(input.startingLocation, "startingLocation");
|
|
45698
45852
|
input.startingLocation = undefined;
|
|
@@ -45707,11 +45861,28 @@ function translateGameStartInput(workspace, raw) {
|
|
|
45707
45861
|
return character;
|
|
45708
45862
|
});
|
|
45709
45863
|
}
|
|
45864
|
+
if ("opening" in input) {
|
|
45865
|
+
input.opening = translateOpening(input.opening, "opening");
|
|
45866
|
+
}
|
|
45867
|
+
if (Array.isArray(input.characterOpenings)) {
|
|
45868
|
+
input.characterOpenings = input.characterOpenings.map((characterOpening, index) => {
|
|
45869
|
+
if (typeof characterOpening !== "object" || characterOpening === null) {
|
|
45870
|
+
return characterOpening;
|
|
45871
|
+
}
|
|
45872
|
+
const entry = { ...characterOpening };
|
|
45873
|
+
if ("character" in entry) {
|
|
45874
|
+
entry.characterFileReferenceId = resolve6(entry.character, `characterOpenings[${index}].character`);
|
|
45875
|
+
entry.character = undefined;
|
|
45876
|
+
}
|
|
45877
|
+
entry.opening = translateOpening(entry.opening, `characterOpenings[${index}].opening`);
|
|
45878
|
+
return entry;
|
|
45879
|
+
});
|
|
45880
|
+
}
|
|
45710
45881
|
if (failures.length > 0) {
|
|
45711
45882
|
throw new CliError(`Nothing was saved — some references do not resolve to pushed files:
|
|
45712
45883
|
` + `${failures.map((f) => ` ${f}`).join(`
|
|
45713
45884
|
`)}
|
|
45714
|
-
` + "Use workspace paths, slug.type tokens, or
|
|
45885
|
+
` + "Use workspace paths (preferred), slug.type tokens, slugs, or file names of PUSHED files.", 2);
|
|
45715
45886
|
}
|
|
45716
45887
|
return input;
|
|
45717
45888
|
}
|
|
@@ -50485,12 +50656,19 @@ content. File type changes from the zip apply only with --include-types
|
|
|
50485
50656
|
(missing types are created, drifted types updated \u2014 the server revalidates
|
|
50486
50657
|
existing files against schema changes). Project settings changes from the
|
|
50487
50658
|
zip's .craft/project.json apply only with --include-settings; without it,
|
|
50488
|
-
differing settings are listed but left untouched.
|
|
50659
|
+
differing settings are listed but left untouched. Every field of
|
|
50660
|
+
project.json is diffed and applied individually: name, description, tags,
|
|
50661
|
+
and settings.* \u2014 theme, image, projectIcon, attribution, gameSystemName,
|
|
50662
|
+
headlineLabel, headline, body, authorsNotes, gallery, galleryLayout,
|
|
50663
|
+
isClonable, hideHeroTitle, imageStyleInstructions, autoImageGeneration,
|
|
50664
|
+
defaultImageModel, gmToolSettings, rootMapFileReferenceId, preludeFlow, gm,
|
|
50665
|
+
playerHandbook, builderManual.
|
|
50489
50666
|
|
|
50490
50667
|
--dry-run shows the full plan without writing. --exclude <referenceId>
|
|
50491
50668
|
skips individual rows from the plan (repeatable, or comma-separated; get the
|
|
50492
50669
|
ids from a --dry-run --json plan). --exclude-setting <key> vetoes a single
|
|
50493
|
-
settings change (e.g.
|
|
50670
|
+
settings change, named exactly as the plan's rows are keyed (e.g.
|
|
50671
|
+
settings.preludeFlow, settings.playerHandbook). Runs inside the target
|
|
50494
50672
|
project's workspace, or anywhere with --project <projectId>. The apply is
|
|
50495
50673
|
one atomic batch: on any per-file failure (409) nothing is written and every
|
|
50496
50674
|
failure is listed. Exits 1 while conflicts or failures remain.
|
package/package.json
CHANGED