@forgerock/login-framework-cli 0.0.0-beta.0 → 0.1.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 (51) hide show
  1. package/README.md +107 -34
  2. package/dist/{commands → src/commands}/generate.d.ts +3 -2
  3. package/dist/{commands → src/commands}/generate.js +15 -8
  4. package/dist/src/commands/init.d.ts +16 -0
  5. package/dist/{commands → src/commands}/init.js +8 -10
  6. package/dist/{commands → src/commands}/source.d.ts +1 -1
  7. package/dist/{commands → src/commands}/update.d.ts +4 -2
  8. package/dist/{commands → src/commands}/update.js +7 -6
  9. package/dist/{config → src/config}/version.d.ts +1 -4
  10. package/dist/{config → src/config}/version.js +1 -2
  11. package/dist/src/main.js +61 -0
  12. package/dist/src/mcp.d.ts +52 -0
  13. package/dist/src/mcp.js +182 -0
  14. package/dist/{services → src/services}/registry.js +2 -2
  15. package/dist/{services → src/services}/release.d.ts +2 -1
  16. package/dist/src/templates/callback/__COMPONENT_SLUG__.mock.ts +22 -0
  17. package/dist/src/templates/callback/__COMPONENT_SLUG__.stories.js +28 -0
  18. package/dist/src/templates/callback/__COMPONENT_SLUG__.story.svelte +59 -0
  19. package/dist/src/templates/callback/__COMPONENT_SLUG__.svelte +49 -0
  20. package/dist/src/templates/callback/__COMPONENT_SLUG__.utilities.test.ts +9 -0
  21. package/dist/{templates → src/templates}/callback/__COMPONENT_SLUG__.utilities.ts +1 -1
  22. package/dist/src/templates/stage/__COMPONENT_SLUG__.mock.ts +23 -0
  23. package/dist/src/templates/stage/__COMPONENT_SLUG__.stories.js +43 -0
  24. package/dist/src/templates/stage/__COMPONENT_SLUG__.story.svelte +47 -0
  25. package/dist/{templates → src/templates}/stage/__COMPONENT_SLUG__.svelte +21 -19
  26. package/dist/src/templates/stage/__COMPONENT_SLUG__.utilities.test.ts +9 -0
  27. package/dist/{templates → src/templates}/stage/__COMPONENT_SLUG__.utilities.ts +1 -1
  28. package/dist/src/templates/tsconfig.json +18 -0
  29. package/dist/src/utils.d.ts +11 -0
  30. package/dist/src/utils.js +17 -0
  31. package/package.json +13 -10
  32. package/dist/commands/init.d.ts +0 -8
  33. package/dist/main.js +0 -34
  34. package/dist/templates/callback/__COMPONENT_SLUG__.svelte +0 -73
  35. package/dist/templates/callback/__COMPONENT_SLUG__.utilities.test.ts +0 -9
  36. package/dist/templates/stage/__COMPONENT_SLUG__.utilities.test.ts +0 -9
  37. package/dist/utils.d.ts +0 -2
  38. package/dist/utils.js +0 -4
  39. package/scripts/generate-registry.mjs +0 -23
  40. package/dist/{commands → src/commands}/releases.d.ts +0 -0
  41. package/dist/{commands → src/commands}/releases.js +0 -0
  42. package/dist/{commands → src/commands}/source.js +0 -0
  43. package/dist/{config → src/config}/exclusions.d.ts +0 -0
  44. package/dist/{config → src/config}/exclusions.js +0 -0
  45. package/dist/{errors.d.ts → src/errors.d.ts} +8 -8
  46. package/dist/{errors.js → src/errors.js} +2 -2
  47. package/dist/{main.d.ts → src/main.d.ts} +0 -0
  48. package/dist/{services → src/services}/file-system.d.ts +1 -1
  49. package/dist/{services → src/services}/file-system.js +2 -2
  50. package/dist/{services → src/services}/registry.d.ts +1 -1
  51. package/dist/{services → src/services}/release.js +1 -1
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@forgerock/login-framework-cli",
3
- "version": "0.0.0-beta.0",
3
+ "version": "0.1.0",
4
4
  "description": "CLI tool for scaffolding and managing Ping Login Widget and Login App custom component projects",
