prpm 1.0.0 → 1.0.2
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 +144 -97
- package/dist/schemas/prpm-manifest.schema.json +723 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -4633,8 +4633,8 @@ function loadSchema(format, subtype) {
|
|
|
4633
4633
|
};
|
|
4634
4634
|
schemaFilename = schemaMap[format] || `${format}.schema.json`;
|
|
4635
4635
|
}
|
|
4636
|
-
const
|
|
4637
|
-
const schemaContent = (0, import_fs8.readFileSync)(
|
|
4636
|
+
const schemaPath = (0, import_path7.join)(currentDirname, "..", "schemas", schemaFilename);
|
|
4637
|
+
const schemaContent = (0, import_fs8.readFileSync)(schemaPath, "utf-8");
|
|
4638
4638
|
const schema3 = JSON.parse(schemaContent);
|
|
4639
4639
|
const compiled = ajv.compile(schema3);
|
|
4640
4640
|
schemaCache.set(cacheKey, compiled);
|
|
@@ -6730,6 +6730,7 @@ async function handleInstall(packageSpec, options) {
|
|
|
6730
6730
|
packageId = parts[0];
|
|
6731
6731
|
specVersion = parts[1];
|
|
6732
6732
|
}
|
|
6733
|
+
const config = await getConfig();
|
|
6733
6734
|
const lockfile = await readLockfile();
|
|
6734
6735
|
const lockedVersion = getLockedVersion(lockfile, packageId);
|
|
6735
6736
|
let version;
|
|
@@ -6741,10 +6742,15 @@ async function handleInstall(packageSpec, options) {
|
|
|
6741
6742
|
} else {
|
|
6742
6743
|
version = options.version || specVersion || lockedVersion || "latest";
|
|
6743
6744
|
}
|
|
6745
|
+
let targetFormat = options.as;
|
|
6746
|
+
if (!targetFormat) {
|
|
6747
|
+
targetFormat = config.defaultFormat || await autoDetectFormat() || void 0;
|
|
6748
|
+
}
|
|
6744
6749
|
if (!options.force && lockfile && lockfile.packages[packageId]) {
|
|
6745
6750
|
const installedPkg = lockfile.packages[packageId];
|
|
6746
6751
|
const requestedVersion = options.version || specVersion;
|
|
6747
|
-
|
|
6752
|
+
const sameFormat = !targetFormat || installedPkg.format === targetFormat;
|
|
6753
|
+
if (sameFormat && (!requestedVersion || requestedVersion === "latest" || requestedVersion === installedPkg.version)) {
|
|
6748
6754
|
console.log(`
|
|
6749
6755
|
\u2728 Package already installed!`);
|
|
6750
6756
|
console.log(` \u{1F4E6} ${packageId}@${installedPkg.version}`);
|
|
@@ -6753,14 +6759,16 @@ async function handleInstall(packageSpec, options) {
|
|
|
6753
6759
|
\u{1F4A1} To reinstall or upgrade:`);
|
|
6754
6760
|
console.log(` prpm upgrade ${packageId} # Upgrade to latest version`);
|
|
6755
6761
|
console.log(` prpm uninstall ${packageId} # Uninstall first, then install`);
|
|
6762
|
+
console.log(` prpm install ${packageId} --as <format> # Install in different format`);
|
|
6756
6763
|
success = true;
|
|
6757
6764
|
return;
|
|
6765
|
+
} else if (!sameFormat) {
|
|
6766
|
+
console.log(`\u{1F4E6} Installing ${packageId} in ${targetFormat} format (already have ${installedPkg.format} version)`);
|
|
6758
6767
|
} else if (requestedVersion !== installedPkg.version) {
|
|
6759
6768
|
console.log(`\u{1F4E6} Upgrading ${packageId}: ${installedPkg.version} \u2192 ${requestedVersion}`);
|
|
6760
6769
|
}
|
|
6761
6770
|
}
|
|
6762
6771
|
console.log(`\u{1F4E5} Installing ${packageId}@${version}...`);
|
|
6763
|
-
const config = await getConfig();
|
|
6764
6772
|
const client = (0, import_registry_client5.getRegistryClient)(config);
|
|
6765
6773
|
let isCollection = false;
|
|
6766
6774
|
try {
|
|
@@ -7210,65 +7218,90 @@ ${afterFrontmatter}`;
|
|
|
7210
7218
|
}
|
|
7211
7219
|
}
|
|
7212
7220
|
async function extractTarball(tarball, packageId) {
|
|
7213
|
-
const files = [];
|
|
7214
7221
|
const zlib = await import("zlib");
|
|
7215
|
-
const fs9 = await import("fs");
|
|
7222
|
+
const fs9 = await import("fs/promises");
|
|
7216
7223
|
const os2 = await import("os");
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7224
|
+
const fallback = (buffer) => [
|
|
7225
|
+
{
|
|
7226
|
+
name: `${packageId}.md`,
|
|
7227
|
+
content: buffer.toString("utf-8")
|
|
7228
|
+
}
|
|
7229
|
+
];
|
|
7230
|
+
let decompressed;
|
|
7231
|
+
try {
|
|
7232
|
+
decompressed = await new Promise((resolve2, reject) => {
|
|
7233
|
+
zlib.gunzip(tarball, (err, result) => {
|
|
7234
|
+
if (err) {
|
|
7235
|
+
reject(err);
|
|
7236
|
+
return;
|
|
7237
|
+
}
|
|
7238
|
+
resolve2(result);
|
|
7239
|
+
});
|
|
7240
|
+
});
|
|
7241
|
+
} catch (error) {
|
|
7242
|
+
throw error;
|
|
7243
|
+
}
|
|
7244
|
+
const tmpDir = await fs9.mkdtemp(import_path8.default.join(os2.tmpdir(), "prpm-"));
|
|
7245
|
+
const cleanup = async () => {
|
|
7246
|
+
try {
|
|
7247
|
+
await fs9.rm(tmpDir, { recursive: true, force: true });
|
|
7248
|
+
} catch {
|
|
7249
|
+
}
|
|
7250
|
+
};
|
|
7251
|
+
const excludedNames = /* @__PURE__ */ new Set([
|
|
7252
|
+
"prpm.json",
|
|
7253
|
+
"README",
|
|
7254
|
+
"README.md",
|
|
7255
|
+
"README.txt",
|
|
7256
|
+
"LICENSE",
|
|
7257
|
+
"LICENSE.txt",
|
|
7258
|
+
"LICENSE.md"
|
|
7259
|
+
]);
|
|
7260
|
+
try {
|
|
7261
|
+
const extract2 = tar.extract({
|
|
7262
|
+
cwd: tmpDir,
|
|
7263
|
+
strict: false
|
|
7264
|
+
});
|
|
7265
|
+
await (0, import_promises.pipeline)(import_stream.Readable.from(decompressed), extract2);
|
|
7266
|
+
const extractedFiles = await collectExtractedFiles(tmpDir, excludedNames, fs9);
|
|
7267
|
+
if (extractedFiles.length === 0) {
|
|
7268
|
+
return fallback(decompressed);
|
|
7269
|
+
}
|
|
7270
|
+
return extractedFiles;
|
|
7271
|
+
} catch {
|
|
7272
|
+
return fallback(decompressed);
|
|
7273
|
+
} finally {
|
|
7274
|
+
await cleanup();
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
async function collectExtractedFiles(rootDir, excludedNames, fs9) {
|
|
7278
|
+
const files = [];
|
|
7279
|
+
const dirs = [rootDir];
|
|
7280
|
+
while (dirs.length > 0) {
|
|
7281
|
+
const currentDir = dirs.pop();
|
|
7282
|
+
if (!currentDir) continue;
|
|
7283
|
+
const entries = await fs9.readdir(currentDir, { withFileTypes: true });
|
|
7284
|
+
for (const entry of entries) {
|
|
7285
|
+
const fullPath = import_path8.default.join(currentDir, entry.name);
|
|
7286
|
+
if (entry.isDirectory()) {
|
|
7287
|
+
dirs.push(fullPath);
|
|
7288
|
+
continue;
|
|
7222
7289
|
}
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
files.push({
|
|
7226
|
-
name: `${packageId}.md`,
|
|
7227
|
-
content: result.toString("utf-8")
|
|
7228
|
-
});
|
|
7229
|
-
resolve2(files);
|
|
7230
|
-
return;
|
|
7290
|
+
if (!entry.isFile()) {
|
|
7291
|
+
continue;
|
|
7231
7292
|
}
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
const tarPath = import_path8.default.join(tmpDir, "package.tar");
|
|
7235
|
-
await fs9.promises.writeFile(tarPath, result);
|
|
7236
|
-
await tar.extract({
|
|
7237
|
-
file: tarPath,
|
|
7238
|
-
cwd: tmpDir
|
|
7239
|
-
});
|
|
7240
|
-
const extractedFiles = await fs9.promises.readdir(tmpDir, { withFileTypes: true, recursive: true });
|
|
7241
|
-
const excludeFiles = ["package.tar", "prpm.json", "README.md", "LICENSE", "LICENSE.txt", "LICENSE.md"];
|
|
7242
|
-
for (const entry of extractedFiles) {
|
|
7243
|
-
if (entry.isFile() && !excludeFiles.includes(entry.name)) {
|
|
7244
|
-
const filePath = import_path8.default.join(entry.path || tmpDir, entry.name);
|
|
7245
|
-
const content = await fs9.promises.readFile(filePath, "utf-8");
|
|
7246
|
-
const relativePath = import_path8.default.relative(tmpDir, filePath);
|
|
7247
|
-
files.push({
|
|
7248
|
-
name: relativePath,
|
|
7249
|
-
content
|
|
7250
|
-
});
|
|
7251
|
-
}
|
|
7252
|
-
}
|
|
7253
|
-
if (files.length === 0) {
|
|
7254
|
-
files.push({
|
|
7255
|
-
name: `${packageId}.md`,
|
|
7256
|
-
content: result.toString("utf-8")
|
|
7257
|
-
});
|
|
7258
|
-
}
|
|
7259
|
-
await fs9.promises.rm(tmpDir, { recursive: true, force: true });
|
|
7260
|
-
resolve2(files);
|
|
7261
|
-
} catch (tarErr) {
|
|
7262
|
-
await fs9.promises.rm(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
7263
|
-
});
|
|
7264
|
-
files.push({
|
|
7265
|
-
name: `${packageId}.md`,
|
|
7266
|
-
content: result.toString("utf-8")
|
|
7267
|
-
});
|
|
7268
|
-
resolve2(files);
|
|
7293
|
+
if (excludedNames.has(entry.name)) {
|
|
7294
|
+
continue;
|
|
7269
7295
|
}
|
|
7270
|
-
|
|
7271
|
-
|
|
7296
|
+
const content = await fs9.readFile(fullPath, "utf-8");
|
|
7297
|
+
const relativePath = import_path8.default.relative(rootDir, fullPath).split(import_path8.default.sep).join("/");
|
|
7298
|
+
files.push({
|
|
7299
|
+
name: relativePath,
|
|
7300
|
+
content
|
|
7301
|
+
});
|
|
7302
|
+
}
|
|
7303
|
+
}
|
|
7304
|
+
return files;
|
|
7272
7305
|
}
|
|
7273
7306
|
async function installFromLockfile(options) {
|
|
7274
7307
|
var _a;
|
|
@@ -7362,7 +7395,7 @@ function createInstallCommand() {
|
|
|
7362
7395
|
});
|
|
7363
7396
|
return command;
|
|
7364
7397
|
}
|
|
7365
|
-
var import_commander10, import_registry_client5, tar, import_path8;
|
|
7398
|
+
var import_commander10, import_registry_client5, import_stream, import_promises, tar, import_path8;
|
|
7366
7399
|
var init_install = __esm({
|
|
7367
7400
|
"src/commands/install.ts"() {
|
|
7368
7401
|
"use strict";
|
|
@@ -7372,6 +7405,8 @@ var init_install = __esm({
|
|
|
7372
7405
|
init_user_config();
|
|
7373
7406
|
init_filesystem();
|
|
7374
7407
|
init_telemetry();
|
|
7408
|
+
import_stream = require("stream");
|
|
7409
|
+
import_promises = require("stream/promises");
|
|
7375
7410
|
tar = __toESM(require("tar"));
|
|
7376
7411
|
init_errors();
|
|
7377
7412
|
init_prompts();
|
|
@@ -9940,7 +9975,7 @@ init_install();
|
|
|
9940
9975
|
// src/commands/publish.ts
|
|
9941
9976
|
init_cjs_shims();
|
|
9942
9977
|
var import_commander11 = require("commander");
|
|
9943
|
-
var
|
|
9978
|
+
var import_promises5 = require("fs/promises");
|
|
9944
9979
|
var import_path12 = require("path");
|
|
9945
9980
|
var tar2 = __toESM(require("tar"));
|
|
9946
9981
|
var import_os3 = require("os");
|
|
@@ -10116,11 +10151,23 @@ var import_ajv2 = __toESM(require("ajv"));
|
|
|
10116
10151
|
var import_ajv_formats2 = __toESM(require("ajv-formats"));
|
|
10117
10152
|
var import_fs9 = require("fs");
|
|
10118
10153
|
var import_path9 = require("path");
|
|
10119
|
-
var schemaPath = (0, import_path9.join)(__dirname, "../../schemas/prpm-manifest.schema.json");
|
|
10120
10154
|
var schema2;
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10155
|
+
var schemaCandidates = [
|
|
10156
|
+
// Source file layout (src/core → ../../schemas)
|
|
10157
|
+
(0, import_path9.join)(__dirname, "../../schemas/prpm-manifest.schema.json"),
|
|
10158
|
+
// Bundled layout (dist/index.js → ../schemas)
|
|
10159
|
+
(0, import_path9.join)(__dirname, "../schemas/prpm-manifest.schema.json")
|
|
10160
|
+
];
|
|
10161
|
+
for (const candidate of schemaCandidates) {
|
|
10162
|
+
try {
|
|
10163
|
+
if ((0, import_fs9.existsSync)(candidate)) {
|
|
10164
|
+
schema2 = JSON.parse((0, import_fs9.readFileSync)(candidate, "utf-8"));
|
|
10165
|
+
break;
|
|
10166
|
+
}
|
|
10167
|
+
} catch {
|
|
10168
|
+
}
|
|
10169
|
+
}
|
|
10170
|
+
if (!schema2) {
|
|
10124
10171
|
console.warn("\u26A0\uFE0F Could not load manifest schema, skipping schema validation");
|
|
10125
10172
|
}
|
|
10126
10173
|
function validateManifestSchema(manifest) {
|
|
@@ -10168,7 +10215,7 @@ function getManifestSchema() {
|
|
|
10168
10215
|
|
|
10169
10216
|
// src/utils/license-extractor.ts
|
|
10170
10217
|
init_cjs_shims();
|
|
10171
|
-
var
|
|
10218
|
+
var import_promises2 = require("fs/promises");
|
|
10172
10219
|
var import_path10 = require("path");
|
|
10173
10220
|
var import_fs10 = require("fs");
|
|
10174
10221
|
var LICENSE_FILE_PATTERNS = [
|
|
@@ -10221,8 +10268,8 @@ async function extractLicenseInfo(repositoryUrl) {
|
|
|
10221
10268
|
for (const fileName of LICENSE_FILE_PATTERNS) {
|
|
10222
10269
|
const filePath = (0, import_path10.join)(cwd, fileName);
|
|
10223
10270
|
try {
|
|
10224
|
-
await (0,
|
|
10225
|
-
const text = await (0,
|
|
10271
|
+
await (0, import_promises2.access)(filePath, import_fs10.constants.R_OK);
|
|
10272
|
+
const text = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
10226
10273
|
const type2 = detectLicenseType(text);
|
|
10227
10274
|
const url = generateLicenseUrl(repositoryUrl, fileName);
|
|
10228
10275
|
return {
|
|
@@ -10254,7 +10301,7 @@ function validateLicenseInfo(licenseInfo, packageName) {
|
|
|
10254
10301
|
|
|
10255
10302
|
// src/utils/snippet-extractor.ts
|
|
10256
10303
|
init_cjs_shims();
|
|
10257
|
-
var
|
|
10304
|
+
var import_promises3 = require("fs/promises");
|
|
10258
10305
|
var import_path11 = require("path");
|
|
10259
10306
|
var MAX_SNIPPET_LENGTH = 2e3;
|
|
10260
10307
|
async function extractSnippet(manifest) {
|
|
@@ -10272,12 +10319,12 @@ async function extractSnippet(manifest) {
|
|
|
10272
10319
|
fileName = typeof firstFile === "string" ? firstFile : firstFile.path;
|
|
10273
10320
|
}
|
|
10274
10321
|
const fullPath = (0, import_path11.join)(cwd, fileName);
|
|
10275
|
-
const stats = await (0,
|
|
10322
|
+
const stats = await (0, import_promises3.stat)(fullPath);
|
|
10276
10323
|
if (stats.isDirectory()) {
|
|
10277
10324
|
console.warn(`\u26A0\uFE0F Skipping snippet extraction: "${fullPath}" is a directory`);
|
|
10278
10325
|
return null;
|
|
10279
10326
|
}
|
|
10280
|
-
const content = await (0,
|
|
10327
|
+
const content = await (0, import_promises3.readFile)(fullPath, "utf-8");
|
|
10281
10328
|
if (content.length <= MAX_SNIPPET_LENGTH) {
|
|
10282
10329
|
return content.trim();
|
|
10283
10330
|
}
|
|
@@ -10360,7 +10407,7 @@ async function executePrepublishOnly(scripts, options = {}) {
|
|
|
10360
10407
|
|
|
10361
10408
|
// src/utils/format-file-validator.ts
|
|
10362
10409
|
init_cjs_shims();
|
|
10363
|
-
var
|
|
10410
|
+
var import_promises4 = require("fs/promises");
|
|
10364
10411
|
function normalizeFilePaths(files) {
|
|
10365
10412
|
return files.map((file) => {
|
|
10366
10413
|
if (typeof file === "string") {
|
|
@@ -10388,7 +10435,7 @@ function getFormatType(format, subtype) {
|
|
|
10388
10435
|
async function validateMarkdownFile(filePath, formatType) {
|
|
10389
10436
|
try {
|
|
10390
10437
|
const { validateMarkdown: validateMarkdown2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
10391
|
-
const content = await (0,
|
|
10438
|
+
const content = await (0, import_promises4.readFile)(filePath, "utf-8");
|
|
10392
10439
|
const result = validateMarkdown2(formatType, content);
|
|
10393
10440
|
return {
|
|
10394
10441
|
valid: result.valid,
|
|
@@ -10494,7 +10541,7 @@ async function findAndLoadManifests() {
|
|
|
10494
10541
|
let prpmJsonExists = false;
|
|
10495
10542
|
let prpmJsonError = null;
|
|
10496
10543
|
try {
|
|
10497
|
-
const content = await (0,
|
|
10544
|
+
const content = await (0, import_promises5.readFile)(prpmJsonPath, "utf-8");
|
|
10498
10545
|
prpmJsonExists = true;
|
|
10499
10546
|
const manifest = JSON.parse(content);
|
|
10500
10547
|
const collections = [];
|
|
@@ -10543,7 +10590,7 @@ async function findAndLoadManifests() {
|
|
|
10543
10590
|
}
|
|
10544
10591
|
const marketplaceJsonPath = (0, import_path12.join)(process.cwd(), ".claude", "marketplace.json");
|
|
10545
10592
|
try {
|
|
10546
|
-
const content = await (0,
|
|
10593
|
+
const content = await (0, import_promises5.readFile)(marketplaceJsonPath, "utf-8");
|
|
10547
10594
|
const marketplaceData = JSON.parse(content);
|
|
10548
10595
|
if (!validateMarketplaceJson(marketplaceData)) {
|
|
10549
10596
|
throw new Error("Invalid marketplace.json format");
|
|
@@ -10559,7 +10606,7 @@ async function findAndLoadManifests() {
|
|
|
10559
10606
|
}
|
|
10560
10607
|
const marketplaceJsonPluginPath = (0, import_path12.join)(process.cwd(), ".claude-plugin", "marketplace.json");
|
|
10561
10608
|
try {
|
|
10562
|
-
const content = await (0,
|
|
10609
|
+
const content = await (0, import_promises5.readFile)(marketplaceJsonPluginPath, "utf-8");
|
|
10563
10610
|
const marketplaceData = JSON.parse(content);
|
|
10564
10611
|
if (!validateMarketplaceJson(marketplaceData)) {
|
|
10565
10612
|
throw new Error("Invalid marketplace.json format");
|
|
@@ -10672,7 +10719,7 @@ async function createTarball(manifest) {
|
|
|
10672
10719
|
const tmpDir = (0, import_path12.join)((0, import_os3.tmpdir)(), `prpm-${(0, import_crypto2.randomBytes)(8).toString("hex")}`);
|
|
10673
10720
|
const tarballPath = (0, import_path12.join)(tmpDir, "package.tar.gz");
|
|
10674
10721
|
try {
|
|
10675
|
-
await (0,
|
|
10722
|
+
await (0, import_promises5.mkdir)(tmpDir, { recursive: true });
|
|
10676
10723
|
const filePaths = normalizeFilePaths2(manifest.files);
|
|
10677
10724
|
const standardFiles = ["prpm.json", "README.md", "LICENSE"];
|
|
10678
10725
|
for (const file of standardFiles) {
|
|
@@ -10683,7 +10730,7 @@ async function createTarball(manifest) {
|
|
|
10683
10730
|
const existingFiles = [];
|
|
10684
10731
|
for (const file of filePaths) {
|
|
10685
10732
|
try {
|
|
10686
|
-
await (0,
|
|
10733
|
+
await (0, import_promises5.stat)(file);
|
|
10687
10734
|
existingFiles.push(file);
|
|
10688
10735
|
} catch {
|
|
10689
10736
|
}
|
|
@@ -10699,7 +10746,7 @@ async function createTarball(manifest) {
|
|
|
10699
10746
|
},
|
|
10700
10747
|
existingFiles
|
|
10701
10748
|
);
|
|
10702
|
-
const tarballBuffer = await (0,
|
|
10749
|
+
const tarballBuffer = await (0, import_promises5.readFile)(tarballPath);
|
|
10703
10750
|
const sizeMB = tarballBuffer.length / (1024 * 1024);
|
|
10704
10751
|
if (sizeMB > 10) {
|
|
10705
10752
|
throw new Error(`Package size (${sizeMB.toFixed(2)}MB) exceeds 10MB limit`);
|
|
@@ -10709,7 +10756,7 @@ async function createTarball(manifest) {
|
|
|
10709
10756
|
throw error;
|
|
10710
10757
|
} finally {
|
|
10711
10758
|
try {
|
|
10712
|
-
await (0,
|
|
10759
|
+
await (0, import_promises5.rm)(tmpDir, { recursive: true, force: true });
|
|
10713
10760
|
} catch {
|
|
10714
10761
|
}
|
|
10715
10762
|
}
|
|
@@ -10732,7 +10779,7 @@ async function handlePublish(options) {
|
|
|
10732
10779
|
if (source === "prpm.json (multi-package)" || source === "prpm.json") {
|
|
10733
10780
|
try {
|
|
10734
10781
|
const prpmJsonPath = (0, import_path12.join)(process.cwd(), "prpm.json");
|
|
10735
|
-
const prpmContent = await (0,
|
|
10782
|
+
const prpmContent = await (0, import_promises5.readFile)(prpmJsonPath, "utf-8");
|
|
10736
10783
|
const prpmManifest = JSON.parse(prpmContent);
|
|
10737
10784
|
if (prpmManifest.scripts) {
|
|
10738
10785
|
await executePrepublishOnly(prpmManifest.scripts);
|
|
@@ -11722,7 +11769,7 @@ function createSchemaCommand() {
|
|
|
11722
11769
|
// src/commands/init.ts
|
|
11723
11770
|
init_cjs_shims();
|
|
11724
11771
|
var import_commander18 = require("commander");
|
|
11725
|
-
var
|
|
11772
|
+
var import_promises6 = require("fs/promises");
|
|
11726
11773
|
var import_path13 = require("path");
|
|
11727
11774
|
var import_fs11 = require("fs");
|
|
11728
11775
|
var readline3 = __toESM(require("readline/promises"));
|
|
@@ -12029,7 +12076,7 @@ ${question}`);
|
|
|
12029
12076
|
}
|
|
12030
12077
|
async function extractMetadataFromFile(filePath) {
|
|
12031
12078
|
try {
|
|
12032
|
-
const content = await (0,
|
|
12079
|
+
const content = await (0, import_promises6.readFile)(filePath, "utf-8");
|
|
12033
12080
|
const metadata = {};
|
|
12034
12081
|
const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
12035
12082
|
if (frontmatterMatch) {
|
|
@@ -12094,7 +12141,7 @@ async function createExampleFiles(format, files, packageName) {
|
|
|
12094
12141
|
const filePath = (0, import_path13.join)(process.cwd(), file);
|
|
12095
12142
|
const dirPath = (0, import_path13.join)(filePath, "..");
|
|
12096
12143
|
if (!(0, import_fs11.existsSync)(dirPath)) {
|
|
12097
|
-
await (0,
|
|
12144
|
+
await (0, import_promises6.mkdir)(dirPath, { recursive: true });
|
|
12098
12145
|
}
|
|
12099
12146
|
if ((0, import_fs11.existsSync)(filePath)) {
|
|
12100
12147
|
console.log(` Skipping ${file} (already exists)`);
|
|
@@ -12105,7 +12152,7 @@ async function createExampleFiles(format, files, packageName) {
|
|
|
12105
12152
|
Add your content here.
|
|
12106
12153
|
`;
|
|
12107
12154
|
content = content.replace(/example-skill/g, packageName);
|
|
12108
|
-
await (0,
|
|
12155
|
+
await (0, import_promises6.writeFile)(filePath, content, "utf-8");
|
|
12109
12156
|
console.log(` Created ${file}`);
|
|
12110
12157
|
}
|
|
12111
12158
|
}
|
|
@@ -12141,7 +12188,7 @@ ${config.author}
|
|
|
12141
12188
|
|
|
12142
12189
|
${config.license}
|
|
12143
12190
|
`;
|
|
12144
|
-
await (0,
|
|
12191
|
+
await (0, import_promises6.writeFile)(readmePath, content, "utf-8");
|
|
12145
12192
|
console.log(" Created README.md");
|
|
12146
12193
|
}
|
|
12147
12194
|
async function initPackage(options) {
|
|
@@ -12298,7 +12345,7 @@ Current files (${config.files.length}):`);
|
|
|
12298
12345
|
manifest.tags = config.tags;
|
|
12299
12346
|
}
|
|
12300
12347
|
manifest.files = config.files;
|
|
12301
|
-
await (0,
|
|
12348
|
+
await (0, import_promises6.writeFile)(
|
|
12302
12349
|
manifestPath,
|
|
12303
12350
|
JSON.stringify(manifest, null, 2) + "\n",
|
|
12304
12351
|
"utf-8"
|
|
@@ -12444,7 +12491,7 @@ function createConfigCommand() {
|
|
|
12444
12491
|
// src/commands/catalog.ts
|
|
12445
12492
|
init_cjs_shims();
|
|
12446
12493
|
var import_commander20 = require("commander");
|
|
12447
|
-
var
|
|
12494
|
+
var import_promises7 = require("fs/promises");
|
|
12448
12495
|
var import_path14 = require("path");
|
|
12449
12496
|
init_telemetry();
|
|
12450
12497
|
init_lockfile();
|
|
@@ -12503,7 +12550,7 @@ async function scanDirectory2(dirPath, baseDir, scanDir, maxDepth = 5, currentDe
|
|
|
12503
12550
|
}
|
|
12504
12551
|
const discovered = [];
|
|
12505
12552
|
try {
|
|
12506
|
-
const entries = await (0,
|
|
12553
|
+
const entries = await (0, import_promises7.readdir)(dirPath, { withFileTypes: true });
|
|
12507
12554
|
for (const entry of entries) {
|
|
12508
12555
|
const fullPath = (0, import_path14.join)(dirPath, entry.name);
|
|
12509
12556
|
const relativePath = (0, import_path14.relative)(baseDir, fullPath);
|
|
@@ -12515,7 +12562,7 @@ async function scanDirectory2(dirPath, baseDir, scanDir, maxDepth = 5, currentDe
|
|
|
12515
12562
|
discovered.push(...subDirPackages);
|
|
12516
12563
|
} else if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".mdc") || entry.name.endsWith(".txt"))) {
|
|
12517
12564
|
try {
|
|
12518
|
-
const content = await (0,
|
|
12565
|
+
const content = await (0, import_promises7.readFile)(fullPath, "utf-8");
|
|
12519
12566
|
const packageInfo = detectPackageInfo(fullPath, content);
|
|
12520
12567
|
if (packageInfo) {
|
|
12521
12568
|
discovered.push({
|
|
@@ -12594,7 +12641,7 @@ async function handleCatalog(directories, options) {
|
|
|
12594
12641
|
for (const dir of directories) {
|
|
12595
12642
|
console.log(` Scanning ${dir}...`);
|
|
12596
12643
|
try {
|
|
12597
|
-
const dirStat = await (0,
|
|
12644
|
+
const dirStat = await (0, import_promises7.stat)(dir);
|
|
12598
12645
|
if (!dirStat.isDirectory()) {
|
|
12599
12646
|
console.log(` \u26A0\uFE0F Skipping ${dir} (not a directory)`);
|
|
12600
12647
|
continue;
|
|
@@ -12647,7 +12694,7 @@ async function handleCatalog(directories, options) {
|
|
|
12647
12694
|
let manifest;
|
|
12648
12695
|
if (options.append) {
|
|
12649
12696
|
try {
|
|
12650
|
-
const existingContent = await (0,
|
|
12697
|
+
const existingContent = await (0, import_promises7.readFile)(prpmJsonPath, "utf-8");
|
|
12651
12698
|
const existing = JSON.parse(existingContent);
|
|
12652
12699
|
if ("packages" in existing && Array.isArray(existing.packages)) {
|
|
12653
12700
|
manifest = existing;
|
|
@@ -12682,7 +12729,7 @@ async function handleCatalog(directories, options) {
|
|
|
12682
12729
|
let description = `${discovered.format} ${discovered.subtype}`;
|
|
12683
12730
|
try {
|
|
12684
12731
|
const firstFilePath = (0, import_path14.join)(process.cwd(), discovered.scanDir, discovered.files[0]);
|
|
12685
|
-
const content = await (0,
|
|
12732
|
+
const content = await (0, import_promises7.readFile)(firstFilePath, "utf-8");
|
|
12686
12733
|
const extractedDesc = extractDescription2(content);
|
|
12687
12734
|
if (extractedDesc) {
|
|
12688
12735
|
description = extractedDesc;
|
|
@@ -12702,7 +12749,7 @@ async function handleCatalog(directories, options) {
|
|
|
12702
12749
|
manifest.packages.push(packageManifest);
|
|
12703
12750
|
addedCount++;
|
|
12704
12751
|
}
|
|
12705
|
-
await (0,
|
|
12752
|
+
await (0, import_promises7.writeFile)(prpmJsonPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
12706
12753
|
console.log(`
|
|
12707
12754
|
\u2705 Updated ${prpmJsonPath}`);
|
|
12708
12755
|
console.log(` Added ${addedCount} new package(s)`);
|
|
@@ -13931,7 +13978,7 @@ function createStarredCommand() {
|
|
|
13931
13978
|
// src/commands/convert.ts
|
|
13932
13979
|
init_cjs_shims();
|
|
13933
13980
|
var import_commander26 = require("commander");
|
|
13934
|
-
var
|
|
13981
|
+
var import_promises8 = require("fs/promises");
|
|
13935
13982
|
var import_path15 = require("path");
|
|
13936
13983
|
var import_fs12 = require("fs");
|
|
13937
13984
|
var import_readline = require("readline");
|
|
@@ -14037,7 +14084,7 @@ async function handleConvert(sourcePath, options) {
|
|
|
14037
14084
|
console.log(import_chalk.default.dim("Reading source file..."));
|
|
14038
14085
|
let content;
|
|
14039
14086
|
try {
|
|
14040
|
-
content = await (0,
|
|
14087
|
+
content = await (0, import_promises8.readFile)(sourcePath, "utf-8");
|
|
14041
14088
|
} catch (error) {
|
|
14042
14089
|
throw new CLIError(`Failed to read source file: ${error.message}`);
|
|
14043
14090
|
}
|
|
@@ -14137,9 +14184,9 @@ async function handleConvert(sourcePath, options) {
|
|
|
14137
14184
|
}
|
|
14138
14185
|
}
|
|
14139
14186
|
const outputDir = (0, import_path15.dirname)(outputPath);
|
|
14140
|
-
await (0,
|
|
14187
|
+
await (0, import_promises8.mkdir)(outputDir, { recursive: true });
|
|
14141
14188
|
console.log(import_chalk.default.dim("Writing converted file..."));
|
|
14142
|
-
await (0,
|
|
14189
|
+
await (0, import_promises8.writeFile)(outputPath, result.content, "utf-8");
|
|
14143
14190
|
console.log(import_chalk.default.green(`\u2713 Converted file written to ${outputPath}`));
|
|
14144
14191
|
console.log();
|
|
14145
14192
|
if (options.to === "cursor") {
|
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://prpm.dev/schemas/manifest.json",
|
|
4
|
+
"title": "PRPM Package Manifest",
|
|
5
|
+
"description": "Schema for PRPM package manifest (prpm.json)",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"name",
|
|
9
|
+
"version",
|
|
10
|
+
"description",
|
|
11
|
+
"format"
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Package name in format: package-name or @scope/package-name",
|
|
17
|
+
"pattern": "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$",
|
|
18
|
+
"minLength": 1,
|
|
19
|
+
"maxLength": 214,
|
|
20
|
+
"examples": [
|
|
21
|
+
"react-rules",
|
|
22
|
+
"@community/testing-skills",
|
|
23
|
+
"@company/cursor-rules"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
"version": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Semantic version (semver)",
|
|
29
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$",
|
|
30
|
+
"examples": [
|
|
31
|
+
"1.0.0",
|
|
32
|
+
"2.1.3",
|
|
33
|
+
"1.0.0-beta.1"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"description": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Package description",
|
|
39
|
+
"minLength": 10,
|
|
40
|
+
"maxLength": 500
|
|
41
|
+
},
|
|
42
|
+
"format": {
|
|
43
|
+
"type": "string",
|
|
44
|
+
"description": "Package format - the AI tool/platform this package is for",
|
|
45
|
+
"enum": [
|
|
46
|
+
"cursor",
|
|
47
|
+
"claude",
|
|
48
|
+
"continue",
|
|
49
|
+
"windsurf",
|
|
50
|
+
"copilot",
|
|
51
|
+
"kiro",
|
|
52
|
+
"agents.md",
|
|
53
|
+
"generic",
|
|
54
|
+
"mcp"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"subtype": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Package subtype - the functional category (optional, defaults to 'rule')",
|
|
60
|
+
"enum": [
|
|
61
|
+
"rule",
|
|
62
|
+
"agent",
|
|
63
|
+
"skill",
|
|
64
|
+
"slash-command",
|
|
65
|
+
"prompt",
|
|
66
|
+
"workflow",
|
|
67
|
+
"tool",
|
|
68
|
+
"template",
|
|
69
|
+
"collection"
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
"author": {
|
|
73
|
+
"description": "Package author",
|
|
74
|
+
"oneOf": [
|
|
75
|
+
{
|
|
76
|
+
"type": "string",
|
|
77
|
+
"examples": [
|
|
78
|
+
"John Doe",
|
|
79
|
+
"Jane Smith"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "object",
|
|
84
|
+
"required": [
|
|
85
|
+
"name"
|
|
86
|
+
],
|
|
87
|
+
"properties": {
|
|
88
|
+
"name": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "Author name"
|
|
91
|
+
},
|
|
92
|
+
"email": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"format": "email",
|
|
95
|
+
"description": "Author email"
|
|
96
|
+
},
|
|
97
|
+
"url": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"format": "uri",
|
|
100
|
+
"description": "Author URL"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"license": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"description": "SPDX license identifier",
|
|
109
|
+
"examples": [
|
|
110
|
+
"MIT",
|
|
111
|
+
"Apache-2.0",
|
|
112
|
+
"GPL-3.0",
|
|
113
|
+
"BSD-3-Clause"
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"license_text": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "Full text of the license file for proper attribution"
|
|
119
|
+
},
|
|
120
|
+
"license_url": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"format": "uri",
|
|
123
|
+
"description": "URL to the license file in the repository"
|
|
124
|
+
},
|
|
125
|
+
"repository": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"format": "uri",
|
|
128
|
+
"description": "Repository URL",
|
|
129
|
+
"examples": [
|
|
130
|
+
"https://github.com/username/repo"
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
"homepage": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"format": "uri",
|
|
136
|
+
"description": "Package homepage URL"
|
|
137
|
+
},
|
|
138
|
+
"documentation": {
|
|
139
|
+
"type": "string",
|
|
140
|
+
"format": "uri",
|
|
141
|
+
"description": "Documentation URL"
|
|
142
|
+
},
|
|
143
|
+
"organization": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "Organization name or ID to publish this package under. If not specified, publishes to personal account.",
|
|
146
|
+
"examples": [
|
|
147
|
+
"my-team",
|
|
148
|
+
"my-company"
|
|
149
|
+
]
|
|
150
|
+
},
|
|
151
|
+
"private": {
|
|
152
|
+
"type": "boolean",
|
|
153
|
+
"description": "Whether the package is private. Private packages are only accessible to the owner/organization members. Defaults to false (public).",
|
|
154
|
+
"default": false
|
|
155
|
+
},
|
|
156
|
+
"scripts": {
|
|
157
|
+
"type": "object",
|
|
158
|
+
"description": "Lifecycle scripts that run during package operations. Only applies to multi-package manifests (prpm.json with packages array).",
|
|
159
|
+
"properties": {
|
|
160
|
+
"prepublishOnly": {
|
|
161
|
+
"type": "string",
|
|
162
|
+
"description": "Script to run before publishing (recommended - only runs on 'prpm publish')",
|
|
163
|
+
"examples": [
|
|
164
|
+
"npm run build",
|
|
165
|
+
"cd packages/hooks && npm run build",
|
|
166
|
+
"npm test && npm run build"
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
"prepublish": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"description": "Script to run before publishing and on npm install (not recommended - use prepublishOnly instead)",
|
|
172
|
+
"examples": [
|
|
173
|
+
"npm run build"
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"additionalProperties": false
|
|
178
|
+
},
|
|
179
|
+
"tags": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"description": "Package tags for categorization",
|
|
182
|
+
"items": {
|
|
183
|
+
"type": "string"
|
|
184
|
+
},
|
|
185
|
+
"maxItems": 10,
|
|
186
|
+
"uniqueItems": true,
|
|
187
|
+
"examples": [
|
|
188
|
+
[
|
|
189
|
+
"productivity",
|
|
190
|
+
"coding"
|
|
191
|
+
],
|
|
192
|
+
[
|
|
193
|
+
"testing",
|
|
194
|
+
"quality"
|
|
195
|
+
]
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
"keywords": {
|
|
199
|
+
"type": "array",
|
|
200
|
+
"description": "Search keywords",
|
|
201
|
+
"items": {
|
|
202
|
+
"type": "string"
|
|
203
|
+
},
|
|
204
|
+
"maxItems": 20,
|
|
205
|
+
"uniqueItems": true,
|
|
206
|
+
"examples": [
|
|
207
|
+
[
|
|
208
|
+
"ai",
|
|
209
|
+
"prompts",
|
|
210
|
+
"development"
|
|
211
|
+
]
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
"category": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"description": "Package category",
|
|
217
|
+
"examples": [
|
|
218
|
+
"development",
|
|
219
|
+
"productivity",
|
|
220
|
+
"testing"
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
"files": {
|
|
224
|
+
"description": "Files to include in package. Can be simple paths or enhanced file objects with metadata.",
|
|
225
|
+
"oneOf": [
|
|
226
|
+
{
|
|
227
|
+
"type": "array",
|
|
228
|
+
"description": "Simple format: array of file paths",
|
|
229
|
+
"items": {
|
|
230
|
+
"type": "string"
|
|
231
|
+
},
|
|
232
|
+
"minItems": 1,
|
|
233
|
+
"examples": [
|
|
234
|
+
[
|
|
235
|
+
"skill.md",
|
|
236
|
+
"README.md"
|
|
237
|
+
],
|
|
238
|
+
[
|
|
239
|
+
".cursor/rules/react.mdc",
|
|
240
|
+
"LICENSE"
|
|
241
|
+
]
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"type": "array",
|
|
246
|
+
"description": "Enhanced format: array of file objects with metadata",
|
|
247
|
+
"items": {
|
|
248
|
+
"type": "object",
|
|
249
|
+
"required": [
|
|
250
|
+
"path",
|
|
251
|
+
"format"
|
|
252
|
+
],
|
|
253
|
+
"properties": {
|
|
254
|
+
"path": {
|
|
255
|
+
"type": "string",
|
|
256
|
+
"description": "Relative path to file",
|
|
257
|
+
"examples": [
|
|
258
|
+
".claude/skills/tdd.md",
|
|
259
|
+
".cursor/rules/react.mdc",
|
|
260
|
+
".continue/rules/python.json"
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"format": {
|
|
264
|
+
"type": "string",
|
|
265
|
+
"description": "File format - the AI tool/platform this file is for",
|
|
266
|
+
"enum": [
|
|
267
|
+
"cursor",
|
|
268
|
+
"claude",
|
|
269
|
+
"continue",
|
|
270
|
+
"windsurf",
|
|
271
|
+
"copilot",
|
|
272
|
+
"kiro",
|
|
273
|
+
"agents.md",
|
|
274
|
+
"generic",
|
|
275
|
+
"mcp"
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
"subtype": {
|
|
279
|
+
"type": "string",
|
|
280
|
+
"description": "File subtype - the functional category",
|
|
281
|
+
"enum": [
|
|
282
|
+
"rule",
|
|
283
|
+
"agent",
|
|
284
|
+
"skill",
|
|
285
|
+
"slash-command",
|
|
286
|
+
"prompt",
|
|
287
|
+
"workflow",
|
|
288
|
+
"tool",
|
|
289
|
+
"template",
|
|
290
|
+
"collection"
|
|
291
|
+
]
|
|
292
|
+
},
|
|
293
|
+
"name": {
|
|
294
|
+
"type": "string",
|
|
295
|
+
"description": "Display name for this file",
|
|
296
|
+
"examples": [
|
|
297
|
+
"React Rules",
|
|
298
|
+
"Test-Driven Development"
|
|
299
|
+
]
|
|
300
|
+
},
|
|
301
|
+
"description": {
|
|
302
|
+
"type": "string",
|
|
303
|
+
"description": "Description of what this file does"
|
|
304
|
+
},
|
|
305
|
+
"tags": {
|
|
306
|
+
"type": "array",
|
|
307
|
+
"description": "File-specific tags",
|
|
308
|
+
"items": {
|
|
309
|
+
"type": "string"
|
|
310
|
+
},
|
|
311
|
+
"uniqueItems": true,
|
|
312
|
+
"examples": [
|
|
313
|
+
[
|
|
314
|
+
"react",
|
|
315
|
+
"typescript"
|
|
316
|
+
],
|
|
317
|
+
[
|
|
318
|
+
"testing",
|
|
319
|
+
"tdd"
|
|
320
|
+
]
|
|
321
|
+
]
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
"additionalProperties": false
|
|
325
|
+
},
|
|
326
|
+
"minItems": 1
|
|
327
|
+
}
|
|
328
|
+
]
|
|
329
|
+
},
|
|
330
|
+
"main": {
|
|
331
|
+
"type": "string",
|
|
332
|
+
"description": "Main entry file (for single-file packages)",
|
|
333
|
+
"examples": [
|
|
334
|
+
"index.md",
|
|
335
|
+
"skill.md"
|
|
336
|
+
]
|
|
337
|
+
},
|
|
338
|
+
"dependencies": {
|
|
339
|
+
"type": "object",
|
|
340
|
+
"description": "Package dependencies",
|
|
341
|
+
"patternProperties": {
|
|
342
|
+
"^(@[a-z0-9-]+\\/)?[a-z0-9-]+$": {
|
|
343
|
+
"type": "string",
|
|
344
|
+
"pattern": "^(\\^|~)?\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"additionalProperties": false,
|
|
348
|
+
"examples": [
|
|
349
|
+
{
|
|
350
|
+
"@pr-pm/utils": "^1.0.0",
|
|
351
|
+
"common-rules": "~2.1.0"
|
|
352
|
+
}
|
|
353
|
+
]
|
|
354
|
+
},
|
|
355
|
+
"peerDependencies": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"description": "Peer dependencies (packages that should be installed alongside)",
|
|
358
|
+
"patternProperties": {
|
|
359
|
+
"^(@[a-z0-9-]+\\/)?[a-z0-9-]+$": {
|
|
360
|
+
"type": "string"
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
"additionalProperties": false
|
|
364
|
+
},
|
|
365
|
+
"engines": {
|
|
366
|
+
"type": "object",
|
|
367
|
+
"description": "Required engine versions",
|
|
368
|
+
"properties": {
|
|
369
|
+
"prpm": {
|
|
370
|
+
"type": "string",
|
|
371
|
+
"description": "Required PRPM version"
|
|
372
|
+
},
|
|
373
|
+
"node": {
|
|
374
|
+
"type": "string",
|
|
375
|
+
"description": "Required Node.js version"
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
"additionalProperties": false,
|
|
379
|
+
"examples": [
|
|
380
|
+
{
|
|
381
|
+
"prpm": ">=1.0.0",
|
|
382
|
+
"node": ">=18.0.0"
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
},
|
|
386
|
+
"packages": {
|
|
387
|
+
"type": "array",
|
|
388
|
+
"description": "Array of packages to publish from a single manifest (multi-package publishing). Packages inherit top-level fields unless overridden.",
|
|
389
|
+
"items": {
|
|
390
|
+
"$ref": "#"
|
|
391
|
+
},
|
|
392
|
+
"minItems": 1
|
|
393
|
+
},
|
|
394
|
+
"collections": {
|
|
395
|
+
"type": "array",
|
|
396
|
+
"description": "Array of collections to publish. Collections bundle multiple packages together for easier installation.",
|
|
397
|
+
"items": {
|
|
398
|
+
"type": "object",
|
|
399
|
+
"required": ["id", "name", "description", "packages"],
|
|
400
|
+
"properties": {
|
|
401
|
+
"id": {
|
|
402
|
+
"type": "string",
|
|
403
|
+
"description": "Unique collection identifier (kebab-case)",
|
|
404
|
+
"pattern": "^[a-z0-9-]+$",
|
|
405
|
+
"minLength": 3,
|
|
406
|
+
"maxLength": 100,
|
|
407
|
+
"examples": ["nextjs-complete", "fullstack-setup", "react-essentials"]
|
|
408
|
+
},
|
|
409
|
+
"name": {
|
|
410
|
+
"type": "string",
|
|
411
|
+
"description": "Display name of the collection",
|
|
412
|
+
"minLength": 3,
|
|
413
|
+
"maxLength": 100,
|
|
414
|
+
"examples": ["Next.js Complete", "Full Stack Setup"]
|
|
415
|
+
},
|
|
416
|
+
"description": {
|
|
417
|
+
"type": "string",
|
|
418
|
+
"description": "What this collection provides",
|
|
419
|
+
"minLength": 10,
|
|
420
|
+
"maxLength": 500
|
|
421
|
+
},
|
|
422
|
+
"version": {
|
|
423
|
+
"type": "string",
|
|
424
|
+
"description": "Semantic version of the collection",
|
|
425
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$",
|
|
426
|
+
"examples": ["1.0.0", "2.1.0"]
|
|
427
|
+
},
|
|
428
|
+
"category": {
|
|
429
|
+
"type": "string",
|
|
430
|
+
"description": "Collection category",
|
|
431
|
+
"enum": ["development", "testing", "deployment", "data-science", "devops", "design", "documentation", "security", "performance", "general"],
|
|
432
|
+
"examples": ["development", "testing"]
|
|
433
|
+
},
|
|
434
|
+
"tags": {
|
|
435
|
+
"type": "array",
|
|
436
|
+
"description": "Tags for discoverability (kebab-case)",
|
|
437
|
+
"items": {
|
|
438
|
+
"type": "string",
|
|
439
|
+
"pattern": "^[a-z0-9-]+$"
|
|
440
|
+
},
|
|
441
|
+
"minItems": 1,
|
|
442
|
+
"maxItems": 10,
|
|
443
|
+
"examples": [["react", "typescript", "nextjs"], ["python", "data-science", "ml"]]
|
|
444
|
+
},
|
|
445
|
+
"icon": {
|
|
446
|
+
"type": "string",
|
|
447
|
+
"description": "Emoji or icon for the collection",
|
|
448
|
+
"maxLength": 10,
|
|
449
|
+
"examples": ["⚛️", "🚀", "📦"]
|
|
450
|
+
},
|
|
451
|
+
"packages": {
|
|
452
|
+
"type": "array",
|
|
453
|
+
"description": "Array of packages included in this collection",
|
|
454
|
+
"items": {
|
|
455
|
+
"type": "object",
|
|
456
|
+
"required": ["packageId"],
|
|
457
|
+
"properties": {
|
|
458
|
+
"packageId": {
|
|
459
|
+
"type": "string",
|
|
460
|
+
"description": "Package identifier to include",
|
|
461
|
+
"minLength": 1,
|
|
462
|
+
"examples": ["typescript-strict", "react-best-practices"]
|
|
463
|
+
},
|
|
464
|
+
"version": {
|
|
465
|
+
"type": "string",
|
|
466
|
+
"description": "Version range (semver) or 'latest'",
|
|
467
|
+
"examples": ["^1.0.0", "~2.1.0", "1.0.0", "latest"]
|
|
468
|
+
},
|
|
469
|
+
"required": {
|
|
470
|
+
"type": "boolean",
|
|
471
|
+
"description": "Whether this package is required (true) or optional (false)",
|
|
472
|
+
"default": true
|
|
473
|
+
},
|
|
474
|
+
"reason": {
|
|
475
|
+
"type": "string",
|
|
476
|
+
"description": "Explanation of why this package is included",
|
|
477
|
+
"maxLength": 200,
|
|
478
|
+
"examples": ["Enforces strict TypeScript type safety", "React component best practices"]
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
"minItems": 1
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
"minItems": 1
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
"additionalProperties": false,
|
|
490
|
+
"examples": [
|
|
491
|
+
{
|
|
492
|
+
"name": "@username/simple-package",
|
|
493
|
+
"version": "1.0.0",
|
|
494
|
+
"description": "A simple package with basic files",
|
|
495
|
+
"format": "claude", "subtype": "skill",
|
|
496
|
+
"author": "Your Name",
|
|
497
|
+
"license": "MIT",
|
|
498
|
+
"files": [
|
|
499
|
+
"skill.md",
|
|
500
|
+
"README.md"
|
|
501
|
+
]
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
"name": "@company/team-package",
|
|
505
|
+
"version": "1.0.0",
|
|
506
|
+
"description": "A package published under organization account",
|
|
507
|
+
"format": "cursor",
|
|
508
|
+
"author": "Team Name",
|
|
509
|
+
"organization": "my-company",
|
|
510
|
+
"license": "MIT",
|
|
511
|
+
"files": [
|
|
512
|
+
".cursor/rules/guidelines.mdc",
|
|
513
|
+
"README.md"
|
|
514
|
+
]
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"name": "@username/cursor-rules",
|
|
518
|
+
"version": "1.0.0",
|
|
519
|
+
"description": "Multiple Cursor rules for different languages",
|
|
520
|
+
"format": "cursor",
|
|
521
|
+
"author": {
|
|
522
|
+
"name": "Your Name",
|
|
523
|
+
"email": "you@example.com"
|
|
524
|
+
},
|
|
525
|
+
"license": "MIT",
|
|
526
|
+
"repository": "https://github.com/username/cursor-rules",
|
|
527
|
+
"tags": [
|
|
528
|
+
"cursor",
|
|
529
|
+
"rules",
|
|
530
|
+
"multi-language"
|
|
531
|
+
],
|
|
532
|
+
"files": [
|
|
533
|
+
{
|
|
534
|
+
"path": ".cursor/rules/typescript.mdc",
|
|
535
|
+
"format": "cursor",
|
|
536
|
+
"name": "TypeScript Rules",
|
|
537
|
+
"tags": [
|
|
538
|
+
"typescript",
|
|
539
|
+
"frontend"
|
|
540
|
+
]
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"path": ".cursor/rules/python.mdc",
|
|
544
|
+
"format": "cursor",
|
|
545
|
+
"name": "Python Rules",
|
|
546
|
+
"tags": [
|
|
547
|
+
"python",
|
|
548
|
+
"backend"
|
|
549
|
+
]
|
|
550
|
+
}
|
|
551
|
+
]
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
"name": "@community/testing-suite",
|
|
555
|
+
"version": "2.0.0",
|
|
556
|
+
"description": "Complete testing suite with skills and agents",
|
|
557
|
+
"format": "generic", "subtype": "collection",
|
|
558
|
+
"author": "Community",
|
|
559
|
+
"license": "MIT",
|
|
560
|
+
"tags": [
|
|
561
|
+
"testing",
|
|
562
|
+
"quality"
|
|
563
|
+
],
|
|
564
|
+
"files": [
|
|
565
|
+
{
|
|
566
|
+
"path": ".claude/skills/tdd.md",
|
|
567
|
+
"format": "claude", "subtype": "skill",
|
|
568
|
+
"name": "Test-Driven Development"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
"path": ".claude/agents/test-generator.md",
|
|
572
|
+
"format": "claude", "subtype": "agent",
|
|
573
|
+
"name": "Test Generator"
|
|
574
|
+
}
|
|
575
|
+
]
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"name": "@username/copilot-instructions",
|
|
579
|
+
"version": "1.0.0",
|
|
580
|
+
"description": "GitHub Copilot instructions for API development",
|
|
581
|
+
"format": "copilot",
|
|
582
|
+
"author": "Your Name",
|
|
583
|
+
"license": "MIT",
|
|
584
|
+
"tags": [
|
|
585
|
+
"copilot",
|
|
586
|
+
"api",
|
|
587
|
+
"backend"
|
|
588
|
+
],
|
|
589
|
+
"files": [
|
|
590
|
+
"api-guidelines.md"
|
|
591
|
+
]
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
"name": "@username/kiro-steering",
|
|
595
|
+
"version": "1.0.0",
|
|
596
|
+
"description": "Kiro steering file for testing standards",
|
|
597
|
+
"format": "kiro",
|
|
598
|
+
"author": "Your Name",
|
|
599
|
+
"license": "MIT",
|
|
600
|
+
"tags": [
|
|
601
|
+
"kiro",
|
|
602
|
+
"testing",
|
|
603
|
+
"quality"
|
|
604
|
+
],
|
|
605
|
+
"files": [
|
|
606
|
+
"testing.md"
|
|
607
|
+
]
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
"name": "@username/windsurf-rules",
|
|
611
|
+
"version": "1.0.0",
|
|
612
|
+
"description": "Windsurf coding rules for React projects",
|
|
613
|
+
"format": "windsurf",
|
|
614
|
+
"author": "Your Name",
|
|
615
|
+
"license": "MIT",
|
|
616
|
+
"tags": [
|
|
617
|
+
"windsurf",
|
|
618
|
+
"react",
|
|
619
|
+
"frontend"
|
|
620
|
+
],
|
|
621
|
+
"files": [
|
|
622
|
+
".windsurfrules"
|
|
623
|
+
]
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
"name": "@company/private-package",
|
|
627
|
+
"version": "1.0.0",
|
|
628
|
+
"description": "A private package only accessible to organization members",
|
|
629
|
+
"format": "claude",
|
|
630
|
+
"subtype": "skill",
|
|
631
|
+
"author": "Company Team",
|
|
632
|
+
"organization": "my-company",
|
|
633
|
+
"private": true,
|
|
634
|
+
"license": "Proprietary",
|
|
635
|
+
"files": [
|
|
636
|
+
"internal-skill.md",
|
|
637
|
+
"README.md"
|
|
638
|
+
]
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"name": "@username/multi-package-example",
|
|
642
|
+
"version": "1.0.0",
|
|
643
|
+
"description": "Multi-package manifest example",
|
|
644
|
+
"author": "Your Name",
|
|
645
|
+
"license": "MIT",
|
|
646
|
+
"repository": "https://github.com/username/multi-package",
|
|
647
|
+
"packages": [
|
|
648
|
+
{
|
|
649
|
+
"name": "@username/package-one",
|
|
650
|
+
"version": "1.0.0",
|
|
651
|
+
"description": "First package in the multi-package manifest",
|
|
652
|
+
"format": "claude",
|
|
653
|
+
"subtype": "skill",
|
|
654
|
+
"files": [
|
|
655
|
+
"package-one/SKILL.md"
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
"name": "@username/package-two",
|
|
660
|
+
"version": "1.0.0",
|
|
661
|
+
"description": "Second package with different settings",
|
|
662
|
+
"format": "cursor",
|
|
663
|
+
"private": true,
|
|
664
|
+
"files": [
|
|
665
|
+
"package-two/.cursor/rules/main.mdc"
|
|
666
|
+
]
|
|
667
|
+
}
|
|
668
|
+
]
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
"name": "@username/multi-package-with-collection",
|
|
672
|
+
"version": "1.0.0",
|
|
673
|
+
"description": "Repository with both packages and a collection",
|
|
674
|
+
"author": "Your Name",
|
|
675
|
+
"license": "MIT",
|
|
676
|
+
"packages": [
|
|
677
|
+
{
|
|
678
|
+
"name": "typescript-rules",
|
|
679
|
+
"version": "1.0.0",
|
|
680
|
+
"description": "TypeScript coding standards",
|
|
681
|
+
"format": "cursor",
|
|
682
|
+
"subtype": "rule",
|
|
683
|
+
"tags": ["typescript", "cursor"],
|
|
684
|
+
"files": [".cursor/rules/typescript.mdc"]
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
"name": "react-patterns",
|
|
688
|
+
"version": "1.0.0",
|
|
689
|
+
"description": "React best practices",
|
|
690
|
+
"format": "claude",
|
|
691
|
+
"subtype": "skill",
|
|
692
|
+
"tags": ["react", "best-practices"],
|
|
693
|
+
"files": [".claude/skills/react-patterns/SKILL.md"]
|
|
694
|
+
}
|
|
695
|
+
],
|
|
696
|
+
"collections": [
|
|
697
|
+
{
|
|
698
|
+
"id": "fullstack-setup",
|
|
699
|
+
"name": "Full Stack Setup",
|
|
700
|
+
"description": "Complete full-stack development setup with TypeScript and React",
|
|
701
|
+
"version": "1.0.0",
|
|
702
|
+
"category": "development",
|
|
703
|
+
"tags": ["typescript", "react", "fullstack"],
|
|
704
|
+
"icon": "🚀",
|
|
705
|
+
"packages": [
|
|
706
|
+
{
|
|
707
|
+
"packageId": "typescript-rules",
|
|
708
|
+
"version": "^1.0.0",
|
|
709
|
+
"required": true,
|
|
710
|
+
"reason": "TypeScript coding standards for the project"
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"packageId": "react-patterns",
|
|
714
|
+
"version": "^1.0.0",
|
|
715
|
+
"required": true,
|
|
716
|
+
"reason": "React component best practices"
|
|
717
|
+
}
|
|
718
|
+
]
|
|
719
|
+
}
|
|
720
|
+
]
|
|
721
|
+
}
|
|
722
|
+
]
|
|
723
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prpm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Prompt Package Manager CLI - Install and manage prompt-based files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@octokit/rest": "^22.0.0",
|
|
48
|
-
"@pr-pm/converters": "^
|
|
49
|
-
"@pr-pm/registry-client": "^
|
|
50
|
-
"@pr-pm/types": "^0.
|
|
48
|
+
"@pr-pm/converters": "^1.0.2",
|
|
49
|
+
"@pr-pm/registry-client": "^2.0.2",
|
|
50
|
+
"@pr-pm/types": "^1.0.2",
|
|
51
51
|
"ajv": "^8.17.1",
|
|
52
52
|
"ajv-formats": "^3.0.1",
|
|
53
53
|
"commander": "^11.1.0",
|