@fern-api/generator-cli 0.9.17 → 0.9.19
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/api.d.ts +49 -291
- package/dist/api.js +3105 -8070
- package/dist/cli.js +13210 -13241
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ForgetOptions, ForgetResult, BootstrapResult, ResolveResult, ReplayReport, StatusResult } from '@fern-api/replay';
|
|
2
2
|
export { ConflictDetail, DiffStat, ForgetOptions, ForgetResult, MatchedPatch, ReplayReport, ResolveResult, StatusGeneration, StatusPatch, StatusResult } from '@fern-api/replay';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
|
|
@@ -480,291 +480,6 @@ interface GithubReleaseParams {
|
|
|
480
480
|
}
|
|
481
481
|
declare function githubRelease(params: GithubReleaseParams): Promise<void>;
|
|
482
482
|
|
|
483
|
-
/**
|
|
484
|
-
* Logger interface for pipeline steps.
|
|
485
|
-
* Abstracts away the logging implementation so steps work with both
|
|
486
|
-
* the CLI's TaskContext and the standalone CLI subprocess (console).
|
|
487
|
-
*/
|
|
488
|
-
interface PipelineLogger {
|
|
489
|
-
debug(message: string): void;
|
|
490
|
-
info(message: string): void;
|
|
491
|
-
warn(message: string): void;
|
|
492
|
-
error(message: string): void;
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* Default logger implementation using stderr (to avoid mixing with JSON result output on stdout).
|
|
496
|
-
*/
|
|
497
|
-
declare const consolePipelineLogger: PipelineLogger;
|
|
498
|
-
|
|
499
|
-
interface ReplayRunParams {
|
|
500
|
-
outputDir: string;
|
|
501
|
-
cliVersion?: string;
|
|
502
|
-
generatorVersions?: Record<string, string>;
|
|
503
|
-
/** Don't commit, just stage changes. Default: false */
|
|
504
|
-
stageOnly?: boolean;
|
|
505
|
-
/** Generator name for namespaced tag lookup (e.g. "fernapi/fern-typescript-node-sdk") */
|
|
506
|
-
generatorName?: string;
|
|
507
|
-
/** Commit generation + update lockfile, skip patch detection/application */
|
|
508
|
-
skipApplication?: boolean;
|
|
509
|
-
/** Optional logger for diagnostic output */
|
|
510
|
-
logger?: PipelineLogger;
|
|
511
|
-
}
|
|
512
|
-
interface ReplayRunResult {
|
|
513
|
-
/** null if replay wasn't initialized (no lockfile) */
|
|
514
|
-
report: ReplayReport | null;
|
|
515
|
-
/** Whether .fernignore was updated */
|
|
516
|
-
fernignoreUpdated: boolean;
|
|
517
|
-
/** SHA of the [fern-generated] commit before this replay run (null if first generation or unreadable) */
|
|
518
|
-
previousGenerationSha: string | null;
|
|
519
|
-
/** SHA of the [fern-generated] commit created by this replay run (null if replay didn't run or unreadable) */
|
|
520
|
-
currentGenerationSha: string | null;
|
|
521
|
-
/** SHA of main's HEAD before replay ran. Always on main's lineage, stable after squash merges. */
|
|
522
|
-
baseBranchHead: string | null;
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* Opaque handle returned by `replayPrepare()` and consumed by `replayApply()`.
|
|
526
|
-
*
|
|
527
|
-
* Between prepare and apply, HEAD is at the new `[fern-generated]` commit (or unchanged
|
|
528
|
-
* for dry-run / skip-application terminals). Consumers MAY land additional commits on
|
|
529
|
-
* HEAD (e.g. `[fern-autoversion]`) — apply will run patches on top of current HEAD at
|
|
530
|
-
* call time while rebasing stored patches against the pure `[fern-generated]` tree.
|
|
531
|
-
*
|
|
532
|
-
* If apply is never reached, the working tree has the new `[fern-generated]` commit
|
|
533
|
-
* but the lockfile is stale. Callers MUST either call apply (which advances the
|
|
534
|
-
* lockfile) or reset HEAD to `previousGenerationSha`.
|
|
535
|
-
*/
|
|
536
|
-
interface PreparedReplay {
|
|
537
|
-
/** @internal Service instance carrying in-memory state across phases. */
|
|
538
|
-
_service: ReplayService;
|
|
539
|
-
/** @internal Preparation state handed to the service's apply phase. */
|
|
540
|
-
_preparation: ReplayPreparation;
|
|
541
|
-
/** Working tree / git repo the replay operates on. */
|
|
542
|
-
outputDir: string;
|
|
543
|
-
/** Flow selected by the service during prepare. */
|
|
544
|
-
flow: ReplayPreparation["flow"];
|
|
545
|
-
/** SHA of the `[fern-generated]` commit before this run; null if no prior generation. */
|
|
546
|
-
previousGenerationSha: string | null;
|
|
547
|
-
/** SHA of the new `[fern-generated]` commit created by prepare (or prior HEAD for dry-run terminals). */
|
|
548
|
-
currentGenerationSha: string;
|
|
549
|
-
/** SHA of main's HEAD captured before prepare mutated anything. */
|
|
550
|
-
baseBranchHead: string | null;
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* Backwards-compatible atomic entry point. Composes `replayPrepare` +
|
|
554
|
-
* `replayApply` with byte-identical behavior for existing callers.
|
|
555
|
-
*/
|
|
556
|
-
declare function replayRun(params: ReplayRunParams): Promise<ReplayRunResult>;
|
|
557
|
-
|
|
558
|
-
interface PipelineConfig {
|
|
559
|
-
outputDir: string;
|
|
560
|
-
replay?: ReplayStepConfig;
|
|
561
|
-
autoVersion?: AutoVersionStepConfig;
|
|
562
|
-
fernignore?: FernignoreStepConfig;
|
|
563
|
-
github?: GithubStepConfig;
|
|
564
|
-
cliVersion?: string;
|
|
565
|
-
generatorVersions?: Record<string, string>;
|
|
566
|
-
generatorName?: string;
|
|
567
|
-
}
|
|
568
|
-
interface PipelineContext {
|
|
569
|
-
previousStepResults: {
|
|
570
|
-
generationCommit?: GenerationCommitStepResult;
|
|
571
|
-
replay?: ReplayStepResult;
|
|
572
|
-
autoVersion?: AutoVersionStepResult;
|
|
573
|
-
fernignore?: FernignoreStepResult;
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Result of running replayPrepare(). Holds the opaque PreparedReplay handle that
|
|
578
|
-
* downstream steps (AutoVersionStep, ReplayStep) consume.
|
|
579
|
-
*
|
|
580
|
-
* `preparedReplay` is null when replay isn't initialized for this repo (no
|
|
581
|
-
* lockfile) or when prepare failed — the pipeline proceeds without replay in
|
|
582
|
-
* both cases.
|
|
583
|
-
*/
|
|
584
|
-
interface GenerationCommitStepResult extends StepResult {
|
|
585
|
-
/** Opaque handle consumed by ReplayStep's apply phase. Imported at the import site to avoid circular deps. */
|
|
586
|
-
preparedReplay?: PreparedReplay | null;
|
|
587
|
-
previousGenerationSha?: string;
|
|
588
|
-
currentGenerationSha?: string;
|
|
589
|
-
baseBranchHead?: string;
|
|
590
|
-
/** Flow selected by the replay service during prepare. */
|
|
591
|
-
flow?: "first-generation" | "no-patches" | "normal-regeneration" | "skip-application";
|
|
592
|
-
}
|
|
593
|
-
interface ReplayStepConfig {
|
|
594
|
-
enabled: boolean;
|
|
595
|
-
stageOnly?: boolean;
|
|
596
|
-
skipApplication?: boolean;
|
|
597
|
-
}
|
|
598
|
-
interface AutoVersionStepConfig {
|
|
599
|
-
enabled: boolean;
|
|
600
|
-
/** Generator language: typescript | python | java | go | ruby | csharp | php | swift | rust | kotlin */
|
|
601
|
-
language: string;
|
|
602
|
-
/** Existing changelog content passed to the AI for context. */
|
|
603
|
-
priorChangelog?: string;
|
|
604
|
-
/** Fallback version when no prior generation exists (first run). Defaults to "0.0.1" (or "v0.0.1" for Go). */
|
|
605
|
-
baseVersion?: string;
|
|
606
|
-
/**
|
|
607
|
-
* BAML AI service configuration (provider + model). Required when `enabled: true` — without it,
|
|
608
|
-
* AnalyzeSdkDiff calls will fail and the step will fall back to a PATCH bump.
|
|
609
|
-
* Shape matches `generatorsYml.AiServicesSchema` from @fern-api/configuration; typed structurally
|
|
610
|
-
* to avoid pulling the configuration package into generator-cli's dep graph.
|
|
611
|
-
*/
|
|
612
|
-
ai?: AutoVersionAiConfig;
|
|
613
|
-
/** Optional Fern API token passed through to BAML client configuration if needed by the provider. */
|
|
614
|
-
fernToken?: string;
|
|
615
|
-
/** Spec repository commit message included as additional AI context. */
|
|
616
|
-
specCommitMessage?: string;
|
|
617
|
-
/** When true, strips "🌿 Generated with Fern" trailers from commit messages (whitelabel customers). */
|
|
618
|
-
isWhitelabel?: boolean;
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* Minimal shape for the BAML AI service configuration. Structural equivalent of
|
|
622
|
-
* `generatorsYml.AiServicesSchema` from @fern-api/configuration.
|
|
623
|
-
*/
|
|
624
|
-
interface AutoVersionAiConfig {
|
|
625
|
-
provider: string;
|
|
626
|
-
model: string;
|
|
627
|
-
}
|
|
628
|
-
interface FernignoreStepConfig {
|
|
629
|
-
enabled: boolean;
|
|
630
|
-
customContents?: string;
|
|
631
|
-
}
|
|
632
|
-
interface GithubStepConfig {
|
|
633
|
-
enabled: boolean;
|
|
634
|
-
/** GitHub repository URI (e.g. "owner/repo") */
|
|
635
|
-
uri: string;
|
|
636
|
-
/** GitHub auth token */
|
|
637
|
-
token: string;
|
|
638
|
-
/** Output mode */
|
|
639
|
-
mode: "push" | "pull-request";
|
|
640
|
-
/** Target branch (base branch for PRs, push target for push mode) */
|
|
641
|
-
branch?: string;
|
|
642
|
-
/** Commit message for the generation */
|
|
643
|
-
commitMessage?: string;
|
|
644
|
-
/** User-facing changelog entry for PR body. When present, used instead of commit message body. */
|
|
645
|
-
changelogEntry?: string;
|
|
646
|
-
/** Structured PR description with Before/After code fences for breaking changes. Takes priority over changelogEntry for PR body. */
|
|
647
|
-
prDescription?: string;
|
|
648
|
-
/** One-sentence justification for WHY the version bump was chosen. Shown only for breaking changes. */
|
|
649
|
-
versionBumpReason?: string;
|
|
650
|
-
/** The previous SDK version before this change (e.g. "1.2.3"). Used for version header in PR body. */
|
|
651
|
-
previousVersion?: string;
|
|
652
|
-
/** The new SDK version after this change (e.g. "1.3.0"). Used for version header in PR body. */
|
|
653
|
-
newVersion?: string;
|
|
654
|
-
/** The version bump level: MAJOR, MINOR, or PATCH. Used for version header formatting. */
|
|
655
|
-
versionBump?: string;
|
|
656
|
-
/** Skip push/PR creation, just prepare branches locally */
|
|
657
|
-
previewMode?: boolean;
|
|
658
|
-
/** Generator name for namespaced fern-generation-base tag */
|
|
659
|
-
generatorName?: string;
|
|
660
|
-
/** Explicit override: whether replay already created commits (derived from replay context if omitted) */
|
|
661
|
-
skipCommit?: boolean;
|
|
662
|
-
/** Explicit override: replay conflict info (derived from replay context if omitted) */
|
|
663
|
-
replayConflictInfo?: {
|
|
664
|
-
previousGenerationSha: string;
|
|
665
|
-
currentGenerationSha: string;
|
|
666
|
-
};
|
|
667
|
-
/** When true: separate PRs per generation, automerge support, run_id in body */
|
|
668
|
-
automationMode?: boolean;
|
|
669
|
-
/** When true: skip opening a PR / pushing when the generated output has no diff from the base branch. */
|
|
670
|
-
skipIfNoDiff?: boolean;
|
|
671
|
-
/** Enable GitHub automerge on the PR (only effective when automationMode && !hasBreakingChanges) */
|
|
672
|
-
autoMerge?: boolean;
|
|
673
|
-
/** Pre-computed: version bump is MAJOR (from --version AUTO AI analysis) */
|
|
674
|
-
hasBreakingChanges?: boolean;
|
|
675
|
-
/** Human-readable breaking changes summary for PR body (from autoVersioningPrDescription on MAJOR) */
|
|
676
|
-
breakingChangesSummary?: string;
|
|
677
|
-
/** FERN_RUN_ID for cross-repo correlation (set by GitHub Action) */
|
|
678
|
-
runId?: string;
|
|
679
|
-
}
|
|
680
|
-
interface PipelineResult {
|
|
681
|
-
success: boolean;
|
|
682
|
-
steps: {
|
|
683
|
-
generationCommit?: GenerationCommitStepResult;
|
|
684
|
-
replay?: ReplayStepResult;
|
|
685
|
-
autoVersion?: AutoVersionStepResult;
|
|
686
|
-
fernignore?: FernignoreStepResult;
|
|
687
|
-
github?: GithubStepResult;
|
|
688
|
-
};
|
|
689
|
-
errors?: string[];
|
|
690
|
-
warnings?: string[];
|
|
691
|
-
}
|
|
692
|
-
interface ReplayStepResult extends StepResult {
|
|
693
|
-
flow?: "first-generation" | "no-patches" | "normal-regeneration" | "skip-application";
|
|
694
|
-
patchesDetected?: number;
|
|
695
|
-
patchesApplied?: number;
|
|
696
|
-
patchesWithConflicts?: number;
|
|
697
|
-
patchesAbsorbed?: number;
|
|
698
|
-
patchesRepointed?: number;
|
|
699
|
-
patchesContentRebased?: number;
|
|
700
|
-
patchesKeptAsUserOwned?: number;
|
|
701
|
-
previousGenerationSha?: string;
|
|
702
|
-
currentGenerationSha?: string;
|
|
703
|
-
baseBranchHead?: string;
|
|
704
|
-
unresolvedPatches?: Array<{
|
|
705
|
-
patchId: string;
|
|
706
|
-
patchMessage: string;
|
|
707
|
-
files: string[];
|
|
708
|
-
conflictDetails: Array<{
|
|
709
|
-
file: string;
|
|
710
|
-
conflictReason?: string;
|
|
711
|
-
}>;
|
|
712
|
-
}>;
|
|
713
|
-
warnings?: string[];
|
|
714
|
-
}
|
|
715
|
-
interface FernignoreStepResult extends StepResult {
|
|
716
|
-
pathsPreserved?: string[];
|
|
717
|
-
}
|
|
718
|
-
interface AutoVersionStepResult extends StepResult {
|
|
719
|
-
/** The new version to use (e.g. "1.2.3"). Field name matches fiddle's Java AutoVersionResult DTO. */
|
|
720
|
-
version?: string;
|
|
721
|
-
/** Commit subject for the `[fern-autoversion]` commit. */
|
|
722
|
-
commitMessage?: string;
|
|
723
|
-
/** User-facing changelog entry appended to changelog.md. */
|
|
724
|
-
changelogEntry?: string;
|
|
725
|
-
/** Prior SDK version before this change (e.g. "1.2.2"). */
|
|
726
|
-
previousVersion?: string;
|
|
727
|
-
/** The version bump level determined by FAI. */
|
|
728
|
-
versionBump?: "MAJOR" | "MINOR" | "PATCH" | "NO_CHANGE";
|
|
729
|
-
/** Structured PR description with Before/After code fences for breaking changes. */
|
|
730
|
-
prDescription?: string;
|
|
731
|
-
/** One-sentence justification for WHY the version bump was chosen. */
|
|
732
|
-
versionBumpReason?: string;
|
|
733
|
-
/** SHA of the `[fern-autoversion]` commit once it's been made. TS-only; no fiddle counterpart. */
|
|
734
|
-
commitSha?: string;
|
|
735
|
-
}
|
|
736
|
-
interface GithubStepResult extends StepResult {
|
|
737
|
-
commitSha?: string;
|
|
738
|
-
branchUrl?: string;
|
|
739
|
-
prUrl?: string;
|
|
740
|
-
prNumber?: number;
|
|
741
|
-
updatedExistingPr?: boolean;
|
|
742
|
-
generationBaseTagSha?: string;
|
|
743
|
-
/** True when generation produced no changes vs base branch — PR skipped */
|
|
744
|
-
skippedNoDiff?: boolean;
|
|
745
|
-
/** True when automerge was enabled on the PR */
|
|
746
|
-
autoMergeEnabled?: boolean;
|
|
747
|
-
}
|
|
748
|
-
interface StepResult {
|
|
749
|
-
executed: boolean;
|
|
750
|
-
success: boolean;
|
|
751
|
-
errorMessage?: string;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
declare class PostGenerationPipeline {
|
|
755
|
-
private readonly config;
|
|
756
|
-
private readonly logger;
|
|
757
|
-
private steps;
|
|
758
|
-
constructor(config: PipelineConfig, logger?: PipelineLogger);
|
|
759
|
-
run(): Promise<PipelineResult>;
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
declare function logReplaySummary(result: ReplayStepResult, logger: PipelineLogger): void;
|
|
763
|
-
declare function formatReplayPrBody(result: ReplayStepResult | undefined, options?: {
|
|
764
|
-
branchName?: string;
|
|
765
|
-
repoUri?: string;
|
|
766
|
-
}): string | undefined;
|
|
767
|
-
|
|
768
483
|
interface ReplayForgetParams {
|
|
769
484
|
/** Directory containing the SDK (where .fern/replay.lock lives) */
|
|
770
485
|
outputDir: string;
|
|
@@ -792,10 +507,10 @@ interface ReplayInitResult {
|
|
|
792
507
|
bootstrap: BootstrapResult;
|
|
793
508
|
/** Raw lockfile YAML content, present when bootstrap succeeded and not dry-run */
|
|
794
509
|
lockfileContent?: string;
|
|
795
|
-
/** Raw replay.yml content, present only when fernignore migration created it */
|
|
796
|
-
replayYmlContent?: string;
|
|
797
510
|
/** Fernignore entries that the server should ensure exist */
|
|
798
511
|
fernignoreEntries: string[];
|
|
512
|
+
/** Gitattributes entries the server should ensure exist (e.g. linguist-generated markers) */
|
|
513
|
+
gitattributesEntries: string[];
|
|
799
514
|
/** Generated PR body markdown for the server to use */
|
|
800
515
|
prBody?: string;
|
|
801
516
|
}
|
|
@@ -808,8 +523,8 @@ interface ReplayInitResult {
|
|
|
808
523
|
* Flow:
|
|
809
524
|
* 1. Clone the SDK repo (read-only)
|
|
810
525
|
* 2. Run bootstrap() to scan history and create lockfile
|
|
811
|
-
* 3.
|
|
812
|
-
* 4.
|
|
526
|
+
* 3. Read lockfile content from disk
|
|
527
|
+
* 4. Return lockfile + fernignore/gitattributes entries for Fiddle to apply server-side
|
|
813
528
|
*/
|
|
814
529
|
declare function replayInit(params: ReplayInitParams): Promise<ReplayInitResult>;
|
|
815
530
|
interface BootstrapLogEntry {
|
|
@@ -831,6 +546,49 @@ interface ReplayResolveParams {
|
|
|
831
546
|
}
|
|
832
547
|
declare function replayResolve(params: ReplayResolveParams): Promise<ResolveResult>;
|
|
833
548
|
|
|
549
|
+
/**
|
|
550
|
+
* Logger interface for pipeline steps.
|
|
551
|
+
* Abstracts away the logging implementation so steps work with both
|
|
552
|
+
* the CLI's TaskContext and the standalone CLI subprocess (console).
|
|
553
|
+
*/
|
|
554
|
+
interface PipelineLogger {
|
|
555
|
+
debug(message: string): void;
|
|
556
|
+
info(message: string): void;
|
|
557
|
+
warn(message: string): void;
|
|
558
|
+
error(message: string): void;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
interface ReplayRunParams {
|
|
562
|
+
outputDir: string;
|
|
563
|
+
cliVersion?: string;
|
|
564
|
+
generatorVersions?: Record<string, string>;
|
|
565
|
+
/** Don't commit, just stage changes. Default: false */
|
|
566
|
+
stageOnly?: boolean;
|
|
567
|
+
/** Generator name for namespaced tag lookup (e.g. "fernapi/fern-typescript-node-sdk") */
|
|
568
|
+
generatorName?: string;
|
|
569
|
+
/** Commit generation + update lockfile, skip patch detection/application */
|
|
570
|
+
skipApplication?: boolean;
|
|
571
|
+
/** Optional logger for diagnostic output */
|
|
572
|
+
logger?: PipelineLogger;
|
|
573
|
+
}
|
|
574
|
+
interface ReplayRunResult {
|
|
575
|
+
/** null if replay wasn't initialized (no lockfile) */
|
|
576
|
+
report: ReplayReport | null;
|
|
577
|
+
/** Whether .fernignore was updated */
|
|
578
|
+
fernignoreUpdated: boolean;
|
|
579
|
+
/** SHA of the [fern-generated] commit before this replay run (null if first generation or unreadable) */
|
|
580
|
+
previousGenerationSha: string | null;
|
|
581
|
+
/** SHA of the [fern-generated] commit created by this replay run (null if replay didn't run or unreadable) */
|
|
582
|
+
currentGenerationSha: string | null;
|
|
583
|
+
/** SHA of main's HEAD before replay ran. Always on main's lineage, stable after squash merges. */
|
|
584
|
+
baseBranchHead: string | null;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Backwards-compatible atomic entry point. Composes `replayPrepare` +
|
|
588
|
+
* `replayApply` with byte-identical behavior for existing callers.
|
|
589
|
+
*/
|
|
590
|
+
declare function replayRun(params: ReplayRunParams): Promise<ReplayRunResult>;
|
|
591
|
+
|
|
834
592
|
interface ReplayStatusParams {
|
|
835
593
|
/** Directory containing the SDK (where .fern/replay.lock lives) */
|
|
836
594
|
outputDir: string;
|
|
@@ -881,4 +639,4 @@ declare class ReplaySubmitError extends Error {
|
|
|
881
639
|
constructor(message: string, statusCode?: number);
|
|
882
640
|
}
|
|
883
641
|
|
|
884
|
-
export { type BootstrapLogEntry, type GenerateReadmeParams, type GenerateReadmeToStreamParams, type GenerateReferenceParams, type GenerateReferenceToStreamParams, type GithubPrParams, type GithubPushParams, type GithubReleaseParams, type
|
|
642
|
+
export { type BootstrapLogEntry, type GenerateReadmeParams, type GenerateReadmeToStreamParams, type GenerateReferenceParams, type GenerateReferenceToStreamParams, type GithubPrParams, type GithubPushParams, type GithubReleaseParams, type ReplayForgetParams, type ReplayInitParams, type ReplayInitResult, type ReplayResolveParams, type ReplayRunParams, type ReplayRunResult, type ReplayStatusParams, ReplaySubmitError, type SubmitReplayInitParams, type SubmitReplayInitResult, formatBootstrapSummary, generateReadme, generateReadmeToStream, generateReference, generateReferenceToStream, githubPr, githubPush, githubRelease, parseOwnerRepo, replayForget, replayInit, replayResolve, replayRun, replayStatus, submitReplayInit };
|