5
5
  "type": "module",
6
- "exports": "./dist/main.js",
7
- "main": "./dist/main.js",
8
- "module": "./dist/main.js",
6
+ "exports": {
7
+ ".": "./dist/src/main.js"
8
+ },
9
+ "main": "./dist/src/main.js",
10
+ "module": "./dist/src/main.js",
9
11
  "bin": {
10
- "ping-lf": "./dist/main.js"
12
+ "ping-lf": "./dist/src/main.js"
11
13
  },
12
14
  "files": [
13
- "dist",
14
- "scripts"
15
+ "dist"
15
16
  ],
16
17
  "keywords": [
17
18
  "ping-identity",
@@ -35,6 +36,7 @@
35
36
  "access": "public"
36
37
  },
37
38
  "dependencies": {
39
+ "@effect/ai": "^0.35.0",
38
40
  "@effect/cli": "^0.75.0",
39
41
  "@effect/platform": "^0.96.0",
40
42
  "@effect/platform-node": "^0.106.0",
@@ -42,14 +44,15 @@
42
44
  "@effect/printer-ansi": "^0.49.0",
43
45
  "@effect/typeclass": "^0.40.0",
44
46
  "effect": "^3.21.0",
45
- "tar": "^7.5.13"
47
+ "svelte": "^5.55.7",
48
+ "tar": "^7.5.21"
46
49
  },
47
50
  "devDependencies": {
48
51
  "typescript": "^5.2.2",
49
- "vitest": "^3.0.0"
52
+ "vitest": "^3.2.6"
50
53
  },
