@pikku/inspector 0.12.54 → 0.12.56

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/CHANGELOG.md CHANGED
@@ -1,3 +1,80 @@
1
+ ## 0.12.56
2
+
3
+ ### Patch Changes
4
+
5
+ - 7e60867: Delete exports nothing references
6
+
7
+ A sweep of the `@pikku/core` surface for exports with no consumer anywhere in the repo — no package, template, verifier or e2e project imports them: `ExtractFunctionOutput`, `CLICommandDefinition`, `RequestHeaders`, `HTTPFunctionsMeta`, `HTTPWiringMiddleware`, `JsonRpcError`, `TriggerSourceInfo`, `getMCPResources`, `getMCPPrompts`, `onGraphNodeComplete` and `InputRef`.
8
+
9
+ Every one was a compatibility promise with nothing on the other end of it. Removing them narrows what 0.13 has to keep stable.
10
+
11
+ `isRef` looked like the twelfth, and isn't. It is the type guard that reads what `createRef` writes — the `__isRef` brand marking a graph node input as "substitute another node's output here". Nothing imported it because neither it nor `RefValue` was reachable from any entry point, so the one consumer that needed it, the inspector's graph serializer, had reimplemented the same four conditions privately as `isRefValue` along with its own structural copy of `RefValue`. Deleting `isRef` would have made that duplicate permanent, with the brand's shape asserted in two places free to drift apart.
12
+
13
+ So `isRef` and `RefValue` are exported from `@pikku/core/workflow` instead, and the inspector imports them rather than keeping its own copy.
14
+
15
+ - a879ab3: **Codegen reports a schema it named but never generated (PKU463).** A named
16
+ contract type that is declared but not exported is imported by the virtual
17
+ source file the schema generator compiles, resolves to nothing, and yields no
18
+ schema — while the function meta still carries the name. `pikku all` exited 0
19
+ and the first call to that function failed in a deployment with
20
+ `MissingSchemaError`. The reference is now checked once addon schemas are
21
+ merged, since an addon supplies its own and checking earlier would report every
22
+ one of them as unresolved.
23
+ - Updated dependencies [41c1a95]
24
+ - Updated dependencies [ce96383]
25
+ - Updated dependencies [7e60867]
26
+ - Updated dependencies [f8f1244]
27
+ - Updated dependencies [dcf20cb]
28
+ - Updated dependencies [6512384]
29
+ - Updated dependencies [e3b4c14]
30
+ - Updated dependencies [efd0ed1]
31
+ - Updated dependencies [cba98fb]
32
+ - Updated dependencies [ce96383]
33
+ - Updated dependencies [f8f1244]
34
+ - Updated dependencies [f8f1244]
35
+ - Updated dependencies [6e93a35]
36
+ - Updated dependencies [6dada45]
37
+ - @pikku/core@0.12.80
38
+
39
+ ## 0.12.55
40
+
41
+ ### Patch Changes
42
+
43
+ - ae4e898: Carry a secret's `allowedHosts` through code generation, and close three gaps in
44
+ the SSRF guard.
45
+
46
+ `allowedHosts` was declared and enforced but never survived codegen: the
47
+ inspector did not read the property off the `defineSecret` literal, and the meta
48
+ builder rebuilt its objects without it. Enforcement in `assertSecretAllowedForHost`
49
+ then always saw `undefined`, so the egress restriction was a no-op by default —
50
+ and, with `secrets.requireAllowedHosts` set, threw for every secret including the
51
+ ones that correctly declared hosts. Both stages now carry the field, and the
52
+ secrets verifier asserts it against the generated JSON rather than a hand-written
53
+ meta literal, which is why the existing tests stayed green.
54
+
55
+ `isPrivateHost` now checks an explicit CIDR table instead of ad-hoc octet
56
+ comparisons. It previously missed `100.64.0.0/10` — which contains Alibaba
57
+ Cloud's `100.100.100.200` metadata endpoint — along with `192.0.0.0/24`,
58
+ `198.18.0.0/15`, `192.88.99.0/24`, the TEST-NETs, multicast and reserved space.
59
+ IPv6 gains a real parser, so `fec0::/10`, `ff00::/8`, and NAT64 (`64:ff9b::/96`)
60
+ and 6to4 (`2002::/16`) forms wrapping an internal IPv4 address are caught.
61
+
62
+ `safeFetch` takes an optional `resolveHost`, checked on the initial URL and every
63
+ redirect hop, so a _public_ hostname pointing at a private address is refused —
64
+ the `169-254-169-254.nip.io` shape a literal-only check cannot see. Core cannot
65
+ resolve DNS itself (Workers has no DNS API), so the Node resolver ships as
66
+ `@pikku/core/node-host-resolver` and the Node server runtimes install it during
67
+ `init()`. The connection is not pinned to the address that was checked, so a
68
+ rebind between check and connect is still possible.
69
+
70
+ The graph addon's `httpRequest` node called bare `fetch`, bypassing the guard
71
+ entirely; it now goes through `safeFetch`.
72
+
73
+ - Updated dependencies [e848eb2]
74
+ - Updated dependencies [b170489]
75
+ - Updated dependencies [ae4e898]
76
+ - @pikku/core@0.12.79
77
+
1
78
  ## 0.12.54
