@t-req/core 0.1.0 → 0.2.1

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 (68) hide show
  1. package/README.md +204 -14
  2. package/dist/client.d.ts +0 -3
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/config/engine-options.d.ts +50 -0
  5. package/dist/config/engine-options.d.ts.map +1 -0
  6. package/dist/config/index.d.ts +7 -3
  7. package/dist/config/index.d.ts.map +1 -1
  8. package/dist/config/index.js +9 -2
  9. package/dist/config/index.js.map +23 -5
  10. package/dist/config/jsonc.d.ts +18 -0
  11. package/dist/config/jsonc.d.ts.map +1 -0
  12. package/dist/config/load.d.ts +13 -2
  13. package/dist/config/load.d.ts.map +1 -1
  14. package/dist/config/merge.d.ts +31 -5
  15. package/dist/config/merge.d.ts.map +1 -1
  16. package/dist/config/resolve.d.ts +59 -0
  17. package/dist/config/resolve.d.ts.map +1 -0
  18. package/dist/config/substitution.d.ts +25 -0
  19. package/dist/config/substitution.d.ts.map +1 -0
  20. package/dist/config/types.d.ts +74 -6
  21. package/dist/config/types.d.ts.map +1 -1
  22. package/dist/cookies/persistence.d.ts +48 -0
  23. package/dist/cookies/persistence.d.ts.map +1 -0
  24. package/dist/cookies/persistence.js +4 -0
  25. package/dist/cookies/persistence.js.map +10 -0
  26. package/dist/cookies.js +5 -5
  27. package/dist/cookies.js.map +2 -2
  28. package/dist/engine/engine.d.ts +3 -4
  29. package/dist/engine/engine.d.ts.map +1 -1
  30. package/dist/engine/index.js +4 -4
  31. package/dist/engine/index.js.map +4 -4
  32. package/dist/index.d.ts +4 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +8 -4
  35. package/dist/index.js.map +21 -7
  36. package/dist/interpolate.d.ts.map +1 -1
  37. package/dist/plugin/define.d.ts +65 -0
  38. package/dist/plugin/define.d.ts.map +1 -0
  39. package/dist/plugin/index.d.ts +7 -0
  40. package/dist/plugin/index.d.ts.map +1 -0
  41. package/dist/plugin/index.js +8 -0
  42. package/dist/plugin/index.js.map +22 -0
  43. package/dist/plugin/loader.d.ts +69 -0
  44. package/dist/plugin/loader.d.ts.map +1 -0
  45. package/dist/plugin/manager.d.ts +186 -0
  46. package/dist/plugin/manager.d.ts.map +1 -0
  47. package/dist/plugin/permissions.d.ts +33 -0
  48. package/dist/plugin/permissions.d.ts.map +1 -0
  49. package/dist/plugin/subprocess.d.ts +100 -0
  50. package/dist/plugin/subprocess.d.ts.map +1 -0
  51. package/dist/plugin/types.d.ts +668 -0
  52. package/dist/plugin/types.d.ts.map +1 -0
  53. package/dist/resolver/command.d.ts +19 -0
  54. package/dist/resolver/command.d.ts.map +1 -0
  55. package/dist/resolver/index.d.ts +2 -0
  56. package/dist/resolver/index.d.ts.map +1 -0
  57. package/dist/resolver/index.js +5 -0
  58. package/dist/resolver/index.js.map +10 -0
  59. package/dist/runtime/index.js +2 -2
  60. package/dist/runtime/index.js.map +2 -2
  61. package/dist/runtime/types.d.ts.map +1 -1
  62. package/dist/server-client.d.ts +50 -0
  63. package/dist/server-client.d.ts.map +1 -0
  64. package/dist/server-metadata.d.ts +13 -0
  65. package/dist/server-metadata.d.ts.map +1 -0
  66. package/dist/types.d.ts +41 -0
  67. package/dist/types.d.ts.map +1 -1
  68. package/package.json +20 -5
