@roughapp/feature 0.2.0 → 0.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.
Files changed (5) hide show
  1. package/CHANGELOG.md +220 -0
  2. package/README.md +100 -24
  3. package/index.d.ts +177 -29
  4. package/index.js +15 -15
  5. package/package.json +3 -2
package/index.d.ts CHANGED
@@ -307,35 +307,167 @@ type Sprite = {
307
307
  publishedSpriteBuildId: SpriteBuildId | null;
308
308
  };
309
309
 
310
- type SurfaceDefinition = {
311
- key: string;
310
+ /**
311
+ * An immutable, project-independent surface contract.
312
+ *
313
+ * A definition holds no client, project id, server surface id, registration
314
+ * state, subscription, or lifecycle hook. That is what lets the same value be
315
+ * handed to two clients for two different projects at once: each resolves it
316
+ * against its own project and caches the canonical id privately.
317
+ */
318
+ type RoughSurfaceDefinition<TKey extends string = string, TTools extends readonly AnyTool[] = readonly AnyTool[]> = Readonly<{
319
+ key: TKey;
312
320
  name: string;
313
321
  description: string;
314
- toolList: readonly AnyTool[];
322
+ tools: TTools;
323
+ }>;
324
+ type DefineRoughSurfaceOptions<TKey extends string, TTools extends readonly AnyTool[]> = {
325
+ key: TKey;
326
+ name: string;
327
+ description: string;
328
+ tools: TTools;
315
329
  };
316
- declare const defineSurface: (config: SurfaceDefinition) => SurfaceDefinition;
317
-
318
- declare const getRoughFeatures: (surface: SurfaceDefinition, callback: (features: Sprite[]) => void) => (() => void);
330
+ declare const defineRoughSurface: <const TKey extends string, const TTools extends readonly AnyTool[]>(options: DefineRoughSurfaceOptions<TKey, TTools>) => RoughSurfaceDefinition<TKey, TTools>;
319
331
 
320
332
  type FetchUserTokenFn = () => string | Promise<string>;
321
333
 
322
- type SurfaceEntry = {
323
- surfaceId: SurfaceId;
324
- toolList: readonly AnyTool[];
325
- };
326
- declare const registerSurfaceEntry: (key: string, entry: SurfaceEntry) => (() => void);
327
-
328
- type InitRoughOptions = {
329
- baseUrl?: string;
334
+ type RoughClientOptions = {
330
335
  projectId: string;
336
+ baseUrl?: string;
331
337
  fetchUserToken: FetchUserTokenFn;
332
338
  };
333
- declare const initRough: (options: InitRoughOptions) => void;
339
+ /**
340
+ * A handle to one project's live Rough runtime.
341
+ *
342
+ * The client is an opaque capability: it exposes identity and lifecycle, not
343
+ * behavior. Behavior lives in the package's function exports, which take the
344
+ * client in their options.
345
+ */
346
+ type RoughClient = {
347
+ readonly projectId: string;
348
+ destroy: () => Promise<void>;
349
+ };
350
+ /**
351
+ * Creates and immediately starts a client for one Rough project.
352
+ *
353
+ * Returns synchronously so a framework provider can own the value in the same
354
+ * tick it renders, and so a client whose auth or Replicache startup is still
355
+ * pending can still be destroyed. Startup runs in the background; observe it
356
+ * with `whenRoughClientReady({ client })` if you need to.
357
+ *
358
+ * The host owns the result until it calls `client.destroy()`. There is no
359
+ * release, restart, or reuse: a failed client is destroyed and replaced.
360
+ */
361
+ declare const createRoughClient: (options: RoughClientOptions) => RoughClient;
362
+ /**
363
+ * Awaits the client's eager startup.
364
+ *
365
+ * Rejects with the retained startup error if it failed. Operations do this
366
+ * internally, so hosts only need it when they want to show startup state or
367
+ * when a test needs a deterministic point to await.
368
+ */
369
+ declare const whenRoughClientReady: (options: {
370
+ client: RoughClient;
371
+ }) => Promise<void>;
372
+
373
+ /**
374
+ * Errors that hosts are expected to branch on.
375
+ *
376
+ * These are exported from the package root so a host can distinguish "you used
377
+ * a client you already destroyed" (a programming error) from "another client
378
+ * already owns this local database" (a coordination error the host fixes by
379
+ * sharing one client).
380
+ */
381
+ /** Thrown when an operation is started on a destroying or destroyed client. */
382
+ declare class RoughClientDestroyedError extends Error {
383
+ readonly name = "RoughClientDestroyedError";
384
+ constructor(message?: string);
385
+ }
386
+ /**
387
+ * Thrown during startup when another live client in this JavaScript realm
388
+ * already owns the `<baseUrl, projectId, personId>` Replicache identity.
389
+ */
390
+ declare class RoughReplicacheIdentityConflictError extends Error {
391
+ readonly name = "RoughReplicacheIdentityConflictError";
392
+ readonly replicacheName: string;
393
+ constructor(options: {
394
+ replicacheName: string;
395
+ });
396
+ }
397
+ /**
398
+ * Thrown when two concurrent operations disagree about the serialized contract
399
+ * of one surface key on the same client.
400
+ */
401
+ declare class RoughSurfaceContractConflictError extends Error {
402
+ readonly name = "RoughSurfaceContractConflictError";
403
+ readonly surfaceKey: string;
404
+ constructor(options: {
405
+ surfaceKey: string;
406
+ });
407
+ }
408
+ /**
409
+ * Rejection value of `client.destroy()` when at least one cleanup stage failed.
410
+ *
411
+ * `destroy()` always attempts every stage, so this is reported only after all
412
+ * of them have settled. `errors` holds one entry per failed stage.
413
+ */
414
+ declare class RoughClientDestroyError extends Error {
415
+ readonly name = "RoughClientDestroyError";
416
+ readonly errors: readonly Error[];
417
+ constructor(options: {
418
+ errors: readonly Error[];
419
+ });
420
+ }
421
+ /** Thrown when a value that is not a Rough client is passed as `client`. */
422
+ declare class RoughInvalidClientError extends Error {
423
+ readonly name = "RoughInvalidClientError";
424
+ constructor(message?: string);
425
+ }
426
+
427
+ /**
428
+ * Every cleanup handle in the public API has this shape.
429
+ *
430
+ * It is a promise rather than `void` on purpose. Un-awaitable teardown is what
431
+ * lets Replicache closes, store watches, and mounted modals outlive the thing
432
+ * that owned them, which shows up as work still running during a test
433
+ * environment teardown long after the assertions passed. Calling a cleanup
434
+ * twice is always safe: the second call returns the first call's promise.
435
+ */
436
+ type RoughCleanup = () => Promise<void>;
437
+
438
+ type GetRoughFeaturesOptions = {
439
+ client: RoughClient;
440
+ surface: RoughSurfaceDefinition;
441
+ onFeatures: (features: Sprite[]) => void;
442
+ onError?: (error: Error) => void;
443
+ signal?: AbortSignal;
444
+ };
445
+ type RoughFeatureSubscription = {
446
+ /**
447
+ * Resolves after the first feature batch is published. Rejects if startup or
448
+ * surface resolution failed.
449
+ */
450
+ readonly ready: Promise<void>;
451
+ unsubscribe: RoughCleanup;
452
+ };
453
+ /** Subscribes to published features for a surface. */
454
+ declare const getRoughFeatures: (options: GetRoughFeaturesOptions) => RoughFeatureSubscription;
334
455
 
335
456
  type OpenRoughCreateOptions = {
336
- projectId?: string;
457
+ client: RoughClient;
458
+ surface: RoughSurfaceDefinition;
459
+ /** Portal target. Use when Rough theme variables are scoped below document.body. */
460
+ target?: HTMLElement;
461
+ signal?: AbortSignal;
337
462
  };
338
- declare const openRoughCreate: (surface: SurfaceDefinition, options?: OpenRoughCreateOptions) => void;
463
+ type RoughModalHandle = {
464
+ close: RoughCleanup;
465
+ };
466
+ /**
467
+ * Opens the Feature Builder for a surface. Resolves the surface itself, so no
468
+ * `<RoughSurface>` need be mounted first.
469
+ */
470
+ declare const openRoughCreate: (options: OpenRoughCreateOptions) => Promise<RoughModalHandle>;
339
471
 
340
472
  type Props$9 = {
341
473
  children?: Snippet;
@@ -377,18 +509,21 @@ declare const ResizeHandle: svelte.Component<Props$8, {}, "">;
377
509
  type ResizeHandle = ReturnType<typeof ResizeHandle>;
378
510
 
379
511
  type Props$7 = {
380
- toolList: readonly AnyTool[];
512
+ client: RoughClient;
513
+ surface: RoughSurfaceDefinition;
381
514
  surfaceId: SurfaceId;
382
- projectId?: string;
515
+ /** Portal target; use when Rough theme variables are scoped to a subtree. */
516
+ portalTarget?: HTMLElement;
383
517
  onclose?: () => void;
384
518
  };
385
519
  declare const RoughCreateModal: svelte.Component<Props$7, {}, "">;
386
520
  type RoughCreateModal = ReturnType<typeof RoughCreateModal>;
387
521
 
388
522
  type Props$6 = {
389
- toolList: readonly AnyTool[];
523
+ client: RoughClient;
524
+ surface: RoughSurfaceDefinition;
525
+ spriteId: SpriteId;
390
526
  label?: string;
391
- spriteId: string;
392
527
  };
393
528
  declare const RoughEditButton: svelte.Component<Props$6, {}, "">;
394
529
  type RoughEditButton = ReturnType<typeof RoughEditButton>;
@@ -407,16 +542,18 @@ type SpriteFrameDatastoreContext = {
407
542
  };
408
543
 
409
544
  type Props$5 = {
545
+ client: RoughClient;
546
+ surface: RoughSurfaceDefinition;
410
547
  featureId: SpriteId;
411
548
  buildId: SpriteBuildId;
412
- surfaceKey: string;
413
549
  datastore?: SpriteFrameDatastore;
414
550
  };
415
551
  declare const RoughFeature: svelte.Component<Props$5, {}, "">;
416
552
  type RoughFeature = ReturnType<typeof RoughFeature>;
417
553
 
418
554
  type Props$4 = {
419
- surface: SurfaceDefinition;
555
+ client: RoughClient;
556
+ surface: RoughSurfaceDefinition;
420
557
  getDatastore?: (context: SpriteFrameDatastoreContext) => SpriteFrameDatastore | undefined;
421
558
  };
422
559
  declare const RoughSurface: svelte.Component<Props$4, {}, "">;
@@ -440,16 +577,16 @@ declare const SecondaryButton: svelte.Component<Props$3, {}, "">;
440
577
  type SecondaryButton = ReturnType<typeof SecondaryButton>;
441
578
 
442
579
  type Props$2 = {
580
+ client: RoughClient;
443
581
  surfaceId: SurfaceId;
444
582
  onselect?: (sprite: Sprite, spriteBuild: SpriteBuild) => Promise<void> | void;
445
583
  };
446
584
  declare const SpriteBuildMenu: svelte.Component<Props$2, {}, "">;
447
585
  type SpriteBuildMenu = ReturnType<typeof SpriteBuildMenu>;
448
586
 
449
- type Props$1 = {
587
+ type BaseProps = {
450
588
  spriteId: string;
451
589
  spriteBuildId: SpriteBuildId;
452
- artifactUrl?: string;
453
590
  toolList: readonly AnyTool[];
454
591
  datastore?: SpriteFrameDatastore;
455
592
  isMock?: boolean;
@@ -457,12 +594,23 @@ type Props$1 = {
457
594
  minHeight?: number;
458
595
  maxHeight?: number;
459
596
  };
597
+ /** A client is required unless artifactUrl is provided explicitly. */
598
+ type Props$1 = BaseProps & ({
599
+ artifactUrl: string;
600
+ client?: undefined;
601
+ } | {
602
+ artifactUrl?: undefined;
603
+ client: RoughClient;
604
+ });
460
605
  declare const SpriteFrame: svelte.Component<Props$1, {}, "">;
461
606
  type SpriteFrame = ReturnType<typeof SpriteFrame>;
462
607
 
463
608
  type Props = {
464
- toolList: readonly AnyTool[];
465
- spriteId: string;
609
+ client: RoughClient;
610
+ surface: RoughSurfaceDefinition;
611
+ spriteId: SpriteId;
612
+ /** Where the dialog attaches. Decides which `--rough-*` values it inherits. */
613
+ portalTarget?: HTMLElement;
466
614
  onclose?: () => void;
467
615
  };
468
616
  declare const RoughEditModal: svelte.Component<Props, {}, "">;
@@ -494,5 +642,5 @@ declare global {
494
642
  }
495
643
  }
496
644
 
497
- export { Mutation, PrimaryButton, Query, ResizeHandle, RoughCreateModal, RoughEditButton, RoughFeature, RoughSurface, SecondaryButton, SpriteBuildMenu, SpriteFrame, Subscription, defineSurface, getRoughFeatures, initRough, openRoughCreate, registerSurfaceEntry };
498
- export type { JsonValue, RoughCreateModalElement, RoughEditButtonElement, RoughEditModalElement, RoughFeatureElement, RoughSurfaceElement, Sprite, SpriteBuild, SpriteFrameDatastore, SpriteFrameDatastoreContext, SurfaceDefinition };
645
+ export { Mutation, PrimaryButton, Query, ResizeHandle, RoughClientDestroyError, RoughClientDestroyedError, RoughCreateModal, RoughEditButton, RoughFeature, RoughInvalidClientError, RoughReplicacheIdentityConflictError, RoughSurface, RoughSurfaceContractConflictError, SecondaryButton, SpriteBuildMenu, SpriteFrame, Subscription, createRoughClient, defineRoughSurface, getRoughFeatures, openRoughCreate, whenRoughClientReady };
646
+ export type { FetchUserTokenFn, GetRoughFeaturesOptions, JsonValue, OpenRoughCreateOptions, RoughCleanup, RoughClient, RoughClientOptions, RoughCreateModalElement, RoughEditButtonElement, RoughEditModalElement, RoughFeatureElement, RoughFeatureSubscription, RoughModalHandle, RoughSurfaceDefinition, RoughSurfaceElement, Sprite, SpriteBuild, SpriteFrameDatastore, SpriteFrameDatastoreContext };