@promptframe/cli 0.1.57 → 0.1.63

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.
Files changed (42) hide show
  1. package/README.md +19 -1
  2. package/dist/development-build-worker.d.ts +2 -0
  3. package/dist/development-build-worker.d.ts.map +1 -0
  4. package/dist/development-build-worker.js +184 -0
  5. package/dist/development-build-worker.js.map +1 -0
  6. package/dist/development-build.d.ts +22 -0
  7. package/dist/development-build.d.ts.map +1 -0
  8. package/dist/development-build.js +66 -0
  9. package/dist/development-build.js.map +1 -0
  10. package/dist/development-coordinator.d.ts +26 -0
  11. package/dist/development-coordinator.d.ts.map +1 -0
  12. package/dist/development-coordinator.js +114 -0
  13. package/dist/development-coordinator.js.map +1 -0
  14. package/dist/development-css.d.ts +10 -0
  15. package/dist/development-css.d.ts.map +1 -0
  16. package/dist/development-css.js +65 -0
  17. package/dist/development-css.js.map +1 -0
  18. package/dist/development-files.d.ts +6 -0
  19. package/dist/development-files.d.ts.map +1 -0
  20. package/dist/development-files.js +70 -0
  21. package/dist/development-files.js.map +1 -0
  22. package/dist/development-process.d.ts +15 -0
  23. package/dist/development-process.d.ts.map +1 -0
  24. package/dist/development-process.js +65 -0
  25. package/dist/development-process.js.map +1 -0
  26. package/dist/development-revisions.d.ts +58 -0
  27. package/dist/development-revisions.d.ts.map +1 -0
  28. package/dist/development-revisions.js +130 -0
  29. package/dist/development-revisions.js.map +1 -0
  30. package/dist/development-validation.d.ts +22 -0
  31. package/dist/development-validation.d.ts.map +1 -0
  32. package/dist/development-validation.js +122 -0
  33. package/dist/development-validation.js.map +1 -0
  34. package/dist/development-workspace.d.ts +25 -0
  35. package/dist/development-workspace.d.ts.map +1 -0
  36. package/dist/development-workspace.js +352 -0
  37. package/dist/development-workspace.js.map +1 -0
  38. package/dist/index.js +72 -203
  39. package/dist/index.js.map +1 -1
  40. package/dist/lifecycle.js +4 -4
  41. package/dist/lifecycle.js.map +1 -1
  42. package/package.json +10 -4
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { basename, dirname, extname, join, relative, resolve } from 'node:path';
8
8
  import { inflateRawSync } from 'node:zlib';
9
9
  import { COMPONENT_MANIFEST_SCHEMA_VERSION, COMPONENT_PUBLIC_RESOURCES_CONTRACT_VERSION, COMPONENT_REF_VERSION, COMPONENT_STANDARD_SOURCE_HASH, COMPONENT_STANDARD_VERSION, PROMPTFRAME_AUTHORING_STANDARD_RELEASE, PROMPTFRAME_PUBLIC_RESOURCE_LIMITS, PROMPTFRAME_PUBLIC_RESOURCE_POLICY, PROMPTFRAME_PUBLIC_SECURITY_POLICY, PROMPTFRAME_PUBLIC_SECURITY_POLICY_DIGEST, PROMPTFRAME_PUBLIC_STANDARD_POLICY, PROMPTFRAME_LAYOUT_POLICY_RULE_IDS, PROMPTFRAME_CONTRACTS_VERSION, PROMPTFRAME_PUBLIC_DEPENDENCY_POLICY, detectPromptFrameUnknownCustomStyleProps, evaluatePromptFrameLayoutPolicy, evaluatePromptFrameDependencyPolicy, authoringUploadTargetSchema, parseComponentManifest, } from '@promptframe/contracts';
10
10
  import { evaluatePromptFrameSecurityPolicySource, } from '@promptframe/contracts/security-evaluator';
11
+ import { evaluatePromptFrameSchemaSource, } from '@promptframe/contracts/schema-evaluator';
11
12
  import { applyPackageChanges, buildFreshnessDecision, computePackageChanges, computePackageFreshnessDiagnostics, computeScaffoldFreshnessDiagnostics, resolveLocalPreviewScript, } from './lifecycle.js';
12
13
  import { evaluateLocalReusability, reusabilityDiagnostics, } from './reusability.js';