@@ -0,0 +1,18 @@
1
+ /**
2
+ * JSONC (JSON with Comments) parser
3
+ *
4
+ * Strips single-line (//) and multi-line comments from JSON text
5
+ * while preserving '//' inside string values (e.g., URLs).
6
+ */
7
+ /**
8
+ * Strips JSONC comments from a string while preserving URLs and other
9
+ * strings containing '//' or comment-like sequences.
10
+ */
11
+ export declare function stripJsonComments(content: string): string;
12
+ /**
13
+ * Parse JSONC content (JSON with comments) to an object.
14
+ *
15
+ * @throws {SyntaxError} if the content is not valid JSON after stripping comments
16
+ */
17
+ export declare function parseJsonc<T = unknown>(content: string): T;
18
+ //# sourceMappingURL=jsonc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonc.d.ts","sourceRoot":"","sources":["../../src/config/jsonc.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuFzD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAU1D"}
@@ -1,4 +1,4 @@
1
- import type { LoadedConfig } from './types';
1
+ import type { ConfigFormat, LoadedConfig } from './types';
2
2
  export type LoadConfigOptions = {
3
3
  path: string;
4
4
  } | {
@@ -7,9 +7,20 @@ export type LoadConfigOptions = {
7
7
  stopDir?: string;
8
8
  };
9
9
  /**
10
- * Load `treq.config.ts` from an explicit path or by searching upwards.
10
+ * Load config from an explicit path or by searching upwards.
11
+ *
12
+ * Discovery order (when searching):
13
+ * 1. treq.jsonc (preferred)
14
+ * 2. treq.json
15
+ * 3. treq.config.ts (legacy, deprecated)
16
+ * 4. treq.config.js (legacy, deprecated)
17
+ * 5. treq.config.mjs (legacy, deprecated)
11
18
  *
12
19
  * Node/Bun only (not renderer-safe).
13
20
  */
14
21
  export declare function loadConfig(options: LoadConfigOptions): Promise<LoadedConfig>;
22
+ /**
23
+ * Check if a config format is a legacy format (TS/JS).
24
+ */
25
+ export declare function isLegacyFormat(format: ConfigFormat | undefined): boolean;
15
26
  //# sourceMappingURL=load.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,SAAS,CAAC;AAExD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA4C9D;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAalF"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/config/load.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAmB,MAAM,SAAS,CAAC;AAE3E,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAwH9D;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBlF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,CAExE"}
@@ -1,8 +1,34 @@
1
- import type { TreqConfig } from './types';
1
+ import type { TreqConfigInput, TreqProfileInput } from './types';
2
2
  export type MergeConfigInputs = {
3
- defaults?: TreqConfig;
4
- file?: TreqConfig;
5
- overrides?: TreqConfig;
3
+ defaults?: TreqConfigInput;
4
+ file?: TreqConfigInput;
5
+ overrides?: TreqConfigInput;
6
6
  };
7
- export declare function mergeConfig(inputs: MergeConfigInputs): TreqConfig;
7
+ /**
8
+ * Merge multiple config sources with "last wins" semantics.
9
+ *
10
+ * Order: defaults < file < overrides
11
+ */
12
+ export declare function mergeConfig(inputs: MergeConfigInputs): TreqConfigInput;
13
+ /**
14
+ * Apply a profile to a config input.
15
+ *
16
+ * IMPORTANT: This operates on INPUT config, NOT ResolvedConfig.
17
+ * Returns a new TreqConfigInput with the profile's overrides applied.
18
+ *
19
+ * @param input - The config input to apply the profile to
20
+ * @param profileName - The name of the profile to apply
21
+ * @returns The config with profile applied
22
+ * @throws Error if the profile doesn't exist
23
+ */
24
+ export declare function applyProfile(input: TreqConfigInput, profileName?: string): TreqConfigInput;
25
+ /**
26
+ * Get sorted list of profile names from a config.
27
+ */
28
+ export declare function listProfiles(config: TreqConfigInput): string[];
29
+ /**
30
+ * Merge profile input with deep merge for defaults.
31
+ * Used internally for combining profile with base config.
32
+ */
33
+ export declare function mergeProfileInput(base: TreqProfileInput, overlay: TreqProfileInput): TreqProfileInput;
8
34
  //# sourceMappingURL=merge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/config/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,UAAU,CAgCjE"}
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/config/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,CAAC;AA+EF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAgBtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CA0B1F;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAG9D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,gBAAgB,GACxB,gBAAgB,CAqClB"}
@@ -0,0 +1,59 @@
1
+ import type { ResolvedProjectConfig, TreqConfigInput } from './types';
2
+ export declare const DEFAULT_TIMEOUT_MS = 30000;
3
+ export declare const DEFAULT_FOLLOW_REDIRECTS = true;
4
+ export declare const DEFAULT_VALIDATE_SSL = true;
5
+ export type ConfigOverrideLayer = {
6
+ /**
7
+ * A human-friendly layer name for introspection (e.g. "env", "cli", "session", "request").
8
+ */
9
+ name: string;
10
+ overrides: Partial<TreqConfigInput>;
11
+ };
12
+ export type ResolveProjectConfigOptions = {
13
+ /**
14
+ * Directory to start searching for config from.
15
+ */
16
+ startDir: string;
17
+ /**
18
+ * Stop searching at this directory (e.g., workspace root).
19
+ * Prevents accidentally picking a parent config outside the intended workspace.
20
+ */
21
+ stopDir?: string;
22
+ /**
23
+ * Profile to apply.
24
+ */
25
+ profile?: string;
26
+ /**
27
+ * Named override layers to apply, in-order, after profile.
28
+ * Each layer is merged with "last wins" semantics.
29
+ */
30
+ overrideLayers?: ConfigOverrideLayer[];
31
+ /**
32
+ * Overrides to apply (from CLI flags, environment files, etc.).
33
+ * Applied after profile.
34
+ */
35
+ overrides?: Partial<TreqConfigInput>;
36
+ /**
37
+ * Layer name recorded in metadata for the `overrides` option.
38
+ * Defaults to "overrides".
39
+ */
40
+ overridesLayerName?: string;
41
+ };
42
+ /**
43
+ * Resolve project configuration - the single source of truth for both CLI and server.
44
+ *
45
+ * This function:
46
+ * 1. Discovers config file (treq.jsonc, treq.json, treq.config.ts, etc.)
47
+ * 2. Parses the config
48
+ * 3. Applies substitutions ({env:}, {file:})
49
+ * 4. Applies profile overlay
50
+ * 5. Applies overrides (CLI flags, etc.)
51
+ * 6. Compiles resolvers (CommandResolverDef → Resolver wrapper)
52
+ * 7. Resolves cookies and defaults
53
+ * 8. Returns { config: ResolvedConfig, meta: ConfigMeta }
54
+ *
55
+ * @param options - Configuration options
56
+ * @returns ResolvedProjectConfig with config and metadata
57
+ */
58
+ export declare function resolveProjectConfig(options: ResolveProjectConfigOptions): Promise<ResolvedProjectConfig>;
59
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAMV,qBAAqB,EACrB,eAAe,EAChB,MAAM,SAAS,CAAC;AAMjB,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAMzC,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,cAAc,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAEvC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAErC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAmIF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CA6IhC"}
@@ -0,0 +1,25 @@
1
+ export type SubstitutionOptions = {
2
+ /**
3
+ * Directory containing the config file (for relative path resolution)
4
+ */
5
+ configDir: string;
6
+ /**
7
+ * Workspace root for security scoping
8
+ */
9
+ workspaceRoot: string;
10
+ /**
11
+ * Allow file reads outside workspace (e.g., ~/.treq/token)
12
+ * Default: false
13
+ */
14
+ allowExternalFiles?: boolean;
15
+ };
16
+ /**
17
+ * Apply substitutions to all string values in an object/array.
18
+ * Only substitutes within string values, not keys.
19
+ *
20
+ * @param obj - The object to process
21
+ * @param options - Substitution options
22
+ * @returns A new object with substitutions applied
23
+ */
24
+ export declare function applySubstitutions(obj: unknown, options: SubstitutionOptions): unknown;
25
+ //# sourceMappingURL=substitution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"substitution.d.ts","sourceRoot":"","sources":["../../src/config/substitution.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AA4HF;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAwBtF"}
@@ -1,3 +1,5 @@
1
+ import type { PluginManager } from '../plugin/manager';
2
+ import type { PluginConfigRef, PluginPermissionsConfig } from '../plugin/types';
1
3
  import type { Resolver } from '../types';
2
4
  export type TreqDefaults = {
3
5
  timeoutMs?: number;
@@ -6,17 +8,83 @@ export type TreqDefaults = {
6
8
  proxy?: string;
7
9
  headers?: Record<string, string>;
8
10
  };
9
- export type TreqConfig = {
11
+ export type ResolvedDefaults = {
12
+ timeoutMs: number;
13
+ followRedirects: boolean;
14
+ validateSSL: boolean;
15
+ proxy?: string;
16
+ headers: Record<string, string>;
17
+ };
18
+ export type CookiesConfig = {
19
+ enabled?: boolean;
20
+ jarPath?: string;
21
+ };
22
+ export type ResolvedCookiesConfig = {
23
+ enabled: boolean;
24
+ jarPath?: string;
25
+ mode: 'disabled' | 'memory' | 'persistent';
26
+ };
27
+ export type SecurityConfig = {
28
+ allowExternalFiles?: boolean;
29
+ /** Allow plugins from paths outside project root */
30
+ allowPluginsOutsideProject?: boolean;
31
+ /** Per-plugin permission overrides */
32
+ pluginPermissions?: PluginPermissionsConfig;
33
+ };
34
+ export type CommandResolverDef = {
35
+ type: 'command';
36
+ command: string[];
37
+ timeoutMs?: number;
38
+ };
39
+ export type TreqProfileInput = {
10
40
  variables?: Record<string, unknown>;
11
- resolvers?: Record<string, Resolver>;
12
41
  defaults?: TreqDefaults;
13
- cookies?: {
14
- enabled?: boolean;
15
- jarPath?: string;
42
+ cookies?: CookiesConfig;
43
+ resolvers?: Record<string, Resolver | CommandResolverDef>;
44
+ /** Plugins for this profile (appended to base plugins) */
45
+ plugins?: PluginConfigRef[];
46
+ };
47
+ export type TreqConfigInput = {
48
+ variables?: Record<string, unknown>;
49
+ defaults?: TreqDefaults;
50
+ cookies?: CookiesConfig;
51
+ resolvers?: Record<string, Resolver | CommandResolverDef>;
52
+ profiles?: Record<string, TreqProfileInput>;
53
+ security?: SecurityConfig;
54
+ /** Plugin configuration */
55
+ plugins?: PluginConfigRef[];
56
+ };
57
+ export type ResolvedConfig = {
58
+ projectRoot: string;
59
+ variables: Record<string, unknown>;
60
+ defaults: ResolvedDefaults;
61
+ cookies: ResolvedCookiesConfig;
62
+ resolvers: Record<string, Resolver>;
63
+ security: {
64
+ allowExternalFiles: boolean;
65
+ allowPluginsOutsideProject: boolean;
66
+ pluginPermissions?: PluginPermissionsConfig;
16
67
  };
68
+ /** Plugin manager (initialized if plugins are configured) */
69
+ pluginManager?: PluginManager;
70
+ };
71
+ export type ConfigFormat = 'jsonc' | 'json' | 'ts' | 'js' | 'mjs';
72
+ export type ConfigMeta = {
73
+ configPath?: string;
74
+ projectRoot: string;
75
+ format?: ConfigFormat;
76
+ profile?: string;
77
+ layersApplied: string[];
78
+ warnings: string[];
17
79
  };
18
80
  export type LoadedConfig = {
19
81
  path?: string;
20
- config: TreqConfig;
82
+ config: TreqConfigInput;
83
+ format?: ConfigFormat;
84
+ };
85
+ export type ResolvedProjectConfig = {
86
+ config: ResolvedConfig;
87
+ meta: ConfigMeta;
21
88
  };
89
+ export type TreqConfig = TreqConfigInput;
22
90
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { CookieJar } from '../cookies';
2
+ export type CookieJarData = {
3
+ version: number;
4
+ cookies: Array<{
5
+ key: string;
6
+ value: string;
7
+ domain: string;
8
+ path: string;
9
+ expires?: string;
10
+ secure?: boolean;
11
+ httpOnly?: boolean;
12
+ sameSite?: string;
13
+ }>;
14
+ };
15
+ export type CookieJarManager = {
16
+ load(): CookieJarData | null;
17
+ save(jar: CookieJar): void;
18
+ withLock<T>(fn: () => Promise<T>): Promise<T>;
19
+ };
20
+ /**
21
+ * Load cookie jar data from a file.
22
+ * Returns null if the file doesn't exist.
23
+ */
24
+ export declare function loadCookieJarData(jarPath: string): CookieJarData | null;
25
+ /**
26
+ * Save cookie jar data to a file.
27
+ * Uses atomic write (write to temp file, then rename).
28
+ */
29
+ export declare function saveCookieJarData(jarPath: string, data: CookieJarData): void;
30
+ /**
31
+ * Convert CookieJar to serializable data.
32
+ */
33
+ export declare function cookieJarToData(jar: CookieJar): CookieJarData;
34
+ /**
35
+ * Create a cookie jar manager for a specific jar path.
36
+ */
37
+ export declare function createCookieJarManager(jarPath: string): CookieJarManager;
38
+ /**
39
+ * Schedule a debounced save of the cookie jar.
40
+ * Multiple saves within the debounce interval will be coalesced.
41
+ */
42
+ export declare function scheduleCookieJarSave(jarPath: string, jar: CookieJar): void;
43
+ /**
44
+ * Flush all pending debounced saves immediately.
45
+ * Used for graceful shutdown.
46
+ */
47
+ export declare function flushPendingCookieSaves(): Promise<void>;
48
+ //# sourceMappingURL=persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/cookies/persistence.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,KAAK,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;CACJ,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,IAAI,aAAa,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC/C,CAAC;AA8BF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAyBvE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CA4B5E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,aAAa,CA8B7D;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAexE;AAgBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAsB3E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB7D"}
@@ -0,0 +1,4 @@
1
+ import{createRequire as U}from"node:module";var R=Object.defineProperty;var L=(H,z)=>{for(var G in z)R(H,G,{get:z[G],enumerable:!0,configurable:!0,set:(q)=>z[G]=()=>q})};var V=U(import.meta.url);import{existsSync as $,mkdirSync as B,readFileSync as F,renameSync as N,writeFileSync as _}from"node:fs";import*as Q from"node:path";var Z=new Map;async function A(H,z){let G=Q.resolve(H),q=Z.get(G)??Promise.resolve(),K,W=new Promise((O)=>{K=O}),Y=q.then(()=>W);Z.set(G,Y);try{return await q,await z()}finally{if(K?.(),Z.get(G)===Y)Z.delete(G)}}function g(H){let z=Q.resolve(H);if(!$(z))return null;try{let G=F(z,"utf-8"),q=JSON.parse(G);if(!q||typeof q!=="object")return null;if(!Array.isArray(q.cookies))return null;return q}catch{return null}}function I(H,z){let G=Q.resolve(H),q=Q.dirname(G);if(!$(q))B(q,{recursive:!0});let K=`${G}.tmp.${process.pid}`,W=JSON.stringify(z,null,2);try{_(K,W,"utf-8"),N(K,G)}catch(Y){try{if($(K))V("node:fs").unlinkSync(K)}catch{}throw Y}}function M(H){return{version:1,cookies:(H.toJSON()?.cookies??[]).map((q)=>{let K={key:q.key??"",value:q.value??"",domain:q.domain??"",path:q.path??"/"};if(q.expires)K.expires=q.expires;if(q.secure!==void 0)K.secure=q.secure;if(q.httpOnly!==void 0)K.httpOnly=q.httpOnly;if(q.sameSite)K.sameSite=q.sameSite;return K})}}function C(H){return{load(){return g(H)},save(z){let G=M(z);I(H,G)},async withLock(z){return A(H,z)}}}var w=250,X=new Map;function m(H,z){let G=Q.resolve(H),q=X.get(G);if(q)clearTimeout(q.timer);let K=setTimeout(()=>{X.delete(G),A(H,async()=>{try{let W=M(z);I(H,W)}catch{}return})},w);X.set(G,{timer:K,jarPath:H,jar:z})}async function u(){let H=Array.from(X.values());X.clear();for(let z of H)clearTimeout(z.timer);await Promise.all(H.map(async(z)=>{await A(z.jarPath,async()=>{let G=M(z.jar);I(z.jarPath,G);return})}))}export{m as scheduleCookieJarSave,I as saveCookieJarData,g as loadCookieJarData,u as flushPendingCookieSaves,C as createCookieJarManager,M as cookieJarToData};
2
+
3
+ //# debugId=BC7F7AF664664C7E64756E2164756E21
4
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cookies/persistence.ts"],
4
+ "sourcesContent": [
5
+ "import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport * as path from 'node:path';\nimport type { CookieJar } from '../cookies';\n\nexport type CookieJarData = {\n version: number;\n cookies: Array<{\n key: string;\n value: string;\n domain: string;\n path: string;\n expires?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n }>;\n};\n\nexport type CookieJarManager = {\n load(): CookieJarData | null;\n save(jar: CookieJar): void;\n withLock<T>(fn: () => Promise<T>): Promise<T>;\n};\n\nconst locks = new Map<string, Promise<void>>();\n\nasync function withLock<T>(jarPath: string, fn: () => Promise<T>): Promise<T> {\n const resolvedPath = path.resolve(jarPath);\n\n // Promise-chain mutex: each call appends to the tail, ensuring FIFO exclusivity.\n const prev = locks.get(resolvedPath) ?? Promise.resolve();\n\n let release: (() => void) | undefined;\n const current = new Promise<void>((r) => {\n release = r;\n });\n\n const tail = prev.then(() => current);\n locks.set(resolvedPath, tail);\n\n try {\n await prev;\n return await fn();\n } finally {\n release?.();\n // Only delete if nobody queued behind us.\n if (locks.get(resolvedPath) === tail) {\n locks.delete(resolvedPath);\n }\n }\n}\n\n/**\n * Load cookie jar data from a file.\n * Returns null if the file doesn't exist.\n */\nexport function loadCookieJarData(jarPath: string): CookieJarData | null {\n const resolvedPath = path.resolve(jarPath);\n\n if (!existsSync(resolvedPath)) {\n return null;\n }\n\n try {\n const content = readFileSync(resolvedPath, 'utf-8');\n const data = JSON.parse(content) as CookieJarData;\n\n // Validate basic structure\n if (!data || typeof data !== 'object') {\n return null;\n }\n\n if (!Array.isArray(data.cookies)) {\n return null;\n }\n\n return data;\n } catch {\n // Invalid or corrupted file - return null to start fresh\n return null;\n }\n}\n\n/**\n * Save cookie jar data to a file.\n * Uses atomic write (write to temp file, then rename).\n */\nexport function saveCookieJarData(jarPath: string, data: CookieJarData): void {\n const resolvedPath = path.resolve(jarPath);\n\n // Ensure parent directory exists\n const dir = path.dirname(resolvedPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Write to temp file first (atomic write)\n const tempPath = `${resolvedPath}.tmp.${process.pid}`;\n const content = JSON.stringify(data, null, 2);\n\n try {\n writeFileSync(tempPath, content, 'utf-8');\n renameSync(tempPath, resolvedPath);\n } catch (err) {\n // Clean up temp file on error\n try {\n if (existsSync(tempPath)) {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n require('node:fs').unlinkSync(tempPath);\n }\n } catch {\n // Ignore cleanup errors\n }\n throw err;\n }\n}\n\n/**\n * Convert CookieJar to serializable data.\n */\nexport function cookieJarToData(jar: CookieJar): CookieJarData {\n const serialized = jar.toJSON();\n const cookies = (serialized?.cookies ?? []) as Array<{\n key?: string;\n value?: string;\n domain?: string;\n path?: string;\n expires?: string;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: string;\n }>;\n\n return {\n version: 1,\n cookies: cookies.map((c) => {\n const cookie: CookieJarData['cookies'][number] = {\n key: c.key ?? '',\n value: c.value ?? '',\n domain: c.domain ?? '',\n path: c.path ?? '/'\n };\n // Only include optional fields if defined\n if (c.expires) cookie.expires = c.expires;\n if (c.secure !== undefined) cookie.secure = c.secure;\n if (c.httpOnly !== undefined) cookie.httpOnly = c.httpOnly;\n if (c.sameSite) cookie.sameSite = c.sameSite;\n return cookie;\n })\n };\n}\n\n// ============================================================================\n// Cookie Jar Manager\n// ============================================================================\n\n/**\n * Create a cookie jar manager for a specific jar path.\n */\nexport function createCookieJarManager(jarPath: string): CookieJarManager {\n return {\n load(): CookieJarData | null {\n return loadCookieJarData(jarPath);\n },\n\n save(jar: CookieJar): void {\n const data = cookieJarToData(jar);\n saveCookieJarData(jarPath, data);\n },\n\n async withLock<T>(fn: () => Promise<T>): Promise<T> {\n return withLock(jarPath, fn);\n }\n };\n}\n\n// ============================================================================\n// Debounced Save\n// ============================================================================\n\nconst DEBOUNCE_INTERVAL_MS = 250;\n\ntype DebouncedSaveEntry = {\n timer: NodeJS.Timeout;\n jarPath: string;\n jar: CookieJar;\n};\n\nconst debouncedSaveEntries = new Map<string, DebouncedSaveEntry>();\n\n/**\n * Schedule a debounced save of the cookie jar.\n * Multiple saves within the debounce interval will be coalesced.\n */\nexport function scheduleCookieJarSave(jarPath: string, jar: CookieJar): void {\n const resolvedPath = path.resolve(jarPath);\n\n // Clear any existing timer\n const existing = debouncedSaveEntries.get(resolvedPath);\n if (existing) clearTimeout(existing.timer);\n\n // Schedule new save\n const timer = setTimeout(() => {\n debouncedSaveEntries.delete(resolvedPath);\n void withLock(jarPath, async () => {\n try {\n const data = cookieJarToData(jar);\n saveCookieJarData(jarPath, data);\n } catch {\n // Ignore save errors in debounced context\n }\n return;\n });\n }, DEBOUNCE_INTERVAL_MS);\n\n debouncedSaveEntries.set(resolvedPath, { timer, jarPath, jar });\n}\n\n/**\n * Flush all pending debounced saves immediately.\n * Used for graceful shutdown.\n */\nexport async function flushPendingCookieSaves(): Promise<void> {\n const entries = Array.from(debouncedSaveEntries.values());\n debouncedSaveEntries.clear();\n\n for (const entry of entries) {\n clearTimeout(entry.timer);\n }\n\n // Best-effort flush (keep going even if one fails).\n await Promise.all(\n entries.map(async (entry) => {\n await withLock(entry.jarPath, async () => {\n const data = cookieJarToData(entry.jar);\n saveCookieJarData(entry.jarPath, data);\n return;\n });\n })\n );\n}\n"
6
+ ],
7
+ "mappings": "mMAAA,qBAAS,eAAY,kBAAW,gBAAc,mBAAY,gBAC1D,4BAuBA,IAAM,EAAQ,IAAI,IAElB,eAAe,CAAW,CAAC,EAAiB,EAAkC,CAC5E,IAAM,EAAoB,UAAQ,CAAO,EAGnC,EAAO,EAAM,IAAI,CAAY,GAAK,QAAQ,QAAQ,EAEpD,EACE,EAAU,IAAI,QAAc,CAAC,IAAM,CACvC,EAAU,EACX,EAEK,EAAO,EAAK,KAAK,IAAM,CAAO,EACpC,EAAM,IAAI,EAAc,CAAI,EAE5B,GAAI,CAEF,OADA,MAAM,EACC,MAAM,EAAG,SAChB,CAGA,GAFA,IAAU,EAEN,EAAM,IAAI,CAAY,IAAM,EAC9B,EAAM,OAAO,CAAY,GASxB,SAAS,CAAiB,CAAC,EAAuC,CACvE,IAAM,EAAoB,UAAQ,CAAO,EAEzC,GAAI,CAAC,EAAW,CAAY,EAC1B,OAAO,KAGT,GAAI,CACF,IAAM,EAAU,EAAa,EAAc,OAAO,EAC5C,EAAO,KAAK,MAAM,CAAO,EAG/B,GAAI,CAAC,GAAQ,OAAO,IAAS,SAC3B,OAAO,KAGT,GAAI,CAAC,MAAM,QAAQ,EAAK,OAAO,EAC7B,OAAO,KAGT,OAAO,EACP,KAAM,CAEN,OAAO,MAQJ,SAAS,CAAiB,CAAC,EAAiB,EAA2B,CAC5E,IAAM,EAAoB,UAAQ,CAAO,EAGnC,EAAW,UAAQ,CAAY,EACrC,GAAI,CAAC,EAAW,CAAG,EACjB,EAAU,EAAK,CAAE,UAAW,EAAK,CAAC,EAIpC,IAAM,EAAW,GAAG,SAAoB,QAAQ,MAC1C,EAAU,KAAK,UAAU,EAAM,KAAM,CAAC,EAE5C,GAAI,CACF,EAAc,EAAU,EAAS,OAAO,EACxC,EAAW,EAAU,CAAY,EACjC,MAAO,EAAK,CAEZ,GAAI,CACF,GAAI,EAAW,CAAQ,eAEF,WAAW,CAAQ,EAExC,KAAM,EAGR,MAAM,GAOH,SAAS,CAAe,CAAC,EAA+B,CAa7D,MAAO,CACL,QAAS,EACT,SAdiB,EAAI,OAAO,GACD,SAAW,CAAC,GAatB,IAAI,CAAC,IAAM,CAC1B,IAAM,EAA2C,CAC/C,IAAK,EAAE,KAAO,GACd,MAAO,EAAE,OAAS,GAClB,OAAQ,EAAE,QAAU,GACpB,KAAM,EAAE,MAAQ,GAClB,EAEA,GAAI,EAAE,QAAS,EAAO,QAAU,EAAE,QAClC,GAAI,EAAE,SAAW,OAAW,EAAO,OAAS,EAAE,OAC9C,GAAI,EAAE,WAAa,OAAW,EAAO,SAAW,EAAE,SAClD,GAAI,EAAE,SAAU,EAAO,SAAW,EAAE,SACpC,OAAO,EACR,CACH,EAUK,SAAS,CAAsB,CAAC,EAAmC,CACxE,MAAO,CACL,IAAI,EAAyB,CAC3B,OAAO,EAAkB,CAAO,GAGlC,IAAI,CAAC,EAAsB,CACzB,IAAM,EAAO,EAAgB,CAAG,EAChC,EAAkB,EAAS,CAAI,QAG3B,SAAW,CAAC,EAAkC,CAClD,OAAO,EAAS,EAAS,CAAE,EAE/B,EAOF,IAAM,EAAuB,IAQvB,EAAuB,IAAI,IAM1B,SAAS,CAAqB,CAAC,EAAiB,EAAsB,CAC3E,IAAM,EAAoB,UAAQ,CAAO,EAGnC,EAAW,EAAqB,IAAI,CAAY,EACtD,GAAI,EAAU,aAAa,EAAS,KAAK,EAGzC,IAAM,EAAQ,WAAW,IAAM,CAC7B,EAAqB,OAAO,CAAY,EACnC,EAAS,EAAS,SAAY,CACjC,GAAI,CACF,IAAM,EAAO,EAAgB,CAAG,EAChC,EAAkB,EAAS,CAAI,EAC/B,KAAM,EAGR,OACD,GACA,CAAoB,EAEvB,EAAqB,IAAI,EAAc,CAAE,QAAO,UAAS,KAAI,CAAC,EAOhE,eAAsB,CAAuB,EAAkB,CAC7D,IAAM,EAAU,MAAM,KAAK,EAAqB,OAAO,CAAC,EACxD,EAAqB,MAAM,EAE3B,QAAW,KAAS,EAClB,aAAa,EAAM,KAAK,EAI1B,MAAM,QAAQ,IACZ,EAAQ,IAAI,MAAO,IAAU,CAC3B,MAAM,EAAS,EAAM,QAAS,SAAY,CACxC,IAAM,EAAO,EAAgB,EAAM,GAAG,EACtC,EAAkB,EAAM,QAAS,CAAI,EACrC,OACD,EACF,CACH",
8
+ "debugId": "BC7F7AF664664C7E64756E2164756E21",
9
+ "names": []
10
+ }