2
79
 
3
80
  ### Patch Changes
@@ -1,5 +1,5 @@
1
1
  import * as ts from 'typescript';
2
- import { getPropertyValue, assertStringLiteralProperty, } from '../utils/get-property-value.js';
2
+ import { getPropertyValue, getArrayPropertyValue, assertStringLiteralProperty, } from '../utils/get-property-value.js';
3
3
  import { ErrorCode } from '../error-codes.js';
4
4
  import { detectSchemaVendorOrError } from '../utils/detect-schema-vendor.js';
5
5
  import { parseDurationString } from '@pikku/core';
@@ -27,6 +27,7 @@ export const createAddKeyedWiring = (config) => {
27
27
  const descriptionValue = getPropertyValue(obj, 'description');
28
28
  const rotationPeriodValue = getPropertyValue(obj, 'rotationPeriod');
29
29
  const docsUrlValue = getPropertyValue(obj, 'docsUrl');
30
+ const allowedHostsValue = getArrayPropertyValue(obj, 'allowedHosts');
30
31
  const idValue = getPropertyValue(obj, config.idField);
31
32
  let schemaVariableName = null;
32
33
  let schemaSourceFile = null;
@@ -104,6 +105,7 @@ export const createAddKeyedWiring = (config) => {
104
105
  description: descriptionValue || undefined,
105
106
  rotationPeriod: rotationPeriodValue || undefined,
106
107
  docsUrl: docsUrlValue || undefined,
108
+ allowedHosts: allowedHostsValue || undefined,
107
109
  [config.idField]: idValue,
108
110
  schema: schemaLookupName,
109
111
  sourceFile,
@@ -37,6 +37,7 @@ export declare enum ErrorCode {
37
37
  DB_FORM_ON_NON_STRING = "PKU484",
38
38
  DB_DEFAULT_SCHEMA_NAME_COLLISION = "PKU485",
39
39
  SCHEMA_GENERATION_ERROR = "PKU456",
40
+ SCHEMA_REFERENCE_UNRESOLVED = "PKU463",
40
41
  INLINE_SCHEMA = "PKU489",
41
42
  FUNCTION_METADATA_NOT_FOUND = "PKU559",
42
43
  DUPLICATE_AUTH_DEFINITION = "PKU581",
@@ -42,6 +42,7 @@ export var ErrorCode;
42
42
  ErrorCode["DB_DEFAULT_SCHEMA_NAME_COLLISION"] = "PKU485";
43
43
  // Configuration errors
44
44
  ErrorCode["SCHEMA_GENERATION_ERROR"] = "PKU456";
45
+ ErrorCode["SCHEMA_REFERENCE_UNRESOLVED"] = "PKU463";
45
46
  ErrorCode["INLINE_SCHEMA"] = "PKU489";
46
47
  // Function errors
47
48
  ErrorCode["FUNCTION_METADATA_NOT_FOUND"] = "PKU559";
package/dist/inspector.js CHANGED
@@ -6,12 +6,12 @@ import { TypesMap } from './types-map.js';
6
6
  import { getFilesAndMethods } from './utils/get-files-and-methods.js';
7
7
  import { findCommonAncestor } from './utils/find-root-dir.js';
8
8
  import { createNestedProjectFilter } from './utils/nested-project-filter.js';
9
- import { aggregateRequiredServices, stampAuthHandlerServices, validateAgentModels, validateAgentToolReferences, validateSecretOverrides, validateVariableOverrides, validateCredentialOverrides, validateRemoteAddonDependencies, validateRemoteAddonAuth, validateScopeReferences, validateSystemRoleScopes, validatePersonaRoles, computeResolvedIOTypes, computeMiddlewareGroupsMeta, computePermissionsGroupsMeta, computeRequiredSchemas, computeSecretBrokers, validateNoSecretAliasServices, validateSecretUsage, computeDiagnostics, validateSchemaWiringSeparation, validateScenarioServices, validateScenarioSteps, validateWorkflowGraphAddons, } from './utils/post-process.js';
9
+ import { aggregateRequiredServices, stampAuthHandlerServices, validateAgentModels, validateAgentToolReferences, validateSecretOverrides, validateVariableOverrides, validateCredentialOverrides, validateRemoteAddonDependencies, validateRemoteAddonAuth, validateScopeReferences, validateSystemRoleScopes, validatePersonaRoles, computeResolvedIOTypes, computeMiddlewareGroupsMeta, computePermissionsGroupsMeta, computeRequiredSchemas, computeSecretBrokers, validateNoSecretAliasServices, validateSecretUsage, computeDiagnostics, validateSchemaReferences, validateSchemaWiringSeparation, validateScenarioServices, validateScenarioSteps, validateWorkflowGraphAddons, } from './utils/post-process.js';
10
10
  import { validateExposedFunctionsGated } from './utils/validate-exposed-functions-gated.js';
11
11
  import { validateTagsResolveToMiddleware } from './utils/validate-tags-resolve-to-middleware.js';
12
12
  import { annotateHttpRouteAuth } from './utils/annotate-http-route-auth.js';
13
13
  import { generateOpenAPISpec } from './utils/serialize-openapi-json.js';
14
- import { pikkuState } from '@pikku/core/internal';
14
+ import { pikkuState } from '@pikku/core/ecosystem';
15
15
  import { resolveLatestVersions } from './utils/resolve-versions.js';
16
16
  import { finalizeWorkflows } from './utils/workflow/graph/finalize-workflows.js';
17
17
  import { finalizeWorkflowHelperTypes, finalizeWorkflowWires, } from './utils/workflow/graph/finalize-workflow-wires.js';
@@ -336,6 +336,11 @@ export const inspect = async (logger, routeFiles, options = {}) => {
336
336
  }
337
337
  // Re-load addon schemas (generateAllSchemas replaces state.schemas)
338
338
  await loadAddonSchemas(logger, state);
339
+ // After the addon merge, not before: an addon supplies its own schemas here,
340
+ // and checking earlier would report every one of them as unresolved.
341
+ if (options.schemaConfig) {
342
+ validateSchemaReferences(logger, state);
343
+ }
339
344
  state.manifest.initial = options.manifest ?? null;
340
345
  const contracts = extractContractsFromMeta(state.functions.meta);
341
346
  const baseManifest = state.manifest.initial ?? createEmptyManifest();
@@ -50,6 +50,21 @@ export declare function computeResolvedIOTypes(state: InspectorState): void;
50
50
  export declare function computeMiddlewareGroupsMeta(state: InspectorState): void;
51
51
  export declare function computePermissionsGroupsMeta(state: InspectorState): void;
52
52
  export declare function computeRequiredSchemas(state: InspectorState, options: InspectorOptions): void;
53
+ /**
54
+ * Every schema a function's contract names has to exist once codegen is done.
55
+ *
56
+ * The way it stops existing is quiet. `generateCustomTypes` hands the schema
57
+ * generator a virtual source file that *imports* each named contract type, so a
58
+ * type that is declared but never exported resolves to nothing and yields no
59
+ * schema — while the function's meta still carries the name. Nothing downstream
60
+ * reads that name until the first call, which fails with a runtime
61
+ * `MissingSchemaError` in a deployment rather than in the build that caused it.
62
+ *
63
+ * Reported rather than critical: the reference is only *guaranteed* to break
64
+ * the functions that are actually invoked, so this blocks CI through
65
+ * `--fail-on-error` without failing a dev server over a function nobody calls.
66
+ */
67
+ export declare function validateSchemaReferences(logger: InspectorLogger, state: InspectorState): void;
53
68
  export declare function validateAgentModels(logger: InspectorLogger, state: InspectorState | Omit<InspectorState, 'typesLookup'>): void;
54
69
  /**
55
70
  * Scenarios are pure stories of remote RPCs (same rule as client-side CLI
@@ -554,6 +554,58 @@ export function computeRequiredSchemas(state, options) {
554
554
  ...Array.from(schemaLookup.keys()),
555
555
  ]);
556
556
  }
557
+ /**
558
+ * Every schema a function's contract names has to exist once codegen is done.
559
+ *
560
+ * The way it stops existing is quiet. `generateCustomTypes` hands the schema
561
+ * generator a virtual source file that *imports* each named contract type, so a
562
+ * type that is declared but never exported resolves to nothing and yields no
563
+ * schema — while the function's meta still carries the name. Nothing downstream
564
+ * reads that name until the first call, which fails with a runtime
565
+ * `MissingSchemaError` in a deployment rather than in the build that caused it.
566
+ *
567
+ * Reported rather than critical: the reference is only *guaranteed* to break
568
+ * the functions that are actually invoked, so this blocks CI through
569
+ * `--fail-on-error` without failing a dev server over a function nobody calls.
570
+ */
571
+ export function validateSchemaReferences(logger, state) {
572
+ const { functions, schemas } = state;
573
+ const available = new Set(Object.keys(schemas ?? {}));
574
+ const unresolved = [];
575
+ const resolve = (typeName) => {
576
+ try {
577
+ return functions.typesMap.getUniqueName(typeName);
578
+ }
579
+ catch {
580
+ return typeName;
581
+ }
582
+ };
583
+ for (const [funcName, meta] of Object.entries(functions.meta)) {
584
+ for (const [role, declared] of [
585
+ ['input', meta.inputs?.[0]],
586
+ ['output', meta.outputs?.[0]],
587
+ ]) {
588
+ if (!declared || PRIMITIVE_TYPES.has(declared))
589
+ continue;
590
+ const resolved = resolve(declared);
591
+ if (PRIMITIVE_TYPES.has(resolved) || available.has(resolved))
592
+ continue;
593
+ unresolved.push(`${funcName}.${role} → '${resolved}'`);
594
+ }
595
+ }
596
+ if (unresolved.length === 0)
597
+ return;
598
+ logger.diagnostic({
599
+ severity: 'error',
600
+ code: ErrorCode.SCHEMA_REFERENCE_UNRESOLVED,
601
+ message: `${unresolved.length} function contract${unresolved.length === 1 ? '' : 's'} ` +
602
+ `name${unresolved.length === 1 ? 's' : ''} a schema that was never generated, so ` +
603
+ `calling ${unresolved.length === 1 ? 'it' : 'them'} fails at runtime with ` +
604
+ `MissingSchemaError: ${unresolved.join(', ')}. ` +
605
+ `The usual cause is a named type used as the function's input/output that ` +
606
+ `is declared but not exported — export it, or inline the type at the call site.`,
607
+ });
608
+ }
557
609
  export function validateAgentModels(logger, state) {
558
610
  for (const [, meta] of Object.entries(state.agents.agentsMeta)) {
559
611
  const model = meta.model;
@@ -1,3 +1,4 @@
1
+ import { isRef } from '@pikku/core/workflow';
1
2
  /**
2
3
  * Convert a RefValue (from runtime) to DataRef (serialized)
3
4
  */
@@ -7,22 +8,13 @@ function convertRef(ref) {
7
8
  path: ref.path,
8
9
  };
9
10
  }
10
- /**
11
- * Check if a value is a runtime RefValue
12
- */
13
- function isRefValue(value) {
14
- return (typeof value === 'object' &&
15
- value !== null &&
16
- '__isRef' in value &&
17
- value.__isRef === true);
18
- }
19
11
  /**
20
12
  * Convert input mapping from runtime format to serialized format
21
13
  */
22
14
  function serializeInputMapping(input) {
23
15
  const result = {};
24
16
  for (const [key, value] of Object.entries(input)) {
25
- if (isRefValue(value)) {
17
+ if (isRef(value)) {
26
18
  result[key] = convertRef(value);
27
19
  }
28
20
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/inspector",
3
- "version": "0.12.54",
3
+ "version": "0.12.56",
4
4
  "description": "TypeScript inspector for Pikku — discovers functions and wirings to drive code generation",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "BUSL-1.1",
@@ -45,10 +45,10 @@
45
45
  "zod-to-ts": "^2.1.0"
46
46
  },
47
47
  "peerDependencies": {
48
- "@pikku/core": "^0.12.76"
48
+ "@pikku/core": "^0.12.80"
49
49
  },
50
50
  "devDependencies": {
51
- "@pikku/core": "^0.12.76",
51
+ "@pikku/core": "^0.12.80",
52
52
  "@types/node": "^24.11.0"
53
53
  },
54
54
  "engines": {
@@ -1,6 +1,7 @@
1
1
  import * as ts from 'typescript'
2
2
  import {
3
3
  getPropertyValue,
4
+ getArrayPropertyValue,
4
5
  assertStringLiteralProperty,
5
6
  } from '../utils/get-property-value.js'
6
7
  import type { AddWiring, InspectorState } from '../types.js'
@@ -57,6 +58,7 @@ export const createAddKeyedWiring = (config: KeyedWiringConfig): AddWiring => {
57
58
  | string
58
59
  | null
59
60
  const docsUrlValue = getPropertyValue(obj, 'docsUrl') as string | null
61
+ const allowedHostsValue = getArrayPropertyValue(obj, 'allowedHosts')
60
62
  const idValue = getPropertyValue(obj, config.idField) as string | null
61
63
 
62
64
  let schemaVariableName: string | null = null
@@ -167,6 +169,7 @@ export const createAddKeyedWiring = (config: KeyedWiringConfig): AddWiring => {
167
169
  description: descriptionValue || undefined,
168
170
  rotationPeriod: rotationPeriodValue || undefined,
169
171
  docsUrl: docsUrlValue || undefined,
172
+ allowedHosts: allowedHostsValue || undefined,
170
173
  [config.idField]: idValue,
171
174
  schema: schemaLookupName,
172
175
  sourceFile,
@@ -45,6 +45,7 @@ export enum ErrorCode {
45
45
 
46
46
  // Configuration errors
47
47
  SCHEMA_GENERATION_ERROR = 'PKU456',
48
+ SCHEMA_REFERENCE_UNRESOLVED = 'PKU463',
48
49
  INLINE_SCHEMA = 'PKU489',
49
50
 
50
51
  // Function errors
package/src/inspector.ts CHANGED
@@ -32,6 +32,7 @@ import {
32
32
  validateNoSecretAliasServices,
33
33
  validateSecretUsage,
34
34
  computeDiagnostics,
35
+ validateSchemaReferences,
35
36
  validateSchemaWiringSeparation,
36
37
  validateScenarioServices,
37
38
  validateScenarioSteps,
@@ -41,7 +42,7 @@ import { validateExposedFunctionsGated } from './utils/validate-exposed-function
41
42
  import { validateTagsResolveToMiddleware } from './utils/validate-tags-resolve-to-middleware.js'
42
43
  import { annotateHttpRouteAuth } from './utils/annotate-http-route-auth.js'
43
44
  import { generateOpenAPISpec } from './utils/serialize-openapi-json.js'
44
- import { pikkuState } from '@pikku/core/internal'
45
+ import { pikkuState } from '@pikku/core/ecosystem'
45
46
  import { resolveLatestVersions } from './utils/resolve-versions.js'
46
47
  import { finalizeWorkflows } from './utils/workflow/graph/finalize-workflows.js'
47
48
  import {
@@ -444,6 +445,12 @@ export const inspect = async (
444
445
  // Re-load addon schemas (generateAllSchemas replaces state.schemas)
445
446
  await loadAddonSchemas(logger, state)
446
447
 
448
+ // After the addon merge, not before: an addon supplies its own schemas here,
449
+ // and checking earlier would report every one of them as unresolved.
450
+ if (options.schemaConfig) {
451
+ validateSchemaReferences(logger, state)
452
+ }
453
+
447
454
  state.manifest.initial = options.manifest ?? null
448
455
  const contracts = extractContractsFromMeta(state.functions.meta)
449
456
  const baseManifest = state.manifest.initial ?? createEmptyManifest()
@@ -689,6 +689,63 @@ export function computeRequiredSchemas(
689
689
  ])
690
690
  }
691
691
 
692
+ /**
693
+ * Every schema a function's contract names has to exist once codegen is done.
694
+ *
695
+ * The way it stops existing is quiet. `generateCustomTypes` hands the schema
696
+ * generator a virtual source file that *imports* each named contract type, so a
697
+ * type that is declared but never exported resolves to nothing and yields no
698
+ * schema — while the function's meta still carries the name. Nothing downstream
699
+ * reads that name until the first call, which fails with a runtime
700
+ * `MissingSchemaError` in a deployment rather than in the build that caused it.
701
+ *
702
+ * Reported rather than critical: the reference is only *guaranteed* to break
703
+ * the functions that are actually invoked, so this blocks CI through
704
+ * `--fail-on-error` without failing a dev server over a function nobody calls.
705
+ */
706
+ export function validateSchemaReferences(
707
+ logger: InspectorLogger,
708
+ state: InspectorState
709
+ ): void {
710
+ const { functions, schemas } = state
711
+ const available = new Set(Object.keys(schemas ?? {}))
712
+ const unresolved: string[] = []
713
+
714
+ const resolve = (typeName: string): string => {
715
+ try {
716
+ return functions.typesMap.getUniqueName(typeName)
717
+ } catch {
718
+ return typeName
719
+ }
720
+ }
721
+
722
+ for (const [funcName, meta] of Object.entries(functions.meta)) {
723
+ for (const [role, declared] of [
724
+ ['input', meta.inputs?.[0]],
725
+ ['output', meta.outputs?.[0]],
726
+ ] as const) {
727
+ if (!declared || PRIMITIVE_TYPES.has(declared)) continue
728
+ const resolved = resolve(declared)
729
+ if (PRIMITIVE_TYPES.has(resolved) || available.has(resolved)) continue
730
+ unresolved.push(`${funcName}.${role} → '${resolved}'`)
731
+ }
732
+ }
733
+
734
+ if (unresolved.length === 0) return
735
+
736
+ logger.diagnostic({
737
+ severity: 'error',
738
+ code: ErrorCode.SCHEMA_REFERENCE_UNRESOLVED,
739
+ message:
740
+ `${unresolved.length} function contract${unresolved.length === 1 ? '' : 's'} ` +
741
+ `name${unresolved.length === 1 ? 's' : ''} a schema that was never generated, so ` +
742
+ `calling ${unresolved.length === 1 ? 'it' : 'them'} fails at runtime with ` +
743
+ `MissingSchemaError: ${unresolved.join(', ')}. ` +
744
+ `The usual cause is a named type used as the function's input/output that ` +
745
+ `is declared but not exported — export it, or inline the type at the call site.`,
746
+ })
747
+ }
748
+
692
749
  export function validateAgentModels(
693
750
  logger: InspectorLogger,
694
751
  state: InspectorState | Omit<InspectorState, 'typesLookup'>
@@ -1,3 +1,4 @@
1
+ import { isRef } from '@pikku/core/workflow'
1
2
  import type {
2
3
  SerializedWorkflowGraph,
3
4
  SerializedGraphNode,
@@ -16,20 +17,6 @@ function convertRef(ref: { nodeId: string; path?: string }): DataRef {
16
17
  }
17
18
  }
18
19
 
19
- /**
20
- * Check if a value is a runtime RefValue
21
- */
22
- function isRefValue(
23
- value: unknown
24
- ): value is { __isRef: true; nodeId: string; path?: string } {
25
- return (
26
- typeof value === 'object' &&
27
- value !== null &&
28
- '__isRef' in value &&
29
- (value as any).__isRef === true
30
- )
31
- }
32
-
33
20
  /**
34
21
  * Convert input mapping from runtime format to serialized format
35
22
  */
@@ -39,7 +26,7 @@ function serializeInputMapping(
39
26
  const result: Record<string, unknown | DataRef> = {}
40
27
 
41
28
  for (const [key, value] of Object.entries(input)) {
42
- if (isRefValue(value)) {
29
+ if (isRef(value)) {
43
30
  result[key] = convertRef(value)
44
31
  } else {
45
32
  result[key] = value