diff --git a/lib/entry-points.js b/lib/entry-points.js index f385af4a9..7a739846f 100644 --- a/lib/entry-points.js +++ b/lib/entry-points.js @@ -147520,7 +147520,7 @@ var object = { validate: isObject, required: true }; -function optional(validator) { +function optionalOrNull(validator) { return { validate: (val) => { return val === void 0 || val === null || validator.validate(val); @@ -147528,7 +147528,7 @@ function optional(validator) { required: false }; } -function undefinable(validator) { +function optional(validator) { return { validate: (val) => { return val === void 0 || validator.validate(val); @@ -153679,8 +153679,8 @@ function isVersionInfo(x) { return isObject(x) && validateSchema( { version: string, - features: undefinable(object), - overlayVersion: undefinable(number) + features: optional(object), + overlayVersion: optional(number) }, x ); @@ -160094,14 +160094,14 @@ var toolcache4 = __toESM(require_tool_cache()); // src/start-proxy/types.ts var usernameSchema = { /** The username needed to authenticate to the package registry, if any. */ - username: optional(string) + username: optionalOrNull(string) }; function hasUsername(config) { return "username" in config; } var usernamePasswordSchema = { /** The password needed to authenticate to the package registry, if any. */ - password: optional(string), + password: optionalOrNull(string), ...usernameSchema }; function hasUsernameAndPassword(config) { @@ -160109,7 +160109,7 @@ function hasUsernameAndPassword(config) { } var tokenSchema = { /** The token needed to authenticate to the package registry, if any. */ - token: optional(string), + token: optionalOrNull(string), ...usernameSchema }; function hasToken(config) { @@ -160131,15 +160131,15 @@ var awsConfigSchema = { "role-name": string, domain: string, "domain-owner": string, - audience: optional(string) + audience: optionalOrNull(string) }; function isAWSConfig(config) { return validateSchema(awsConfigSchema, config); } var jfrogConfigSchema = { "jfrog-oidc-provider-name": string, - audience: optional(string), - "identity-mapping-name": optional(string) + audience: optionalOrNull(string), + "identity-mapping-name": optionalOrNull(string) }; function isJFrogConfig(config) { return validateSchema(jfrogConfigSchema, config); @@ -160154,8 +160154,8 @@ function isCloudsmithConfig(config) { } var gcpConfigSchema = { "workload-identity-provider": string, - "service-account": optional(string), - audience: optional(string) + "service-account": optionalOrNull(string), + audience: optionalOrNull(string) }; function isGCPConfig(config) { return validateSchema(gcpConfigSchema, config); diff --git a/src/codeql.ts b/src/codeql.ts index f960ce023..c7c0b4e9d 100644 --- a/src/codeql.ts +++ b/src/codeql.ts @@ -240,8 +240,8 @@ export function isVersionInfo(x: unknown): x is VersionInfo { json.validateSchema( { version: json.string, - features: json.undefinable(json.object), - overlayVersion: json.undefinable(json.number), + features: json.optional(json.object), + overlayVersion: json.optional(json.number), }, x, ) diff --git a/src/json/index.test.ts b/src/json/index.test.ts index d37a86c37..3e96d7639 100644 --- a/src/json/index.test.ts +++ b/src/json/index.test.ts @@ -10,8 +10,8 @@ const testSchema = { requiredKey: json.string, }; -const optionalSchema = { - optionalKey: json.optional(json.string), +const optionalOrNullSchema = { + optionalKey: json.optionalOrNull(json.string), }; test("validateSchema - required properties are required", async (t) => { @@ -30,11 +30,34 @@ test("validateSchema - required properties are required", async (t) => { test("validateSchema - optional properties are optional", async (t) => { // Optional fields may be absent - t.true(json.validateSchema(optionalSchema, {})); - t.true(json.validateSchema(optionalSchema, { optionalKey: undefined })); - t.true(json.validateSchema(optionalSchema, { optionalKey: null })); + t.true(json.validateSchema(optionalOrNullSchema, {})); + t.true(json.validateSchema(optionalOrNullSchema, { optionalKey: undefined })); + t.true(json.validateSchema(optionalOrNullSchema, { optionalKey: null })); // But, if present, should have the expected type + t.false(json.validateSchema(optionalOrNullSchema, { optionalKey: 0 })); + t.false(json.validateSchema(optionalOrNullSchema, { optionalKey: 123 })); + t.false(json.validateSchema(optionalOrNullSchema, { optionalKey: false })); + t.false(json.validateSchema(optionalOrNullSchema, { optionalKey: true })); + t.false(json.validateSchema(optionalOrNullSchema, { optionalKey: [] })); + t.false(json.validateSchema(optionalOrNullSchema, { optionalKey: {} })); + t.true(json.validateSchema(optionalOrNullSchema, { optionalKey: "" })); + t.true(json.validateSchema(optionalOrNullSchema, { optionalKey: "foo" })); +}); + +const optionalSchema = { + optionalKey: json.optional(json.string), +}; + +test("validateSchema - optional properties may be absent or undefined, but reject null", async (t) => { + // Optional fields may be absent or explicitly undefined + t.true(json.validateSchema(optionalSchema, {})); + t.true(json.validateSchema(optionalSchema, { optionalKey: undefined })); + + // But should reject null + t.false(json.validateSchema(optionalSchema, { optionalKey: null })); + + // And, if present, should have the expected type t.false(json.validateSchema(optionalSchema, { optionalKey: 0 })); t.false(json.validateSchema(optionalSchema, { optionalKey: 123 })); t.false(json.validateSchema(optionalSchema, { optionalKey: false })); @@ -44,26 +67,3 @@ test("validateSchema - optional properties are optional", async (t) => { t.true(json.validateSchema(optionalSchema, { optionalKey: "" })); t.true(json.validateSchema(optionalSchema, { optionalKey: "foo" })); }); - -const undefinableSchema = { - optionalKey: json.undefinable(json.string), -}; - -test("validateSchema - undefinable properties are optional but reject null", async (t) => { - // Optional fields may be absent or explicitly undefined - t.true(json.validateSchema(undefinableSchema, {})); - t.true(json.validateSchema(undefinableSchema, { optionalKey: undefined })); - - // But, unlike `optional`, `null` is rejected - t.false(json.validateSchema(undefinableSchema, { optionalKey: null })); - - // And, if present, should have the expected type - t.false(json.validateSchema(undefinableSchema, { optionalKey: 0 })); - t.false(json.validateSchema(undefinableSchema, { optionalKey: 123 })); - t.false(json.validateSchema(undefinableSchema, { optionalKey: false })); - t.false(json.validateSchema(undefinableSchema, { optionalKey: true })); - t.false(json.validateSchema(undefinableSchema, { optionalKey: [] })); - t.false(json.validateSchema(undefinableSchema, { optionalKey: {} })); - t.true(json.validateSchema(undefinableSchema, { optionalKey: "" })); - t.true(json.validateSchema(undefinableSchema, { optionalKey: "foo" })); -}); diff --git a/src/json/index.ts b/src/json/index.ts index 4a3f65947..66adc606b 100644 --- a/src/json/index.ts +++ b/src/json/index.ts @@ -76,7 +76,7 @@ export const object = { * Transforms a validator to be optional, accepting `undefined` or `null` for an * absent value. */ -export function optional(validator: Validator) { +export function optionalOrNull(validator: Validator) { return { validate: (val: unknown) => { return val === undefined || val === null || validator.validate(val); @@ -87,9 +87,9 @@ export function optional(validator: Validator) { /** * Transforms a validator to be optional, accepting `undefined` for an absent - * value but, unlike `optional`, rejecting `null`. + * value but, unlike `optionalOrNull`, rejecting `null`. */ -export function undefinable(validator: Validator) { +export function optional(validator: Validator) { return { validate: (val: unknown): val is T | undefined => { return val === undefined || validator.validate(val); diff --git a/src/start-proxy/types.ts b/src/start-proxy/types.ts index 13a4ce0e8..13369edbf 100644 --- a/src/start-proxy/types.ts +++ b/src/start-proxy/types.ts @@ -12,7 +12,7 @@ export type RawCredential = UnvalidatedObject; /** A schema for credential objects with a username. */ export const usernameSchema = { /** The username needed to authenticate to the package registry, if any. */ - username: json.optional(json.string), + username: json.optionalOrNull(json.string), } as const satisfies json.Schema; /** Usernames may be present for both authentication with tokens or passwords. */ @@ -29,7 +29,7 @@ export function hasUsername(config: AuthConfig): config is Username { /** A schema for credential objects with a username and password. */ export const usernamePasswordSchema = { /** The password needed to authenticate to the package registry, if any. */ - password: json.optional(json.string), + password: json.optionalOrNull(json.string), ...usernameSchema, } as const satisfies json.Schema; @@ -52,7 +52,7 @@ export function hasUsernameAndPassword( /** A schema for credential objects for token-based authentication. */ export const tokenSchema = { /** The token needed to authenticate to the package registry, if any. */ - token: json.optional(json.string), + token: json.optionalOrNull(json.string), ...usernameSchema, } as const satisfies json.Schema; @@ -100,7 +100,7 @@ export const awsConfigSchema = { "role-name": json.string, domain: json.string, "domain-owner": json.string, - audience: json.optional(json.string), + audience: json.optionalOrNull(json.string), } as const satisfies json.Schema; /** Configuration for AWS OIDC. */ @@ -116,8 +116,8 @@ export function isAWSConfig( /** A schema for JFrog OIDC configurations. */ export const jfrogConfigSchema = { "jfrog-oidc-provider-name": json.string, - audience: json.optional(json.string), - "identity-mapping-name": json.optional(json.string), + audience: json.optionalOrNull(json.string), + "identity-mapping-name": json.optionalOrNull(json.string), } as const satisfies json.Schema; /** Configuration for JFrog OIDC. */ @@ -150,8 +150,8 @@ export function isCloudsmithConfig( /** A schema for GCP OIDC configurations. */ export const gcpConfigSchema = { "workload-identity-provider": json.string, - "service-account": json.optional(json.string), - audience: json.optional(json.string), + "service-account": json.optionalOrNull(json.string), + audience: json.optionalOrNull(json.string), } as const satisfies json.Schema; /** Configuration for GCP OIDC. */