13
14
  import { assertPreviewEnvelope, writeLocalPreviewReport, } from './preview-report.js';
@@ -470,6 +471,11 @@ function preview(argv) {
470
471
  console.log(`Run: npm run ${previewScript}`);
471
472
  }
472
473
  async function dev(argv) {
474
+ const workspaceRoot = autoWorkspaceRoot(argv);
475
+ if (workspaceRoot) {
476
+ await devWorkspace(workspaceRoot, argv);
477
+ return;
478
+ }
473
479
  const input = resolveComponentInput(argv);
474
480
  const dir = input.dir;
475
481
  const target = resolveUploadTarget(argv);
@@ -518,6 +524,48 @@ async function dev(argv) {
518
524
  return;
519
525
  await runDevServer(dir, devCommand);
520
526
  }
527
+ async function devWorkspace(root, argv) {
528
+ const studioOrigin = valueAfter(argv, '--studio-origin')
529
+ ?? fail('Workspace dev requires --studio-origin <exact-origin> for its local connection.', 'dev.workspace.origin_required', 2);
530
+ const host = valueAfter(argv, '--host') ?? '127.0.0.1';
531
+ const port = Number(valueAfter(argv, '--port') ?? '0');
532
+ if ((host !== '127.0.0.1' && host !== '::1') || !Number.isSafeInteger(port) || port < 0 || port > 65535) {
533
+ fail('Workspace dev binds one explicit loopback address and port (0 chooses one actual free port).', 'dev.workspace.address_invalid', 2);
534
+ }
535
+ const workspace = readWorkspaceConfig(root);
536
+ if (hasFlag(argv, '--json') && !hasFlag(argv, '--dry-run')) {
537
+ fail('dev --json requires --dry-run so stdout remains machine-readable.', 'dev.json_requires_dry_run');
538
+ }
539
+ if (hasFlag(argv, '--dry-run')) {
540
+ printJson({ command: 'dev.workspace', workspace: workspaceSummary(root), modules: workspace.components,
541
+ host, port, studioOrigin, status: 'declared', checked: false, playerLoaded: false });
542
+ return;
543
+ }
544
+ // Lazy import keeps ordinary validate/check free of a Vite server lifecycle.
545
+ const { startDevelopmentWorkspace } = await import('./development-workspace.js');
546
+ let stop;
547
+ const stopped = new Promise(resolve => { stop = resolve; });
548
+ process.once('SIGINT', stop);
549
+ process.once('SIGTERM', stop);
550
+ try {
551
+ const server = await startDevelopmentWorkspace({ root, modules: workspace.components, studioOrigin, host, port });
552
+ try {
553
+ // This short-lived credential is for explicit local tooling, never an
554
+ // application login token or something to embed in component code.
555
+ printJson({ command: 'dev.workspace', contractVersion: 'promptframe-development.v1',
556
+ connectionId: server.connectionId, url: server.url, studioOrigin: server.studioOrigin,
557
+ credential: server.credential, expiresAt: server.expiresAt, playerLoaded: false });
558
+ await stopped;
559
+ }
560
+ finally {
561
+ await server.close();
562
+ }
563
+ }
564
+ finally {
565
+ process.removeListener('SIGINT', stop);
566
+ process.removeListener('SIGTERM', stop);
567
+ }
568
+ }
521
569
  function packageComponent(argv) {
522
570
  const input = resolveComponentInput(argv);
523
571
  const artifact = packageDirectory(input.dir, valueAfter(argv, '--out'));
@@ -1619,6 +1667,7 @@ const POSITIONAL_VALUE_FLAGS = new Set([
1619
1667
  '--endpoint',
1620
1668
  '--expires-at',
1621
1669
  '--host',
1670
+ '--studio-origin',
1622
1671
  '--id',
1623
1672
  '--level',
1624
1673
  '--name',
@@ -3232,8 +3281,10 @@ function validatePreviewProps(dir, manifest) {
3232
3281
  const preview = readPreviewProps(dir);
3233
3282
  assertPreviewEnvelope(preview, 'src/preview-props.json', fail);
3234
3283
  assertPreviewDurationMatchesManifest(preview, manifest);
3235
- assertPreviewPropsMatchStaticSchema(dir, manifest, preview);
3236
- assertStaticPropsHaveDescriptions(readIfExists(join(dir, manifest.entry.propsSchemaPath)), manifest.entry.propsSchemaPath);
3284
+ const schemaFacts = evaluatePromptFrameSchemaSource(readIfExists(join(dir, manifest.entry.propsSchemaPath)));
3285
+ assertStaticSchemaResolved(schemaFacts, manifest.entry.propsSchemaPath);
3286
+ assertPreviewPropsMatchStaticSchema(manifest, preview, schemaFacts);
3287
+ assertStaticPropsHaveDescriptions(schemaFacts, manifest.entry.propsSchemaPath);
3237
3288
  }
3238
3289
  function assertPreviewDurationMatchesManifest(preview, manifest) {
3239
3290
  const durationFrames = Number(preview.durationFrames);
@@ -3250,12 +3301,12 @@ function readPreviewProps(dir) {
3250
3301
  }
3251
3302
  return preview;
3252
3303
  }
3253
- function assertPreviewPropsMatchStaticSchema(dir, manifest, preview) {
3304
+ function assertPreviewPropsMatchStaticSchema(manifest, preview, schemaFacts) {
3254
3305
  const previewProps = asRecord(preview.props) ?? {};
3255
3306
  const previewPropNames = Object.keys(previewProps);
3256
3307
  if (previewPropNames.length === 0)
3257
3308
  return;
3258
- const schemaKeys = extractStaticZodObjectKeys(readIfExists(join(dir, manifest.entry.propsSchemaPath)));
3309
+ const schemaKeys = new Set(schemaFacts.propKeys);
3259
3310
  if (schemaKeys.size === 0)
3260
3311
  return;
3261
3312
  const unknown = previewPropNames.filter((name) => !schemaKeys.has(name));
@@ -3263,210 +3314,25 @@ function assertPreviewPropsMatchStaticSchema(dir, manifest, preview) {
3263
3314
  return;
3264
3315
  fail(`src/preview-props.json props include fields not declared in ${manifest.entry.propsSchemaPath}: ${unknown.join(', ')}`, 'component_standard.preview_props.unknown_prop');
3265
3316
  }
3266
- function extractStaticZodObjectKeys(source) {
3267
- return new Set(extractStaticZodObjectProps(source).map((prop) => prop.key));
3268
- }
3269
- function extractStaticZodObjectProps(source) {
3270
- const openBrace = findPropsSchemaZodObjectOpenBrace(source) ?? findFirstZodObjectOpenBrace(source);
3271
- if (openBrace < 0)
3272
- return [];
3273
- const closeBrace = findMatchingBrace(source, openBrace);
3274
- if (closeBrace < 0)
3275
- return [];
3276
- return collectTopLevelObjectProps(source.slice(openBrace + 1, closeBrace));
3317
+ function assertStaticSchemaResolved(facts, sourcePath) {
3318
+ if (facts.status === 'resolved')
3319
+ return;
3320
+ const diagnostic = facts.diagnostics.find((item) => item.code !== 'schema.props_schema_not_static');
3321
+ // Legacy zero-prop fixtures may omit propsSchema entirely. Preserve that compatibility,
3322
+ // while any declared but unresolved schema remains fail-visible.
3323
+ if (!diagnostic)
3324
+ return;
3325
+ const location = diagnostic ? ` at ${diagnostic.line}:${diagnostic.column}` : '';
3326
+ const prop = diagnostic?.propPath ? ` for ${diagnostic.propPath}` : '';
3327
+ fail(`${sourcePath} could not be resolved by ${facts.evaluatorVersion}${prop}${location}: ${diagnostic?.message ?? 'schema is not static'}`, 'component_standard.props.schema_unresolved', 1, 'Use inline Zod expressions, named static schemas, an official PromptFrame helper, or a locally provable transparent wrapper. Unknown/dynamic wrappers are not executed or guessed.');
3277
3328
  }
3278
- function assertStaticPropsHaveDescriptions(source, sourcePath) {
3279
- const missingProps = extractStaticZodObjectProps(source)
3280
- .filter((prop) => !hasStaticZodDescription(prop.valueSource))
3281
- .map((prop) => prop.key);
3329
+ function assertStaticPropsHaveDescriptions(facts, sourcePath) {
3330
+ const missingProps = facts.propKeys.filter((key) => !facts.properties[key]?.description?.trim());
3282
3331
  if (missingProps.length === 0)
3283
3332
  return;
3284
3333
  const missingText = missingProps.join(', ');
3285
3334
  fail(`${sourcePath} props must include readable descriptions for: ${missingText}.`, 'component_standard.props.description_missing', 1, 'Add .describe("...") to each public propsSchema field, or provide equivalent metadata.parameterDescriptions before upload.');
3286
3335
  }
3287
- function hasStaticZodDescription(source) {
3288
- return /\.describe\s*\(\s*(?:"[^"]+"|'[^']+'|`[^`]+`)\s*\)/m.test(source);
3289
- }
3290
- function findPropsSchemaZodObjectOpenBrace(source) {
3291
- const propsSchemaMatch = /\bpropsSchema\s*=\s*z\s*\.\s*object\s*\(/.exec(source);
3292
- if (!propsSchemaMatch)
3293
- return undefined;
3294
- const openParen = source.indexOf('(', propsSchemaMatch.index);
3295
- if (openParen < 0)
3296
- return undefined;
3297
- const openBrace = nextNonWhitespaceIndex(source, openParen + 1);
3298
- return openBrace >= 0 && source[openBrace] === '{' ? openBrace : undefined;
3299
- }
3300
- function findFirstZodObjectOpenBrace(source) {
3301
- const objectCallMatch = /\bz\s*\.\s*object\s*\(/.exec(source);
3302
- if (!objectCallMatch)
3303
- return -1;
3304
- const openParen = source.indexOf('(', objectCallMatch.index);
3305
- if (openParen < 0)
3306
- return -1;
3307
- const openBrace = nextNonWhitespaceIndex(source, openParen + 1);
3308
- return openBrace >= 0 && source[openBrace] === '{' ? openBrace : -1;
3309
- }
3310
- function nextNonWhitespaceIndex(source, start) {
3311
- for (let index = start; index < source.length; index += 1) {
3312
- if (!/\s/.test(source[index]))
3313
- return index;
3314
- }
3315
- return -1;
3316
- }
3317
- function findMatchingBrace(source, openIndex) {
3318
- let depth = 0;
3319
- let quote;
3320
- let escaped = false;
3321
- for (let index = openIndex; index < source.length; index += 1) {
3322
- const char = source[index];
3323
- const next = source[index + 1];
3324
- if (quote) {
3325
- if (escaped) {
3326
- escaped = false;
3327
- }
3328
- else if (char === '\\') {
3329
- escaped = true;
3330
- }
3331
- else if (char === quote) {
3332
- quote = undefined;
3333
- }
3334
- continue;
3335
- }
3336
- if (char === '/' && next === '/') {
3337
- index = skipLineComment(source, index + 2);
3338
- continue;
3339
- }
3340
- if (char === '/' && next === '*') {
3341
- index = skipBlockComment(source, index + 2);
3342
- continue;
3343
- }
3344
- if (char === '"' || char === '\'' || char === '`') {
3345
- quote = char;
3346
- continue;
3347
- }
3348
- if (char === '{')
3349
- depth += 1;
3350
- if (char === '}') {
3351
- depth -= 1;
3352
- if (depth === 0)
3353
- return index;
3354
- }
3355
- }
3356
- return -1;
3357
- }
3358
- function collectTopLevelObjectProps(body) {
3359
- const props = [];
3360
- let index = 0;
3361
- while (index < body.length) {
3362
- index = skipWhitespaceAndCommas(body, index);
3363
- if (index >= body.length)
3364
- break;
3365
- if (body.startsWith('...', index)) {
3366
- index = skipTopLevelValue(body, index + 3);
3367
- continue;
3368
- }
3369
- const keyResult = readObjectKey(body, index);
3370
- if (!keyResult) {
3371
- index += 1;
3372
- continue;
3373
- }
3374
- index = skipWhitespaceAndCommas(body, keyResult.nextIndex);
3375
- if (body[index] === ':') {
3376
- const valueStart = index + 1;
3377
- const valueEnd = skipTopLevelValue(body, valueStart);
3378
- props.push({
3379
- key: keyResult.key,
3380
- valueSource: body.slice(valueStart, valueEnd),
3381
- });
3382
- index = valueEnd;
3383
- continue;
3384
- }
3385
- index = keyResult.nextIndex;
3386
- }
3387
- return props;
3388
- }
3389
- function skipWhitespaceAndCommas(source, start) {
3390
- let index = start;
3391
- while (index < source.length && (/[\s,]/.test(source[index])))
3392
- index += 1;
3393
- return index;
3394
- }
3395
- function readObjectKey(source, start) {
3396
- const char = source[start];
3397
- if (char === '"' || char === '\'') {
3398
- let escaped = false;
3399
- let value = '';
3400
- for (let index = start + 1; index < source.length; index += 1) {
3401
- const current = source[index];
3402
- if (escaped) {
3403
- value += current;
3404
- escaped = false;
3405
- continue;
3406
- }
3407
- if (current === '\\') {
3408
- escaped = true;
3409
- continue;
3410
- }
3411
- if (current === char)
3412
- return { key: value, nextIndex: index + 1 };
3413
- value += current;
3414
- }
3415
- return undefined;
3416
- }
3417
- const identifier = /^[A-Za-z_$][\w$]*/.exec(source.slice(start));
3418
- if (!identifier)
3419
- return undefined;
3420
- return { key: identifier[0], nextIndex: start + identifier[0].length };
3421
- }
3422
- function skipTopLevelValue(source, start) {
3423
- let depth = 0;
3424
- let quote;
3425
- let escaped = false;
3426
- for (let index = start; index < source.length; index += 1) {
3427
- const char = source[index];
3428
- const next = source[index + 1];
3429
- if (quote) {
3430
- if (escaped) {
3431
- escaped = false;
3432
- }
3433
- else if (char === '\\') {
3434
- escaped = true;
3435
- }
3436
- else if (char === quote) {
3437
- quote = undefined;
3438
- }
3439
- continue;
3440
- }
3441
- if (char === '/' && next === '/') {
3442
- index = skipLineComment(source, index + 2);
3443
- continue;
3444
- }
3445
- if (char === '/' && next === '*') {
3446
- index = skipBlockComment(source, index + 2);
3447
- continue;
3448
- }
3449
- if (char === '"' || char === '\'' || char === '`') {
3450
- quote = char;
3451
- continue;
3452
- }
3453
- if (char === '(' || char === '[' || char === '{')
3454
- depth += 1;
3455
- if (char === ')' || char === ']' || char === '}')
3456
- depth -= 1;
3457
- if (char === ',' && depth <= 0)
3458
- return index + 1;
3459
- }
3460
- return source.length;
3461
- }
3462
- function skipLineComment(source, start) {
3463
- const nextLine = source.indexOf('\n', start);
3464
- return nextLine < 0 ? source.length : nextLine;
3465
- }
3466
- function skipBlockComment(source, start) {
3467
- const end = source.indexOf('*/', start);
3468
- return end < 0 ? source.length : end + 1;
3469
- }
3470
3336
  function evaluateDirectoryReusability(dir, manifest, uploadTarget) {
3471
3337
  return evaluateLocalReusability({
3472
3338
  manifest,
@@ -3672,7 +3538,9 @@ function assertZipPropsHaveDescriptions(path) {
3672
3538
  const schemaEntry = readZipEntry(zip, (entryName) => isComponentSourceZipEntry(entryName, manifest.entry.propsSchemaPath));
3673
3539
  if (!schemaEntry)
3674
3540
  return;
3675
- assertStaticPropsHaveDescriptions(schemaEntry.toString('utf8'), manifest.entry.propsSchemaPath);
3541
+ const facts = evaluatePromptFrameSchemaSource(schemaEntry.toString('utf8'));
3542
+ assertStaticSchemaResolved(facts, manifest.entry.propsSchemaPath);
3543
+ assertStaticPropsHaveDescriptions(facts, manifest.entry.propsSchemaPath);
3676
3544
  }
3677
3545
  function packageArtifactFromZip(path) {
3678
3546
  const file = readFileSync(path);
@@ -4432,6 +4300,7 @@ Commands:
4432
4300
  preview <dir> Validate and print local Remotion preview envelope
4433
4301
  --write-local-report Write .promptframe/local-previews/preview-report.json
4434
4302
  dev <dir> Start the local Remotion Player preview server
4303
+ --studio-origin <origin> Required for a multi-component workspace's checked-module connection
4435
4304
  package <dir> --out <zip> Validate and package a component source zip
4436
4305
  upload <dir|zip> Upload component source package to PromptFrame
4437
4306
  --target <target> marketplace_authoring or project_private_generation