51
54
  "scripts": {
52
- "build": "rm -rf dist && tsc && chmod +x dist/main.js && ([ -d templates ] && cp -r templates/ dist/templates/ || true)",
55
+ "build": "rm -rf dist && tsc -p tsconfig.json && chmod +x dist/src/main.js && ([ -d templates ] && cp -r templates/ dist/src/templates/ || true)",
53
56
  "dev": "tsc --watch",
54
57
  "test": "vitest run",
55
58
  "test:watch": "vitest"
@@ -1,8 +0,0 @@
1
- import { Command } from '@effect/cli';
2
- import { FileSystem, Path } from '@effect/platform';
3
- import { DirectoryConflictError, DirectoryNotEmptyError } from '../errors.js';
4
- export declare const initCommand: Command.Command<"init", FileSystem.FileSystem | Path.Path | import("../services/release.js").Release, import("../errors.js").InvalidVersionError | import("../errors.js").ReleaseNetworkError | import("../errors.js").ReleaseParseError | import("../errors.js").ReleaseFsError | import("../errors.js").FileSystemError | import("../errors.js").RegistryScanError | DirectoryConflictError | DirectoryNotEmptyError | import("@effect/platform/Error").PlatformError, {
5
- readonly directory: string;
6
- readonly local: import("effect/Option").Option<string>;
7
- readonly version: import("effect/Option").Option<string>;
8
- }>;
package/dist/main.js DELETED
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Command } from '@effect/cli';
3
- import { NodeContext, NodeRuntime } from '@effect/platform-node';
4
- import { Console, Effect } from 'effect';
5
- import { createRequire } from 'node:module';
6
- import { initCommand } from './commands/init.js';
7
- import { generateCommand } from './commands/generate.js';
8
- import { releasesCommand } from './commands/releases.js';
9
- import { updateCommand } from './commands/update.js';
10
- import { GithubReleaseLayer } from './services/release.js';
11
- // Read the version from package.json at runtime so it stays in sync
12
- // with the published package version after changesets bumps it.
13
- const { version } = createRequire(import.meta.url)('../package.json');
14
- const rootCommand = Command.make('ping-lf').pipe(Command.withDescription('CLI for initializing, scaffolding, and updating Ping Login Widget and Login App custom component projects.'), Command.withSubcommands([initCommand, generateCommand, updateCommand, releasesCommand]));
15
- const cli = Command.run(rootCommand, {
16
- name: 'ping-lf',
17
- version,
18
- });
19
- cli(process.argv).pipe(Effect.catchTag('DirectoryConflictError', (err) => Console.error(`\nError: "${err.path}" already contains a framework project.` +
20
- `\n Did you mean to use --local?\n` +
21
- `\n ping-lf init <new-directory> --local ${err.path}\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('DirectoryNotEmptyError', (err) => Console.error(`\nError: "${err.path}" already exists and is not empty.` +
22
- `\n Choose a different directory name, or delete the existing directory first.\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('ReleaseNetworkError', (err) => Console.error(`\nError: Could not reach GitHub to download the release.\n` +
23
- ` ${err.cause}\n\n` +
24
- ` • Check your network connection and try again.\n` +
25
- ` • Use a local path: ping-lf init <dir> --local <path>\n` +
26
- ` • Specify a version: ping-lf init <dir> --version v1.0.0\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('ReleaseParseError', (err) => Console.error(`\nError: Failed to parse the release data.\n ${err.cause}\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('ReleaseFsError', (err) => Console.error(`\nError: Filesystem error during release download (${err.operation}).\n ${err.cause}\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('InvalidVersionError', (err) => Console.error(`\nError: "${err.version}" is not a valid version tag.\n` +
27
- ` Expected semver format like v1.0.0.\n` +
28
- ` Use "ping-lf releases" to list available versions.\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('ReleaseNotFoundError', (err) => Console.error(`\nError: No releases found on GitHub.` +
29
- (err.cause ? `\n ${err.cause}` : '') +
30
- `\n\n • Check your network connection and try again.\n` +
31
- ` • Use a local path: ping-lf init <dir> --local <path>\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('InvalidComponentNameError', (err) => Console.error(`\nError: "${err.name}" is not a valid component name.\n` +
32
- ` Names must be PascalCase, start with an uppercase letter, and contain only letters and digits.\n` +
33
- ` Examples: MyCallback, JWTLogin, DefaultStage\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.catchTag('ComponentAlreadyExistsError', (err) => Console.error(`\nError: component directory already exists: ${err.path}\n` +
34
- ` Choose a different name or delete the existing directory first.\n`).pipe(Effect.andThen(Effect.die(err)))), Effect.provide(GithubReleaseLayer), Effect.provide(NodeContext.layer), (effect) => NodeRuntime.runMain(effect, { disableErrorReporting: true }));
@@ -1,73 +0,0 @@
1
- <!--
2
- @component
3
- Type: callback
4
- Name: __COMPONENT_NAME__
5
-
6
- Custom callback component. Replace this description with your own.
7
- -->
8
-
9
- <script lang="ts">
10
- import type { FRCallback } from '@forgerock/javascript-sdk';
11
- import type { z } from 'zod';
12
-
13
- import type {
14
- CallbackMetadata,
15
- SelfSubmitFunction,
16
- StepMetadata,
17
- } from '$journey/journey.interfaces';
18
- import type { styleSchema } from '$core/style.store';
19
- import type { Maybe } from '$core/interfaces';
20
-
21
- /**
22
- * The AM callback instance for this component. Use `callback.getInputValue()`
23
- * and `callback.setInputValue()` to read/write values sent back to the server.
24
- */
25
- export let callback: FRCallback;
26
-
27
- /**
28
- * Optional function to trigger self-submission (e.g. after an async action).
29
- * Set to `null` when the callback does not need to submit the form itself.
30
- */
31
- export const selfSubmitFunction: Maybe<SelfSubmitFunction> = null;
32
-
33
- /**
34
- * Metadata about the current step (page node) — includes stage name,
35
- * header/description overrides, and derived helpers like `isStepSelfSubmittable()`.
36
- */
37
- export const stepMetadata: Maybe<StepMetadata> = null;
38
-
39
- /**
40
- * Per-callback metadata from the step — may include policies, failed policies,
41
- * and other AM-provided hints for rendering.
42
- */
43
- export const callbackMetadata: Maybe<CallbackMetadata> = null;
44
-
45
- /**
46
- * The widget's resolved style configuration (colors, logos, labels, etc.).
47
- * Use this to keep your custom callback visually consistent with the theme.
48
- */
49
- export const style: z.infer<typeof styleSchema> = {};
50
-
51
- // Suppress the "unused export" warning — remove `void` once you use `callback`.
52
- void callback;
53
- </script>
54
-
55
- <!-- Replace the markup below with your custom callback UI. -->
56
- <div class="__COMPONENT_SLUG__ tw_p-4 tw_rounded-lg tw_border tw_border-secondary-light dark:tw_border-secondary-dark">
57
- <p class="tw_text-base tw_text-secondary-dark dark:tw_text-secondary-light">
58
- __COMPONENT_NAME__ callback — replace this with your implementation.
59
- </p>
60
- </div>
61
-
62
- <!--
63
- Scoped styles for this callback.
64
- These styles only apply to this component — they won't leak to the rest of the widget.
65
- You can also use Tailwind utility classes (prefixed with `tw_`) in the markup above.
66
- -->
67
- <style>
68
- .__COMPONENT_SLUG__ {
69
- display: flex;
70
- flex-direction: column;
71
- gap: 0.5rem;
72
- }
73
- </style>
@@ -1,9 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { format__COMPONENT_NAME__Label } from './__COMPONENT_SLUG__.utilities';
4
-
5
- describe('__COMPONENT_NAME__ utilities', () => {
6
- it('trims whitespace from label', () => {
7
- expect(format__COMPONENT_NAME__Label(' hello ')).toBe('hello');
8
- });
9
- });
@@ -1,9 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
-
3
- import { format__COMPONENT_NAME__Label } from './__COMPONENT_SLUG__.utilities';
4
-
5
- describe('__COMPONENT_NAME__ utilities', () => {
6
- it('trims whitespace from label', () => {
7
- expect(format__COMPONENT_NAME__Label(' hello ')).toBe('hello');
8
- });
9
- });
package/dist/utils.d.ts DELETED
@@ -1,2 +0,0 @@
1
- /** Converts all backslashes to forward slashes for cross-platform path comparisons. */
2
- export declare function normalizeSeparators(p: string): string;
package/dist/utils.js DELETED
@@ -1,4 +0,0 @@
1
- /** Converts all backslashes to forward slashes for cross-platform path comparisons. */
2
- export function normalizeSeparators(p) {
3
- return p.replace(/\\/g, '/');
4
- }
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Thin Effect runner for generating the custom component registry.
4
- *
5
- * Called by:
6
- * - packages/login-widget/package.json "prebuild"
7
- * - Root package.json "generate:registry"
8
- *
9
- * Requires the CLI to be compiled first:
10
- * pnpm --filter @ping-identity/login-framework-cli run build
11
- */
12
- import { Effect } from 'effect';
13
- import { NodeContext, NodeRuntime } from '@effect/platform-node';
14
-
15
- const { runRegistryScript } = await import('../dist/services/registry.js');
16
-
17
- const projectDir = process.argv[2];
18
- if (!projectDir) {
19
- console.error('Usage: node generate-registry.mjs <projectDir>');
20
- process.exit(1);
21
- }
22
-
23
- NodeRuntime.runMain(runRegistryScript(projectDir).pipe(Effect.provide(NodeContext.layer)));
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -51,14 +51,6 @@ export declare class GeneratorVersionError extends GeneratorVersionError_base<{
51
51
  readonly path?: string;
52
52
  }> {
53
53
  }
54
- declare const RegistryScanError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
55
- readonly _tag: "RegistryScanError";
56
- } & Readonly<A>;
57
- export declare class RegistryScanError extends RegistryScanError_base<{
58
- readonly directory: string;
59
- readonly cause?: unknown;
60
- }> {
61
- }
62
54
  declare const DirectoryConflictError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
63
55
  readonly _tag: "DirectoryConflictError";
64
56
  } & Readonly<A>;
@@ -87,4 +79,12 @@ export declare class ComponentAlreadyExistsError extends ComponentAlreadyExistsE
87
79
  readonly path: string;
88
80
  }> {
89
81
  }
82
+ declare const RegistryScanError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
83
+ readonly _tag: "RegistryScanError";
84
+ } & Readonly<A>;
85
+ export declare class RegistryScanError extends RegistryScanError_base<{
86
+ readonly directory: string;
87
+ readonly cause?: unknown;
88
+ }> {
89
+ }
90
90
  export {};
@@ -13,8 +13,6 @@ export class FileSystemError extends Data.TaggedError('FileSystemError') {
13
13
  }
14
14
  export class GeneratorVersionError extends Data.TaggedError('GeneratorVersionError') {
15
15
  }
16
- export class RegistryScanError extends Data.TaggedError('RegistryScanError') {
17
- }
18
16
  export class DirectoryConflictError extends Data.TaggedError('DirectoryConflictError') {
19
17
  }
20
18
  export class DirectoryNotEmptyError extends Data.TaggedError('DirectoryNotEmptyError') {
@@ -23,3 +21,5 @@ export class InvalidComponentNameError extends Data.TaggedError('InvalidComponen
23
21
  }
24
22
  export class ComponentAlreadyExistsError extends Data.TaggedError('ComponentAlreadyExistsError') {
25
23
  }
24
+ export class RegistryScanError extends Data.TaggedError('RegistryScanError') {
25
+ }
File without changes
@@ -1,5 +1,5 @@
1
- import { Effect } from 'effect';
2
1
  import { FileSystem } from '@effect/platform';
2
+ import { Effect } from 'effect';
3
3
  import { FileSystemError } from '../errors.js';
4
4
  /**
5
5
  * Returns true if the given directory looks like an initialized framework
@@ -1,8 +1,8 @@
1
- import { Effect } from 'effect';
2
1
  import { FileSystem } from '@effect/platform';
2
+ import { Effect } from 'effect';
3
+ import path from 'node:path';
3
4
  import { isExcluded } from '../config/exclusions.js';
4
5
  import { FileSystemError } from '../errors.js';
5
- import path from 'node:path';
6
6
  import { normalizeSeparators } from '../utils.js';
7
7
  const wrapFsCall = (operation, fsPath) => (effect) => {
8
8
  const fail = (cause) => Effect.fail(new FileSystemError({ operation, path: fsPath, cause }));
@@ -1,5 +1,5 @@
1
- import { Effect } from 'effect';
2
1
  import { FileSystem, Path } from '@effect/platform';
2
+ import { Effect } from 'effect';
3
3
  import { RegistryScanError } from '../errors.js';
4
4
  type ComponentType = 'stage' | 'callback';
5
5
  /** Extracts names of all `export let` prop declarations from a Svelte component's `<script>` block. */
@@ -1,6 +1,6 @@
1
- import { Context, Effect, Layer, Schema } from 'effect';
2
1
  import { FileSystem, HttpClient, HttpClientResponse } from '@effect/platform';
3
2
  import { NodeHttpClient } from '@effect/platform-node';
3
+ import { Context, Effect, Layer, Schema } from 'effect';
4
4
  import { extract } from 'tar';
5
5
  import { InvalidVersionError, ReleaseFsError, ReleaseNetworkError, ReleaseNotFoundError, ReleaseParseError, } from '../errors.js';
6
6
  const REPO = 'ForgeRock/forgerock-web-login-framework';