@confighub/api 0.2.0 → 0.4.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.
package/dist/index.cjs CHANGED
@@ -129,6 +129,38 @@ function getRevisionMutationSources(client, ref) {
129
129
  });
130
130
  }
131
131
 
132
+ // src/validation.ts
133
+ var SLUG_PATTERN = /^[A-Za-z0-9]([\-_.A-Za-z0-9]*[A-Za-z0-9])?$/;
134
+ var SLUG_MAX_LENGTH = 128;
135
+ var SLUG_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), and periods (.)";
136
+ var LABEL_KEY_PATTERN = /^[A-Za-z0-9]([\-_\./A-Za-z0-9]*[A-Za-z0-9])?$/;
137
+ var LABEL_KEY_MAX_LENGTH = 128;
138
+ var LABEL_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
139
+ var LABEL_VALUE_PATTERN = /^[\-_@/#$%&~+=!?.,:;(){}\[\]<>|A-Za-z0-9](([\-_@/#$%&~+=!?.,:;(){}\[\]<>|A-Za-z0-9]| )*[\-_@/#$%&~+=!?.,:;(){}\[\]<>|A-Za-z0-9])?$/;
140
+ var LABEL_VALUE_MAX_LENGTH = 128;
141
+ var LABEL_VALUE_PATTERN_MESSAGE = "Must start and end with a printable character (no leading/trailing spaces). Quotes, backslashes, and wildcards are not allowed";
142
+ var ANNOTATION_KEY_PATTERN = /^[A-Za-z0-9]([\-_\./A-Za-z0-9]*[A-Za-z0-9])?$/;
143
+ var ANNOTATION_KEY_MAX_LENGTH = 128;
144
+ var ANNOTATION_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
145
+ var ANNOTATION_VALUE_PATTERN = /^(.|\n)*$/;
146
+ var ANNOTATION_VALUE_MAX_LENGTH = 1024;
147
+ var ANNOTATION_VALUE_PATTERN_MESSAGE = "Any content is allowed, including multiline text";
148
+
149
+ exports.ANNOTATION_KEY_MAX_LENGTH = ANNOTATION_KEY_MAX_LENGTH;
150
+ exports.ANNOTATION_KEY_PATTERN = ANNOTATION_KEY_PATTERN;
151
+ exports.ANNOTATION_KEY_PATTERN_MESSAGE = ANNOTATION_KEY_PATTERN_MESSAGE;
152
+ exports.ANNOTATION_VALUE_MAX_LENGTH = ANNOTATION_VALUE_MAX_LENGTH;
153
+ exports.ANNOTATION_VALUE_PATTERN = ANNOTATION_VALUE_PATTERN;
154
+ exports.ANNOTATION_VALUE_PATTERN_MESSAGE = ANNOTATION_VALUE_PATTERN_MESSAGE;
155
+ exports.LABEL_KEY_MAX_LENGTH = LABEL_KEY_MAX_LENGTH;
156
+ exports.LABEL_KEY_PATTERN = LABEL_KEY_PATTERN;
157
+ exports.LABEL_KEY_PATTERN_MESSAGE = LABEL_KEY_PATTERN_MESSAGE;
158
+ exports.LABEL_VALUE_MAX_LENGTH = LABEL_VALUE_MAX_LENGTH;
159
+ exports.LABEL_VALUE_PATTERN = LABEL_VALUE_PATTERN;
160
+ exports.LABEL_VALUE_PATTERN_MESSAGE = LABEL_VALUE_PATTERN_MESSAGE;
161
+ exports.SLUG_MAX_LENGTH = SLUG_MAX_LENGTH;
162
+ exports.SLUG_PATTERN = SLUG_PATTERN;
163
+ exports.SLUG_PATTERN_MESSAGE = SLUG_PATTERN_MESSAGE;
132
164
  exports.createConfigHubClient = createConfigHubClient;
133
165
  exports.getReleaseData = getReleaseData;
134
166
  exports.getRevisionData = getRevisionData;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/data.ts"],"names":["createClient"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport createClient, { type Client, type Middleware } from 'openapi-fetch';\nimport type { paths } from './schema';\n\nexport interface ConfigHubClientOptions {\n /**\n * Base URL of the ConfigHub instance, e.g. `https://hub.confighub.com` — the same\n * value passed to the auth provider. The ConfigHub API is mounted under `/api`\n * (the spec's paths are relative to it), so the client targets `{baseUrl}/api`.\n * Passing a URL that already ends in `/api` is accepted as-is.\n */\n baseUrl: string;\n\n /**\n * Returns the current bearer token, or undefined when unauthenticated. May be\n * async so the caller can await a refresh. Wired as an openapi-fetch middleware\n * that sets `Authorization: Bearer <token>` per request. The client never stores\n * or refreshes tokens itself — that is the auth layer's job (see\n * `@confighub/react-auth`).\n */\n getToken?: () => string | undefined | Promise<string | undefined>;\n\n /**\n * Called when a request returns 401. A library must not redirect on its own, so\n * this hands control back to the caller — typically to trigger a token refresh\n * or re-login. The originating request is not retried automatically.\n */\n onUnauthorized?: () => void | Promise<void>;\n\n /** Override the fetch implementation (tests, non-browser runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\nexport type ConfigHubClient = Client<paths>;\n\nconst trimTrailingSlash = (s: string): string => s.replace(/\\/+$/, '');\n\n// The ConfigHub API lives under /api and the OpenAPI paths are relative to it. Accept\n// either the instance origin or a URL that already includes /api.\nconst apiBaseUrl = (baseUrl: string): string => {\n const trimmed = trimTrailingSlash(baseUrl);\n return trimmed.endsWith('/api') ? trimmed : trimmed + '/api';\n};\n\n/**\n * Create a typed ConfigHub API client. Every path, param, and response is derived\n * from the pinned OpenAPI spec (`src/schema.d.ts`), so it stays in lockstep with\n * the server.\n *\n * ```ts\n * const api = createConfigHubClient({ baseUrl, getToken: () => session.accessToken });\n * const { data, error } = await api.GET('/me');\n * const units = await api.GET('/space/{space_id}/unit', { params: { path: { space_id } } });\n * ```\n */\nexport function createConfigHubClient(options: ConfigHubClientOptions): ConfigHubClient {\n const { baseUrl, getToken, onUnauthorized, fetch: fetchImpl } = options;\n\n const client = createClient<paths>({\n baseUrl: apiBaseUrl(baseUrl),\n fetch: fetchImpl,\n });\n\n const middleware: Middleware = {\n async onRequest({ request }) {\n if (getToken) {\n const token = await getToken();\n if (token) request.headers.set('Authorization', `Bearer ${token}`);\n }\n // ConfigHub's PATCH endpoints expect RFC 7386 merge-patch semantics. This\n // mirrors the first-party UI, which sets the same content type for its\n // patch/bulk-patch operations.\n if (request.method === 'PATCH' && request.body != null) {\n request.headers.set('Content-Type', 'application/merge-patch+json');\n }\n return request;\n },\n async onResponse({ response }) {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized();\n }\n return response;\n },\n };\n\n client.use(middleware);\n return client;\n}\n","// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport type { ConfigHubClient } from './client';\nimport type { components } from './schema';\n\n/**\n * Configuration data is not a field of a Unit, a Revision, or a Release. It is read from\n * and written to its own endpoints, which serve the document itself as\n * `application/octet-stream` rather than a JSON envelope around it.\n *\n * These helpers exist because the two defaults of the underlying fetch client are both\n * wrong for that shape, and neither failure is visible to the type checker:\n *\n * - a read is parsed with `response.json()`, which throws on YAML, and\n * - a write is serialized with `JSON.stringify`, which would upload a quoted string.\n *\n * Everything else in the API is ordinary JSON and needs no wrapper — call the client\n * directly. In particular the bulk reads (`/unit_data`, `/revision_data`,\n * `/unit_mutation_sources`, `/revision_mutation_sources`) return JSON arrays, and a list\n * view should use those rather than one request per Unit.\n */\n\nexport type UnitCreateOrUpdateResponse = components['schemas']['UnitCreateOrUpdateResponse'];\nexport type MutationSourcesResponse = components['schemas']['MutationSourcesResponse'];\n\n/** Identifies a Unit. Both ids are required: the data endpoints are Space-scoped. */\nexport interface UnitRef {\n spaceId: string;\n unitId: string;\n}\n\n/** Identifies one Revision of a Unit. */\nexport interface RevisionRef extends UnitRef {\n revisionId: string;\n}\n\n/** Identifies a Release. */\nexport interface ReleaseRef {\n spaceId: string;\n releaseId: string;\n}\n\nexport interface ReadDataOptions {\n /**\n * A `DataHash` a previous read served, sent as `If-None-Match`. The server answers 304\n * when the configuration has not changed, which surfaces as `notModified: true` and no\n * `data` — keep what you already had.\n */\n ifNoneMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface ReadDataResult {\n /** The configuration, as text. Undefined on a 304 or an error. */\n data?: string;\n /** The `DataHash`, taken from the ETag. Pass it back as `ifNoneMatch` or `ifMatch`. */\n dataHash?: string;\n /** True when the server answered 304 because `ifNoneMatch` still matched. */\n notModified: boolean;\n /** The parsed error body, when the request failed. */\n error?: unknown;\n response: Response;\n}\n\n/**\n * Everything describing *how* a configuration should land belongs on the write that\n * carries it, not on a metadata update that precedes it. A metadata call changes no\n * configuration, so each of these has nothing to act on there and is silently dropped —\n * `mergeExternalSource` degrades to a plain overwrite that ignores protected paths, and\n * `dryRun` leaves the metadata call a dry run while this one really writes.\n */\nexport interface WriteDataOptions {\n /** Description recorded on the Revision this write creates. */\n lastChangeDescription?: string;\n /**\n * Extra parts of the result to return: `'ConfigData'`, `'MutationSources'`, or both,\n * comma-separated. For a `dryRun` nothing is stored, so this is the only way to see what\n * the operation produced. A name that is neither of these nor an expandable field is a 400.\n */\n include?: string;\n /** Compute the result and report it without storing anything. */\n dryRun?: boolean;\n /** Record the paths this write sets as protected local overrides. */\n protect?: boolean;\n /** The classes of guarded reason this write is cleared for, as a JSON Clearance. */\n clearance?: string;\n /** Revision providing the base configuration for a merge. */\n mergeBase?: string;\n /** Merge the body against the Unit as an external source rather than replacing it. */\n mergeExternalSource?: string;\n /** Also subtract the target's local differences from the source patch. */\n mergeEnableSubtraction?: boolean;\n /** Tag id to attach to the head Revision. */\n tag?: string;\n /** ChangeSet the write belongs to. */\n changeSetId?: string;\n /** User-defined category for the Mutation. */\n subgroup?: string;\n /**\n * A `DataHash` a read served, sent as `If-Match`, so the write fails rather than\n * clobbering a configuration somebody else changed in the meantime.\n */\n ifMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface WriteDataResult {\n /**\n * The operation's result. The Unit is in its `Unit` field — a write answers with what\n * it did, not with the entity.\n */\n data?: UnitCreateOrUpdateResponse;\n error?: unknown;\n response: Response;\n}\n\n// An ETag is the quoted DataHash, optionally weak. Give callers back the hash itself, so\n// it can go straight into If-Match / If-None-Match or be compared with Unit.DataHash.\nconst etagToHash = (response: Response): string | undefined => {\n const etag = response.headers.get('ETag');\n if (!etag) return undefined;\n return etag.replace(/^W\\//, '').replace(/^\"|\"$/g, '');\n};\n\nconst readData = async (\n call: Promise<{ data?: unknown; error?: unknown; response: Response }>,\n): Promise<ReadDataResult> => {\n const { data, error, response } = await call;\n if (response.status === 304) {\n return { notModified: true, dataHash: etagToHash(response), response };\n }\n if (!response.ok) {\n return { notModified: false, error, response };\n }\n // parseAs: 'text' below makes this a string; an empty body is an empty configuration,\n // which is a configuration, so it is not normalized away.\n return { data: (data as string | undefined) ?? '', dataHash: etagToHash(response), notModified: false, response };\n};\n\n/** A Unit's configuration, as text. */\nexport function getUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/data', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** One Revision's configuration, as text. */\nexport function getRevisionData(\n client: ConfigHubClient,\n ref: RevisionRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** A Release's bundle. Its ETag is the Release digest rather than a DataHash. */\nexport function getReleaseData(\n client: ConfigHubClient,\n ref: ReleaseRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/release/{release_id}/data', {\n params: { path: { space_id: ref.spaceId, release_id: ref.releaseId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/**\n * Replace a Unit's configuration. This is the only way configuration reaches a Unit other\n * than a clone, which copies it server-side: a metadata write has nowhere to put one, and\n * therefore nowhere to lose one.\n *\n * `data` is the document. An empty string is a real configuration — emptying a Unit is how\n * its resources are withdrawn — so never guard this call on the string being non-empty.\n * Track whether a configuration was *supplied* separately from what it contains.\n */\nexport function putUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n data: string,\n options: WriteDataOptions = {},\n): Promise<WriteDataResult> {\n const headers: Record<string, string> = { 'Content-Type': 'application/octet-stream' };\n if (options.ifMatch) headers['If-Match'] = `\"${options.ifMatch}\"`;\n\n return client.PUT('/space/{space_id}/unit/{unit_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId },\n query: {\n last_change_description: options.lastChangeDescription,\n include: options.include,\n dry_run: options.dryRun,\n protect: options.protect,\n clearance: options.clearance,\n merge_base: options.mergeBase,\n merge_external_source: options.mergeExternalSource,\n merge_enable_subtraction: options.mergeEnableSubtraction,\n tag: options.tag,\n change_set_id: options.changeSetId,\n subgroup: options.subgroup,\n },\n },\n headers,\n signal: options.signal,\n body: data,\n // The body is the configuration. The default serializer would JSON.stringify it and\n // upload a quoted string.\n bodySerializer: (body: string | undefined) => body ?? '',\n });\n}\n\n/** What set each value in a Unit's configuration. Ordinary JSON. */\nexport function getUnitMutationSources(client: ConfigHubClient, ref: UnitRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/mutation_sources', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n });\n}\n\n/** The Revision counterpart of {@link getUnitMutationSources}. */\nexport function getRevisionMutationSources(client: ConfigHubClient, ref: RevisionRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/mutation_sources', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/client.ts","../src/data.ts","../src/validation.ts"],"names":["createClient"],"mappings":"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","file":"index.cjs","sourcesContent":["// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport createClient, { type Client, type Middleware } from 'openapi-fetch';\nimport type { paths } from './schema';\n\nexport interface ConfigHubClientOptions {\n /**\n * Base URL of the ConfigHub instance, e.g. `https://hub.confighub.com` — the same\n * value passed to the auth provider. The ConfigHub API is mounted under `/api`\n * (the spec's paths are relative to it), so the client targets `{baseUrl}/api`.\n * Passing a URL that already ends in `/api` is accepted as-is.\n */\n baseUrl: string;\n\n /**\n * Returns the current bearer token, or undefined when unauthenticated. May be\n * async so the caller can await a refresh. Wired as an openapi-fetch middleware\n * that sets `Authorization: Bearer <token>` per request. The client never stores\n * or refreshes tokens itself — that is the auth layer's job (see\n * `@confighub/react-auth`).\n */\n getToken?: () => string | undefined | Promise<string | undefined>;\n\n /**\n * Called when a request returns 401. A library must not redirect on its own, so\n * this hands control back to the caller — typically to trigger a token refresh\n * or re-login. The originating request is not retried automatically.\n */\n onUnauthorized?: () => void | Promise<void>;\n\n /** Override the fetch implementation (tests, non-browser runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\nexport type ConfigHubClient = Client<paths>;\n\nconst trimTrailingSlash = (s: string): string => s.replace(/\\/+$/, '');\n\n// The ConfigHub API lives under /api and the OpenAPI paths are relative to it. Accept\n// either the instance origin or a URL that already includes /api.\nconst apiBaseUrl = (baseUrl: string): string => {\n const trimmed = trimTrailingSlash(baseUrl);\n return trimmed.endsWith('/api') ? trimmed : trimmed + '/api';\n};\n\n/**\n * Create a typed ConfigHub API client. Every path, param, and response is derived\n * from the pinned OpenAPI spec (`src/schema.d.ts`), so it stays in lockstep with\n * the server.\n *\n * ```ts\n * const api = createConfigHubClient({ baseUrl, getToken: () => session.accessToken });\n * const { data, error } = await api.GET('/me');\n * const units = await api.GET('/space/{space_id}/unit', { params: { path: { space_id } } });\n * ```\n */\nexport function createConfigHubClient(options: ConfigHubClientOptions): ConfigHubClient {\n const { baseUrl, getToken, onUnauthorized, fetch: fetchImpl } = options;\n\n const client = createClient<paths>({\n baseUrl: apiBaseUrl(baseUrl),\n fetch: fetchImpl,\n });\n\n const middleware: Middleware = {\n async onRequest({ request }) {\n if (getToken) {\n const token = await getToken();\n if (token) request.headers.set('Authorization', `Bearer ${token}`);\n }\n // ConfigHub's PATCH endpoints expect RFC 7386 merge-patch semantics. This\n // mirrors the first-party UI, which sets the same content type for its\n // patch/bulk-patch operations.\n if (request.method === 'PATCH' && request.body != null) {\n request.headers.set('Content-Type', 'application/merge-patch+json');\n }\n return request;\n },\n async onResponse({ response }) {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized();\n }\n return response;\n },\n };\n\n client.use(middleware);\n return client;\n}\n","// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport type { ConfigHubClient } from './client';\nimport type { components } from './schema';\n\n/**\n * Configuration data is not a field of a Unit, a Revision, or a Release. It is read from\n * and written to its own endpoints, which serve the document itself as\n * `application/octet-stream` rather than a JSON envelope around it.\n *\n * These helpers exist because the two defaults of the underlying fetch client are both\n * wrong for that shape, and neither failure is visible to the type checker:\n *\n * - a read is parsed with `response.json()`, which throws on YAML, and\n * - a write is serialized with `JSON.stringify`, which would upload a quoted string.\n *\n * Everything else in the API is ordinary JSON and needs no wrapper — call the client\n * directly. In particular the bulk reads (`/unit_data`, `/revision_data`,\n * `/unit_mutation_sources`, `/revision_mutation_sources`) return JSON arrays, and a list\n * view should use those rather than one request per Unit.\n */\n\nexport type UnitCreateOrUpdateResponse = components['schemas']['UnitCreateOrUpdateResponse'];\nexport type MutationSourcesResponse = components['schemas']['MutationSourcesResponse'];\n\n/** Identifies a Unit. Both ids are required: the data endpoints are Space-scoped. */\nexport interface UnitRef {\n spaceId: string;\n unitId: string;\n}\n\n/** Identifies one Revision of a Unit. */\nexport interface RevisionRef extends UnitRef {\n revisionId: string;\n}\n\n/** Identifies a Release. */\nexport interface ReleaseRef {\n spaceId: string;\n releaseId: string;\n}\n\nexport interface ReadDataOptions {\n /**\n * A `DataHash` a previous read served, sent as `If-None-Match`. The server answers 304\n * when the configuration has not changed, which surfaces as `notModified: true` and no\n * `data` — keep what you already had.\n */\n ifNoneMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface ReadDataResult {\n /** The configuration, as text. Undefined on a 304 or an error. */\n data?: string;\n /** The `DataHash`, taken from the ETag. Pass it back as `ifNoneMatch` or `ifMatch`. */\n dataHash?: string;\n /** True when the server answered 304 because `ifNoneMatch` still matched. */\n notModified: boolean;\n /** The parsed error body, when the request failed. */\n error?: unknown;\n response: Response;\n}\n\n/**\n * Everything describing *how* a configuration should land belongs on the write that\n * carries it, not on a metadata update that precedes it. A metadata call changes no\n * configuration, so each of these has nothing to act on there and is silently dropped —\n * `mergeExternalSource` degrades to a plain overwrite that ignores protected paths, and\n * `dryRun` leaves the metadata call a dry run while this one really writes.\n */\nexport interface WriteDataOptions {\n /** Description recorded on the Revision this write creates. */\n lastChangeDescription?: string;\n /**\n * Extra parts of the result to return: `'ConfigData'`, `'MutationSources'`, or both,\n * comma-separated. For a `dryRun` nothing is stored, so this is the only way to see what\n * the operation produced. A name that is neither of these nor an expandable field is a 400.\n */\n include?: string;\n /** Compute the result and report it without storing anything. */\n dryRun?: boolean;\n /** Record the paths this write sets as protected local overrides. */\n protect?: boolean;\n /** The classes of guarded reason this write is cleared for, as a JSON Clearance. */\n clearance?: string;\n /** Revision providing the base configuration for a merge. */\n mergeBase?: string;\n /** Merge the body against the Unit as an external source rather than replacing it. */\n mergeExternalSource?: string;\n /** Also subtract the target's local differences from the source patch. */\n mergeEnableSubtraction?: boolean;\n /** Tag id to attach to the head Revision. */\n tag?: string;\n /** ChangeSet the write belongs to. */\n changeSetId?: string;\n /** User-defined category for the Mutation. */\n subgroup?: string;\n /**\n * A `DataHash` a read served, sent as `If-Match`, so the write fails rather than\n * clobbering a configuration somebody else changed in the meantime.\n */\n ifMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface WriteDataResult {\n /**\n * The operation's result. The Unit is in its `Unit` field — a write answers with what\n * it did, not with the entity.\n */\n data?: UnitCreateOrUpdateResponse;\n error?: unknown;\n response: Response;\n}\n\n// An ETag is the quoted DataHash, optionally weak. Give callers back the hash itself, so\n// it can go straight into If-Match / If-None-Match or be compared with Unit.DataHash.\nconst etagToHash = (response: Response): string | undefined => {\n const etag = response.headers.get('ETag');\n if (!etag) return undefined;\n return etag.replace(/^W\\//, '').replace(/^\"|\"$/g, '');\n};\n\nconst readData = async (\n call: Promise<{ data?: unknown; error?: unknown; response: Response }>,\n): Promise<ReadDataResult> => {\n const { data, error, response } = await call;\n if (response.status === 304) {\n return { notModified: true, dataHash: etagToHash(response), response };\n }\n if (!response.ok) {\n return { notModified: false, error, response };\n }\n // parseAs: 'text' below makes this a string; an empty body is an empty configuration,\n // which is a configuration, so it is not normalized away.\n return { data: (data as string | undefined) ?? '', dataHash: etagToHash(response), notModified: false, response };\n};\n\n/** A Unit's configuration, as text. */\nexport function getUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/data', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** One Revision's configuration, as text. */\nexport function getRevisionData(\n client: ConfigHubClient,\n ref: RevisionRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** A Release's bundle. Its ETag is the Release digest rather than a DataHash. */\nexport function getReleaseData(\n client: ConfigHubClient,\n ref: ReleaseRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/release/{release_id}/data', {\n params: { path: { space_id: ref.spaceId, release_id: ref.releaseId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/**\n * Replace a Unit's configuration. This is the only way configuration reaches a Unit other\n * than a clone, which copies it server-side: a metadata write has nowhere to put one, and\n * therefore nowhere to lose one.\n *\n * `data` is the document. An empty string is a real configuration — emptying a Unit is how\n * its resources are withdrawn — so never guard this call on the string being non-empty.\n * Track whether a configuration was *supplied* separately from what it contains.\n */\nexport function putUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n data: string,\n options: WriteDataOptions = {},\n): Promise<WriteDataResult> {\n const headers: Record<string, string> = { 'Content-Type': 'application/octet-stream' };\n if (options.ifMatch) headers['If-Match'] = `\"${options.ifMatch}\"`;\n\n return client.PUT('/space/{space_id}/unit/{unit_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId },\n query: {\n last_change_description: options.lastChangeDescription,\n include: options.include,\n dry_run: options.dryRun,\n protect: options.protect,\n clearance: options.clearance,\n merge_base: options.mergeBase,\n merge_external_source: options.mergeExternalSource,\n merge_enable_subtraction: options.mergeEnableSubtraction,\n tag: options.tag,\n change_set_id: options.changeSetId,\n subgroup: options.subgroup,\n },\n },\n headers,\n signal: options.signal,\n body: data,\n // The body is the configuration. The default serializer would JSON.stringify it and\n // upload a quoted string.\n bodySerializer: (body: string | undefined) => body ?? '',\n });\n}\n\n/** What set each value in a Unit's configuration. Ordinary JSON. */\nexport function getUnitMutationSources(client: ConfigHubClient, ref: UnitRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/mutation_sources', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n });\n}\n\n/** The Revision counterpart of {@link getUnitMutationSources}. */\nexport function getRevisionMutationSources(client: ConfigHubClient, ref: RevisionRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/mutation_sources', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n });\n}\n","// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n//\n// Generated by the ConfigHub server from its own validation rules; synced by\n// scripts/sync-spec.mjs at the pinned version. Do not edit.\n\nexport const SLUG_PATTERN = /^[A-Za-z0-9]([\\-_.A-Za-z0-9]*[A-Za-z0-9])?$/;\nexport const SLUG_MAX_LENGTH = 128;\nexport const SLUG_PATTERN_MESSAGE =\n 'Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), and periods (.)';\n\nexport const LABEL_KEY_PATTERN = /^[A-Za-z0-9]([\\-_\\./A-Za-z0-9]*[A-Za-z0-9])?$/;\nexport const LABEL_KEY_MAX_LENGTH = 128;\nexport const LABEL_KEY_PATTERN_MESSAGE =\n 'Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)';\n\nexport const LABEL_VALUE_PATTERN = /^[\\-_@/#$%&~+=!?.,:;(){}\\[\\]<>|A-Za-z0-9](([\\-_@/#$%&~+=!?.,:;(){}\\[\\]<>|A-Za-z0-9]| )*[\\-_@/#$%&~+=!?.,:;(){}\\[\\]<>|A-Za-z0-9])?$/;\nexport const LABEL_VALUE_MAX_LENGTH = 128;\nexport const LABEL_VALUE_PATTERN_MESSAGE =\n 'Must start and end with a printable character (no leading/trailing spaces). Quotes, backslashes, and wildcards are not allowed';\n\nexport const ANNOTATION_KEY_PATTERN = /^[A-Za-z0-9]([\\-_\\./A-Za-z0-9]*[A-Za-z0-9])?$/;\nexport const ANNOTATION_KEY_MAX_LENGTH = 128;\nexport const ANNOTATION_KEY_PATTERN_MESSAGE =\n 'Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)';\n\nexport const ANNOTATION_VALUE_PATTERN = /^(.|\\n)*$/;\nexport const ANNOTATION_VALUE_MAX_LENGTH = 1024;\nexport const ANNOTATION_VALUE_PATTERN_MESSAGE =\n 'Any content is allowed, including multiline text';\n\n"]}
package/dist/index.d.cts CHANGED
@@ -2539,9 +2539,10 @@ interface components {
2539
2539
  BoundProvidedProperties?: {
2540
2540
  [key: string]: string;
2541
2541
  };
2542
+ /** @description Value a defaulting function writes at this path, if any */
2543
+ DefaultValue?: unknown;
2542
2544
  /** @description Description of the attribute */
2543
2545
  Description?: string;
2544
- GetterInvocation?: components["schemas"]["FunctionInvocation"];
2545
2546
  /** @description Whether this attribute is a needed value */
2546
2547
  IsNeeded?: boolean;
2547
2548
  /** @description Whether this attribute is a provided value */
@@ -2558,8 +2559,6 @@ interface components {
2558
2559
  ProvidedProperties?: {
2559
2560
  [key: string]: string;
2560
2561
  };
2561
- /** @description Function invocation used to set the attribute (except for the value), if any */
2562
- SetterInvocations?: components["schemas"]["FunctionInvocation"][];
2563
2562
  };
2564
2563
  AttributeInfo: {
2565
2564
  /** @description Name of the registered attribute */
@@ -2864,10 +2863,20 @@ interface components {
2864
2863
  * @example 248df4b7-aa70-47b8-a036-33ac447e668d
2865
2864
  */
2866
2865
  OrganizationID?: string;
2866
+ /** @description ReleasedRestoredSpaceIDs is where the undoing has been released: the Spaces in RestoredSpaceIDs whose Units are released at or past the Revision the restore Tag marks. Covering ReleasedSpaceIDs is what State reports as RestoreReleased. Derived when the ChangeOrder is read. */
2867
+ readonly ReleasedRestoredSpaceIDs?: components["schemas"]["UUID"][];
2867
2868
  /** @description ReleasedSpaceIDs is where the ChangeOrder has been released: the Spaces in scope whose Units in the Space's release are applied at or past the Revision the end Tag marks. Derived when the ChangeOrder is read. */
2868
2869
  readonly ReleasedSpaceIDs?: components["schemas"]["UUID"][];
2869
2870
  /** @description ResolvedSpaceIDs is where the ChangeOrder has been fully propagated to: the Spaces in scope whose Links of its UpdateType have all merged it, plus the Space it resides in. Derived when the ChangeOrder is read. */
2870
2871
  readonly ResolvedSpaceIDs?: components["schemas"]["UUID"][];
2872
+ /**
2873
+ * Format: uuid
2874
+ * @description RestoreTagID is the Tag marking the Revisions that undid the ChangeOrder. The first restore mints it; every restore after that marks with the same Tag. Empty until something has been restored.
2875
+ * @example 248df4b7-aa70-47b8-a036-33ac447e668d
2876
+ */
2877
+ readonly RestoreTagID?: string;
2878
+ /** @description RestoredSpaceIDs is where the ChangeOrder has been undone: the Spaces whose Units all carry the restore Tag. Derived when the ChangeOrder is read. */
2879
+ readonly RestoredSpaceIDs?: components["schemas"]["UUID"][];
2871
2880
  /** @description SkippedUnits names the Units of the ChangeOrder's Space that it carries no Revisions of, mapped to the reason. Written when the scope is derived. A skipped Unit may still be marked by the ChangeOrder's Tags, when the Spaces in scope had already taken it. */
2872
2881
  readonly SkippedUnits?: {
2873
2882
  [key: string]: string;
@@ -2888,7 +2897,7 @@ interface components {
2888
2897
  * @example 248df4b7-aa70-47b8-a036-33ac447e668d
2889
2898
  */
2890
2899
  readonly StartTagID?: string;
2891
- /** @description State is how far the ChangeOrder has got: New until a Space other than its own has taken it, InProgress while some have and some have not, Resolved once every Space in scope has, Released once every Space in scope has released what it took, and Aborted whenever AbortedReason is set. Derived when the ChangeOrder is read. */
2900
+ /** @description State is how far the ChangeOrder has got: New until a Space other than its own has taken it, InProgress while some have and some have not, Resolved once every Space in scope has, Released once every Space in scope has released what it took, Aborted whenever AbortedReason is set, Restored once every Space that had taken it has been restored to the Revisions before it, and RestoreReleased once every Space that had released it has released the restored Revisions. Derived when the ChangeOrder is read. */
2892
2901
  readonly State?: string;
2893
2902
  /** @description UpdateType is the Link UpdateType this ChangeOrder follows when propagating. UpgradeUnit, the clone lineage, is the default; MergeUnits is the other supported value. */
2894
2903
  UpdateType?: string;
@@ -3061,6 +3070,7 @@ interface components {
3061
3070
  EndTag?: components["schemas"]["Tag"];
3062
3071
  Error?: components["schemas"]["ResponseError"];
3063
3072
  Organization?: components["schemas"]["Organization"];
3073
+ RestoreTag?: components["schemas"]["Tag"];
3064
3074
  Space?: components["schemas"]["Space"];
3065
3075
  StartTag?: components["schemas"]["Tag"];
3066
3076
  };
@@ -3339,6 +3349,7 @@ interface components {
3339
3349
  Clearance?: components["schemas"]["Clearance"];
3340
3350
  /** @description Function name */
3341
3351
  FunctionName?: string;
3352
+ Guards?: components["schemas"]["GuardStamp"];
3342
3353
  /** @description Caller-supplied parameter values for expanding templated argument Values; transient, not persisted */
3343
3354
  Params?: {
3344
3355
  [key: string]: unknown;
@@ -3378,6 +3389,7 @@ interface components {
3378
3389
  FunctionInvocationsResponse: {
3379
3390
  /** @description The resulting configuration data; present only when the invocation changed it */
3380
3391
  ConfigData?: string;
3392
+ Conflicts?: components["schemas"]["MutationConflictList"];
3381
3393
  /** @description SHA256 of the resulting configuration data, whether or not ConfigData is present */
3382
3394
  DataHash?: string;
3383
3395
  Error?: components["schemas"]["ResponseError"];
@@ -3510,6 +3522,9 @@ interface components {
3510
3522
  [key: string]: string;
3511
3523
  };
3512
3524
  };
3525
+ GuardStamp: {
3526
+ [key: string]: string;
3527
+ };
3513
3528
  /** @description Defines a stored, reusable call to one or more functions, executed in the order they are listed. */
3514
3529
  Invocation: {
3515
3530
  /** @description An optional map of Annotation key/value pairs for tools to attach information to entities. */
@@ -3648,6 +3663,7 @@ interface components {
3648
3663
  * @example 248df4b7-aa70-47b8-a036-33ac447e668d
3649
3664
  */
3650
3665
  FromUnitID: string;
3666
+ Guards?: components["schemas"]["GuardStamp"];
3651
3667
  /** @description SHA256 hash of the resolution-relevant Link fields, used to detect changes that require re-resolution. */
3652
3668
  readonly Hash?: string;
3653
3669
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -4460,7 +4476,6 @@ interface components {
4460
4476
  BoundProvidedProperties?: {
4461
4477
  [key: string]: string;
4462
4478
  };
4463
- GetterInvocation?: components["schemas"]["FunctionInvocation"];
4464
4479
  /** @description Whether this attribute is a needed value */
4465
4480
  IsNeeded?: boolean;
4466
4481
  /** @description Whether this attribute is a provided value */
@@ -4479,7 +4494,6 @@ interface components {
4479
4494
  [key: string]: string;
4480
4495
  };
4481
4496
  ResourceType?: string;
4482
- SetterInvocation?: components["schemas"]["FunctionInvocation"];
4483
4497
  };
4484
4498
  ResponseError: {
4485
4499
  /** @description Additional context messages */
@@ -5161,6 +5175,7 @@ interface components {
5161
5175
  FailOpenAfter?: number | null;
5162
5176
  /** @description Function name */
5163
5177
  FunctionName?: string;
5178
+ Guards?: components["schemas"]["GuardStamp"];
5164
5179
  /** @description SHA256 hash of the trigger's specification fields, used to detect changes. */
5165
5180
  readonly Hash?: string;
5166
5181
  /**
@@ -8240,7 +8255,7 @@ interface operations {
8240
8255
  * An example conjunction is:
8241
8256
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8242
8257
  *
8243
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8258
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8244
8259
  *
8245
8260
  * The whole string must be query-encoded.
8246
8261
  */
@@ -8282,7 +8297,7 @@ interface operations {
8282
8297
  * The attribute names are case-sensitive, PascalCase, and
8283
8298
  * expected in a comma-separated list format as in the JSON encoding.
8284
8299
  *
8285
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8300
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8286
8301
  *
8287
8302
  * The whole string must be query-encoded.
8288
8303
  */
@@ -8408,7 +8423,7 @@ interface operations {
8408
8423
  * An example conjunction is:
8409
8424
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8410
8425
  *
8411
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8426
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8412
8427
  *
8413
8428
  * The whole string must be query-encoded.
8414
8429
  */
@@ -8450,7 +8465,7 @@ interface operations {
8450
8465
  * The attribute names are case-sensitive, PascalCase, and
8451
8466
  * expected in a comma-separated list format as in the JSON encoding.
8452
8467
  *
8453
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8468
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8454
8469
  *
8455
8470
  * The whole string must be query-encoded.
8456
8471
  */
@@ -8676,7 +8691,7 @@ interface operations {
8676
8691
  * An example conjunction is:
8677
8692
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8678
8693
  *
8679
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8694
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8680
8695
  *
8681
8696
  * The whole string must be query-encoded.
8682
8697
  */
@@ -8718,7 +8733,7 @@ interface operations {
8718
8733
  * The attribute names are case-sensitive, PascalCase, and
8719
8734
  * expected in a comma-separated list format as in the JSON encoding.
8720
8735
  *
8721
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8736
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8722
8737
  *
8723
8738
  * The whole string must be query-encoded.
8724
8739
  */
@@ -8860,7 +8875,7 @@ interface operations {
8860
8875
  * An example conjunction is:
8861
8876
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8862
8877
  *
8863
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8878
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8864
8879
  *
8865
8880
  * The whole string must be query-encoded.
8866
8881
  */
@@ -8902,7 +8917,7 @@ interface operations {
8902
8917
  * The attribute names are case-sensitive, PascalCase, and
8903
8918
  * expected in a comma-separated list format as in the JSON encoding.
8904
8919
  *
8905
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8920
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8906
8921
  *
8907
8922
  * The whole string must be query-encoded.
8908
8923
  */
@@ -10800,6 +10815,8 @@ interface operations {
10800
10815
  protect?: boolean;
10801
10816
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
10802
10817
  clearance?: string;
10818
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
10819
+ guards?: string;
10803
10820
  /** @description Must match ChangeSetID of affected Units unless in dry run mode; not valid when invoked on Revisions */
10804
10821
  change_set_id?: string;
10805
10822
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
@@ -12197,6 +12214,10 @@ interface operations {
12197
12214
  DownstreamSetters?: (Record<string, never> | null)[] | null;
12198
12215
  /** Format: uuid */
12199
12216
  FromUnitID?: string | null;
12217
+ /** @description Guards to record on the paths this link's resolve writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Refused on UpgradeUnit and MergeUnits links, whose guards arrive by propagation from upstream. */
12218
+ Guards?: {
12219
+ [key: string]: string | null;
12220
+ } | null;
12200
12221
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
12201
12222
  Labels?: {
12202
12223
  [key: string]: string | null;
@@ -12608,6 +12629,10 @@ interface operations {
12608
12629
  DownstreamSetters?: (Record<string, never> | null)[] | null;
12609
12630
  /** Format: uuid */
12610
12631
  FromUnitID?: string | null;
12632
+ /** @description Guards to record on the paths this link's resolve writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Refused on UpgradeUnit and MergeUnits links, whose guards arrive by propagation from upstream. */
12633
+ Guards?: {
12634
+ [key: string]: string | null;
12635
+ } | null;
12611
12636
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
12612
12637
  Labels?: {
12613
12638
  [key: string]: string | null;
@@ -17407,7 +17432,7 @@ interface operations {
17407
17432
  * An example conjunction is:
17408
17433
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
17409
17434
  *
17410
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
17435
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
17411
17436
  *
17412
17437
  * The whole string must be query-encoded.
17413
17438
  */
@@ -17449,7 +17474,7 @@ interface operations {
17449
17474
  * The attribute names are case-sensitive, PascalCase, and
17450
17475
  * expected in a comma-separated list format as in the JSON encoding.
17451
17476
  *
17452
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
17477
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
17453
17478
  *
17454
17479
  * The whole string must be query-encoded.
17455
17480
  */
@@ -17641,7 +17666,7 @@ interface operations {
17641
17666
  * The attribute names are case-sensitive, PascalCase, and
17642
17667
  * expected in a comma-separated list format as in the JSON encoding.
17643
17668
  *
17644
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
17669
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
17645
17670
  *
17646
17671
  * The whole string must be query-encoded.
17647
17672
  */
@@ -19520,6 +19545,8 @@ interface operations {
19520
19545
  protect?: boolean;
19521
19546
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
19522
19547
  clearance?: string;
19548
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
19549
+ guards?: string;
19523
19550
  /** @description Must match ChangeSetID of affected Units unless in dry run mode; not valid when invoked on Revisions */
19524
19551
  change_set_id?: string;
19525
19552
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
@@ -21001,6 +21028,10 @@ interface operations {
21001
21028
  DownstreamSetters?: (Record<string, never> | null)[] | null;
21002
21029
  /** Format: uuid */
21003
21030
  FromUnitID?: string | null;
21031
+ /** @description Guards to record on the paths this link's resolve writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Refused on UpgradeUnit and MergeUnits links, whose guards arrive by propagation from upstream. */
21032
+ Guards?: {
21033
+ [key: string]: string | null;
21034
+ } | null;
21004
21035
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
21005
21036
  Labels?: {
21006
21037
  [key: string]: string | null;
@@ -23916,6 +23947,10 @@ interface operations {
23916
23947
  FailOpenAfter?: number | null;
23917
23948
  /** @description Function name */
23918
23949
  FunctionName?: string | null;
23950
+ /** @description Guards to record on the paths this trigger's function writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Only meaningful for a mutating trigger, and part of the trigger's Hash, unlike Protect. */
23951
+ Guards?: {
23952
+ [key: string]: string | null;
23953
+ } | null;
23919
23954
  /** Format: uuid */
23920
23955
  InvocationID?: string | null;
23921
23956
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -24436,6 +24471,8 @@ interface operations {
24436
24471
  protect?: boolean;
24437
24472
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
24438
24473
  clearance?: string;
24474
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
24475
+ guards?: string;
24439
24476
  /** @description Merge the range as one rebased diff and record it as one Revision, instead of walking it. By default a merge replays: it takes the source's Revisions in order and, where a Revision records function invocations that can be re-executed, runs them against this Unit rather than rebasing their recorded paths onto it -- so a change lands where this Unit's own structure puts it -- and records each source Revision that has an effect here as a Revision of its own, carrying that Revision's change description, its own conflicts, and one Mutation per source Mutation. Squashing gives up both: the range arrives as a single rebased patch in a single Revision, which is what a merge did before replay existed. Accepted with upgrade, merge_source, and resolve of an UpgradeUnit or MergeUnits Link, and refused elsewhere, since there is no range to walk. A Link can ask for it standingly with its Squash field. */
24440
24477
  squash?: boolean;
24441
24478
  /** @description Upgrade the unit to the latest version of its upstream unit */
@@ -24514,7 +24551,7 @@ interface operations {
24514
24551
  tag?: string;
24515
24552
  /** @description Must match ChangeSetID of affected Units if config Data is changed unless in dry run mode */
24516
24553
  change_set_id?: string;
24517
- /** @description ChangeOrder to promote, with upgrade or resolve. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. */
24554
+ /** @description ChangeOrder to promote, with upgrade or resolve, or to undo, with restore. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. With restore the change order is being undone rather than promoted: the restore must be 'Before:ChangeOrder:' the same change order, the change order must have an AbortedReason -- undoing a change nobody has said is not coming is a race with whoever is still promoting it -- and a Unit the change order never marked is an error rather than passed over, since naming it says the Unit is part of the undoing. The first restore mints the change order's restore Tag and records it as RestoreTagID; every restore after that marks with the same Tag, which is what RestoredSpaceIDs is read off. A Unit the change order carried nothing for takes the restore Tag on the revision its start and end Tags are already on, and no revision is made. A Unit already carrying the restore Tag has had the change order taken back out of it and is passed over, since undoing one in a Unit happens once as promoting it into one does -- so the revisions a Unit has taken since it was undone are its own work rather than this undoing's to drop. Restoring also advances the merge pointers of the Links of the change order's UpdateType that follow the restored Unit onto the revision the restore made, so a later upgrade does not replay the change that was just taken out; the downstream Units are not restored with it, since each has to be restored and released on its own account. */
24518
24555
  change_order?: string;
24519
24556
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
24520
24557
  subgroup?: string;
@@ -24736,6 +24773,8 @@ interface operations {
24736
24773
  protect?: boolean;
24737
24774
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
24738
24775
  clearance?: string;
24776
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
24777
+ guards?: string;
24739
24778
  /** @description Merge the range as one rebased diff and record it as one Revision, instead of walking it. By default a merge replays: it takes the source's Revisions in order and, where a Revision records function invocations that can be re-executed, runs them against this Unit rather than rebasing their recorded paths onto it -- so a change lands where this Unit's own structure puts it -- and records each source Revision that has an effect here as a Revision of its own, carrying that Revision's change description, its own conflicts, and one Mutation per source Mutation. Squashing gives up both: the range arrives as a single rebased patch in a single Revision, which is what a merge did before replay existed. Accepted with upgrade, merge_source, and resolve of an UpgradeUnit or MergeUnits Link, and refused elsewhere, since there is no range to walk. A Link can ask for it standingly with its Squash field. */
24740
24779
  squash?: boolean;
24741
24780
  /** @description Upgrade the unit to the latest version of its upstream unit */
@@ -24814,7 +24853,7 @@ interface operations {
24814
24853
  tag?: string;
24815
24854
  /** @description Must match ChangeSetID of affected Units if config Data is changed unless in dry run mode */
24816
24855
  change_set_id?: string;
24817
- /** @description ChangeOrder to promote, with upgrade or resolve. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. */
24856
+ /** @description ChangeOrder to promote, with upgrade or resolve, or to undo, with restore. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. With restore the change order is being undone rather than promoted: the restore must be 'Before:ChangeOrder:' the same change order, the change order must have an AbortedReason -- undoing a change nobody has said is not coming is a race with whoever is still promoting it -- and a Unit the change order never marked is an error rather than passed over, since naming it says the Unit is part of the undoing. The first restore mints the change order's restore Tag and records it as RestoreTagID; every restore after that marks with the same Tag, which is what RestoredSpaceIDs is read off. A Unit the change order carried nothing for takes the restore Tag on the revision its start and end Tags are already on, and no revision is made. A Unit already carrying the restore Tag has had the change order taken back out of it and is passed over, since undoing one in a Unit happens once as promoting it into one does -- so the revisions a Unit has taken since it was undone are its own work rather than this undoing's to drop. Restoring also advances the merge pointers of the Links of the change order's UpdateType that follow the restored Unit onto the revision the restore made, so a later upgrade does not replay the change that was just taken out; the downstream Units are not restored with it, since each has to be restored and released on its own account. */
24818
24857
  change_order?: string;
24819
24858
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
24820
24859
  subgroup?: string;
@@ -25236,6 +25275,8 @@ interface operations {
25236
25275
  protect?: boolean;
25237
25276
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
25238
25277
  clearance?: string;
25278
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
25279
+ guards?: string;
25239
25280
  /** @description Merge base revision, which provides the base configuration data of the changes to merge. With merge_source, this is a revision of the merge source unit. With merge_external_source, this is a revision of the unit being updated and overrides the default selection of the latest MergeExternal revision. Supports: Named revisions ('HeadRevisionNum', 'LastReleasedRevisionNum'), direct revision number (e.g., '42'), or entity references ('Tag:uuid', 'ChangeSet:uuid', 'ChangeOrder:uuid', 'Revision:uuid'). Can be prefixed with 'Before:' to select the revision immediately before the specified one (e.g., 'Before:LastReleasedRevisionNum', 'Before:42'). When using Tag or ChangeSet references, the latest revision associated with that entity is selected. 'ChangeOrder:uuid' selects the revision the change order ended at on this Unit and 'Before:ChangeOrder:uuid' the one before it began, which is what undoes a promotion however many revisions it made. */
25240
25281
  merge_base?: string;
25241
25282
  /** @description Identifier of the external source for merge-on-update. When set, computes mutations between the last MergeExternal revision and the provided data, then patches the current unit data with those mutations. */
@@ -29663,6 +29704,10 @@ interface operations {
29663
29704
  FailOpenAfter?: number | null;
29664
29705
  /** @description Function name */
29665
29706
  FunctionName?: string | null;
29707
+ /** @description Guards to record on the paths this trigger's function writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Only meaningful for a mutating trigger, and part of the trigger's Hash, unlike Protect. */
29708
+ Guards?: {
29709
+ [key: string]: string | null;
29710
+ } | null;
29666
29711
  /** Format: uuid */
29667
29712
  InvocationID?: string | null;
29668
29713
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -30069,6 +30114,10 @@ interface operations {
30069
30114
  FailOpenAfter?: number | null;
30070
30115
  /** @description Function name */
30071
30116
  FunctionName?: string | null;
30117
+ /** @description Guards to record on the paths this trigger's function writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Only meaningful for a mutating trigger, and part of the trigger's Hash, unlike Protect. */
30118
+ Guards?: {
30119
+ [key: string]: string | null;
30120
+ } | null;
30072
30121
  /** Format: uuid */
30073
30122
  InvocationID?: string | null;
30074
30123
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -30989,6 +31038,8 @@ interface operations {
30989
31038
  protect?: boolean;
30990
31039
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
30991
31040
  clearance?: string;
31041
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
31042
+ guards?: string;
30992
31043
  /** @description Merge the range as one rebased diff and record it as one Revision, instead of walking it. By default a merge replays: it takes the source's Revisions in order and, where a Revision records function invocations that can be re-executed, runs them against this Unit rather than rebasing their recorded paths onto it -- so a change lands where this Unit's own structure puts it -- and records each source Revision that has an effect here as a Revision of its own, carrying that Revision's change description, its own conflicts, and one Mutation per source Mutation. Squashing gives up both: the range arrives as a single rebased patch in a single Revision, which is what a merge did before replay existed. Accepted with upgrade, merge_source, and resolve of an UpgradeUnit or MergeUnits Link, and refused elsewhere, since there is no range to walk. A Link can ask for it standingly with its Squash field. */
30993
31044
  squash?: boolean;
30994
31045
  /** @description Upgrade the unit to the latest version of its upstream unit */
@@ -31067,7 +31118,7 @@ interface operations {
31067
31118
  tag?: string;
31068
31119
  /** @description Must match ChangeSetID of affected Units if config Data is changed unless in dry run mode */
31069
31120
  change_set_id?: string;
31070
- /** @description ChangeOrder to promote, with upgrade or resolve. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. */
31121
+ /** @description ChangeOrder to promote, with upgrade or resolve, or to undo, with restore. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. With restore the change order is being undone rather than promoted: the restore must be 'Before:ChangeOrder:' the same change order, the change order must have an AbortedReason -- undoing a change nobody has said is not coming is a race with whoever is still promoting it -- and a Unit the change order never marked is an error rather than passed over, since naming it says the Unit is part of the undoing. The first restore mints the change order's restore Tag and records it as RestoreTagID; every restore after that marks with the same Tag, which is what RestoredSpaceIDs is read off. A Unit the change order carried nothing for takes the restore Tag on the revision its start and end Tags are already on, and no revision is made. A Unit already carrying the restore Tag has had the change order taken back out of it and is passed over, since undoing one in a Unit happens once as promoting it into one does -- so the revisions a Unit has taken since it was undone are its own work rather than this undoing's to drop. Restoring also advances the merge pointers of the Links of the change order's UpdateType that follow the restored Unit onto the revision the restore made, so a later upgrade does not replay the change that was just taken out; the downstream Units are not restored with it, since each has to be restored and released on its own account. */
31071
31122
  change_order?: string;
31072
31123
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
31073
31124
  subgroup?: string;
@@ -34149,4 +34200,20 @@ declare function getRevisionMutationSources(client: ConfigHubClient, ref: Revisi
34149
34200
  };
34150
34201
  }, `${string}/${string}`>>;
34151
34202
 
34152
- export { type ConfigHubClient, type ConfigHubClientOptions, type MutationSourcesResponse, type ReadDataOptions, type ReadDataResult, type ReleaseRef, type RevisionRef, type UnitCreateOrUpdateResponse, type UnitRef, type WriteDataOptions, type WriteDataResult, type components, createConfigHubClient, getReleaseData, getRevisionData, getRevisionMutationSources, getUnitData, getUnitMutationSources, type operations, type paths, putUnitData };
34203
+ declare const SLUG_PATTERN: RegExp;
34204
+ declare const SLUG_MAX_LENGTH = 128;
34205
+ declare const SLUG_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), and periods (.)";
34206
+ declare const LABEL_KEY_PATTERN: RegExp;
34207
+ declare const LABEL_KEY_MAX_LENGTH = 128;
34208
+ declare const LABEL_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
34209
+ declare const LABEL_VALUE_PATTERN: RegExp;
34210
+ declare const LABEL_VALUE_MAX_LENGTH = 128;
34211
+ declare const LABEL_VALUE_PATTERN_MESSAGE = "Must start and end with a printable character (no leading/trailing spaces). Quotes, backslashes, and wildcards are not allowed";
34212
+ declare const ANNOTATION_KEY_PATTERN: RegExp;
34213
+ declare const ANNOTATION_KEY_MAX_LENGTH = 128;
34214
+ declare const ANNOTATION_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
34215
+ declare const ANNOTATION_VALUE_PATTERN: RegExp;
34216
+ declare const ANNOTATION_VALUE_MAX_LENGTH = 1024;
34217
+ declare const ANNOTATION_VALUE_PATTERN_MESSAGE = "Any content is allowed, including multiline text";
34218
+
34219
+ export { ANNOTATION_KEY_MAX_LENGTH, ANNOTATION_KEY_PATTERN, ANNOTATION_KEY_PATTERN_MESSAGE, ANNOTATION_VALUE_MAX_LENGTH, ANNOTATION_VALUE_PATTERN, ANNOTATION_VALUE_PATTERN_MESSAGE, type ConfigHubClient, type ConfigHubClientOptions, LABEL_KEY_MAX_LENGTH, LABEL_KEY_PATTERN, LABEL_KEY_PATTERN_MESSAGE, LABEL_VALUE_MAX_LENGTH, LABEL_VALUE_PATTERN, LABEL_VALUE_PATTERN_MESSAGE, type MutationSourcesResponse, type ReadDataOptions, type ReadDataResult, type ReleaseRef, type RevisionRef, SLUG_MAX_LENGTH, SLUG_PATTERN, SLUG_PATTERN_MESSAGE, type UnitCreateOrUpdateResponse, type UnitRef, type WriteDataOptions, type WriteDataResult, type components, createConfigHubClient, getReleaseData, getRevisionData, getRevisionMutationSources, getUnitData, getUnitMutationSources, type operations, type paths, putUnitData };
package/dist/index.d.ts CHANGED
@@ -2539,9 +2539,10 @@ interface components {
2539
2539
  BoundProvidedProperties?: {
2540
2540
  [key: string]: string;
2541
2541
  };
2542
+ /** @description Value a defaulting function writes at this path, if any */
2543
+ DefaultValue?: unknown;
2542
2544
  /** @description Description of the attribute */
2543
2545
  Description?: string;
2544
- GetterInvocation?: components["schemas"]["FunctionInvocation"];
2545
2546
  /** @description Whether this attribute is a needed value */
2546
2547
  IsNeeded?: boolean;
2547
2548
  /** @description Whether this attribute is a provided value */
@@ -2558,8 +2559,6 @@ interface components {
2558
2559
  ProvidedProperties?: {
2559
2560
  [key: string]: string;
2560
2561
  };
2561
- /** @description Function invocation used to set the attribute (except for the value), if any */
2562
- SetterInvocations?: components["schemas"]["FunctionInvocation"][];
2563
2562
  };
2564
2563
  AttributeInfo: {
2565
2564
  /** @description Name of the registered attribute */
@@ -2864,10 +2863,20 @@ interface components {
2864
2863
  * @example 248df4b7-aa70-47b8-a036-33ac447e668d
2865
2864
  */
2866
2865
  OrganizationID?: string;
2866
+ /** @description ReleasedRestoredSpaceIDs is where the undoing has been released: the Spaces in RestoredSpaceIDs whose Units are released at or past the Revision the restore Tag marks. Covering ReleasedSpaceIDs is what State reports as RestoreReleased. Derived when the ChangeOrder is read. */
2867
+ readonly ReleasedRestoredSpaceIDs?: components["schemas"]["UUID"][];
2867
2868
  /** @description ReleasedSpaceIDs is where the ChangeOrder has been released: the Spaces in scope whose Units in the Space's release are applied at or past the Revision the end Tag marks. Derived when the ChangeOrder is read. */
2868
2869
  readonly ReleasedSpaceIDs?: components["schemas"]["UUID"][];
2869
2870
  /** @description ResolvedSpaceIDs is where the ChangeOrder has been fully propagated to: the Spaces in scope whose Links of its UpdateType have all merged it, plus the Space it resides in. Derived when the ChangeOrder is read. */
2870
2871
  readonly ResolvedSpaceIDs?: components["schemas"]["UUID"][];
2872
+ /**
2873
+ * Format: uuid
2874
+ * @description RestoreTagID is the Tag marking the Revisions that undid the ChangeOrder. The first restore mints it; every restore after that marks with the same Tag. Empty until something has been restored.
2875
+ * @example 248df4b7-aa70-47b8-a036-33ac447e668d
2876
+ */
2877
+ readonly RestoreTagID?: string;
2878
+ /** @description RestoredSpaceIDs is where the ChangeOrder has been undone: the Spaces whose Units all carry the restore Tag. Derived when the ChangeOrder is read. */
2879
+ readonly RestoredSpaceIDs?: components["schemas"]["UUID"][];
2871
2880
  /** @description SkippedUnits names the Units of the ChangeOrder's Space that it carries no Revisions of, mapped to the reason. Written when the scope is derived. A skipped Unit may still be marked by the ChangeOrder's Tags, when the Spaces in scope had already taken it. */
2872
2881
  readonly SkippedUnits?: {
2873
2882
  [key: string]: string;
@@ -2888,7 +2897,7 @@ interface components {
2888
2897
  * @example 248df4b7-aa70-47b8-a036-33ac447e668d
2889
2898
  */
2890
2899
  readonly StartTagID?: string;
2891
- /** @description State is how far the ChangeOrder has got: New until a Space other than its own has taken it, InProgress while some have and some have not, Resolved once every Space in scope has, Released once every Space in scope has released what it took, and Aborted whenever AbortedReason is set. Derived when the ChangeOrder is read. */
2900
+ /** @description State is how far the ChangeOrder has got: New until a Space other than its own has taken it, InProgress while some have and some have not, Resolved once every Space in scope has, Released once every Space in scope has released what it took, Aborted whenever AbortedReason is set, Restored once every Space that had taken it has been restored to the Revisions before it, and RestoreReleased once every Space that had released it has released the restored Revisions. Derived when the ChangeOrder is read. */
2892
2901
  readonly State?: string;
2893
2902
  /** @description UpdateType is the Link UpdateType this ChangeOrder follows when propagating. UpgradeUnit, the clone lineage, is the default; MergeUnits is the other supported value. */
2894
2903
  UpdateType?: string;
@@ -3061,6 +3070,7 @@ interface components {
3061
3070
  EndTag?: components["schemas"]["Tag"];
3062
3071
  Error?: components["schemas"]["ResponseError"];
3063
3072
  Organization?: components["schemas"]["Organization"];
3073
+ RestoreTag?: components["schemas"]["Tag"];
3064
3074
  Space?: components["schemas"]["Space"];
3065
3075
  StartTag?: components["schemas"]["Tag"];
3066
3076
  };
@@ -3339,6 +3349,7 @@ interface components {
3339
3349
  Clearance?: components["schemas"]["Clearance"];
3340
3350
  /** @description Function name */
3341
3351
  FunctionName?: string;
3352
+ Guards?: components["schemas"]["GuardStamp"];
3342
3353
  /** @description Caller-supplied parameter values for expanding templated argument Values; transient, not persisted */
3343
3354
  Params?: {
3344
3355
  [key: string]: unknown;
@@ -3378,6 +3389,7 @@ interface components {
3378
3389
  FunctionInvocationsResponse: {
3379
3390
  /** @description The resulting configuration data; present only when the invocation changed it */
3380
3391
  ConfigData?: string;
3392
+ Conflicts?: components["schemas"]["MutationConflictList"];
3381
3393
  /** @description SHA256 of the resulting configuration data, whether or not ConfigData is present */
3382
3394
  DataHash?: string;
3383
3395
  Error?: components["schemas"]["ResponseError"];
@@ -3510,6 +3522,9 @@ interface components {
3510
3522
  [key: string]: string;
3511
3523
  };
3512
3524
  };
3525
+ GuardStamp: {
3526
+ [key: string]: string;
3527
+ };
3513
3528
  /** @description Defines a stored, reusable call to one or more functions, executed in the order they are listed. */
3514
3529
  Invocation: {
3515
3530
  /** @description An optional map of Annotation key/value pairs for tools to attach information to entities. */
@@ -3648,6 +3663,7 @@ interface components {
3648
3663
  * @example 248df4b7-aa70-47b8-a036-33ac447e668d
3649
3664
  */
3650
3665
  FromUnitID: string;
3666
+ Guards?: components["schemas"]["GuardStamp"];
3651
3667
  /** @description SHA256 hash of the resolution-relevant Link fields, used to detect changes that require re-resolution. */
3652
3668
  readonly Hash?: string;
3653
3669
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -4460,7 +4476,6 @@ interface components {
4460
4476
  BoundProvidedProperties?: {
4461
4477
  [key: string]: string;
4462
4478
  };
4463
- GetterInvocation?: components["schemas"]["FunctionInvocation"];
4464
4479
  /** @description Whether this attribute is a needed value */
4465
4480
  IsNeeded?: boolean;
4466
4481
  /** @description Whether this attribute is a provided value */
@@ -4479,7 +4494,6 @@ interface components {
4479
4494
  [key: string]: string;
4480
4495
  };
4481
4496
  ResourceType?: string;
4482
- SetterInvocation?: components["schemas"]["FunctionInvocation"];
4483
4497
  };
4484
4498
  ResponseError: {
4485
4499
  /** @description Additional context messages */
@@ -5161,6 +5175,7 @@ interface components {
5161
5175
  FailOpenAfter?: number | null;
5162
5176
  /** @description Function name */
5163
5177
  FunctionName?: string;
5178
+ Guards?: components["schemas"]["GuardStamp"];
5164
5179
  /** @description SHA256 hash of the trigger's specification fields, used to detect changes. */
5165
5180
  readonly Hash?: string;
5166
5181
  /**
@@ -8240,7 +8255,7 @@ interface operations {
8240
8255
  * An example conjunction is:
8241
8256
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8242
8257
  *
8243
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8258
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8244
8259
  *
8245
8260
  * The whole string must be query-encoded.
8246
8261
  */
@@ -8282,7 +8297,7 @@ interface operations {
8282
8297
  * The attribute names are case-sensitive, PascalCase, and
8283
8298
  * expected in a comma-separated list format as in the JSON encoding.
8284
8299
  *
8285
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8300
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8286
8301
  *
8287
8302
  * The whole string must be query-encoded.
8288
8303
  */
@@ -8408,7 +8423,7 @@ interface operations {
8408
8423
  * An example conjunction is:
8409
8424
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8410
8425
  *
8411
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8426
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8412
8427
  *
8413
8428
  * The whole string must be query-encoded.
8414
8429
  */
@@ -8450,7 +8465,7 @@ interface operations {
8450
8465
  * The attribute names are case-sensitive, PascalCase, and
8451
8466
  * expected in a comma-separated list format as in the JSON encoding.
8452
8467
  *
8453
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8468
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8454
8469
  *
8455
8470
  * The whole string must be query-encoded.
8456
8471
  */
@@ -8676,7 +8691,7 @@ interface operations {
8676
8691
  * An example conjunction is:
8677
8692
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8678
8693
  *
8679
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8694
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8680
8695
  *
8681
8696
  * The whole string must be query-encoded.
8682
8697
  */
@@ -8718,7 +8733,7 @@ interface operations {
8718
8733
  * The attribute names are case-sensitive, PascalCase, and
8719
8734
  * expected in a comma-separated list format as in the JSON encoding.
8720
8735
  *
8721
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8736
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8722
8737
  *
8723
8738
  * The whole string must be query-encoded.
8724
8739
  */
@@ -8860,7 +8875,7 @@ interface operations {
8860
8875
  * An example conjunction is:
8861
8876
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
8862
8877
  *
8863
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8878
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
8864
8879
  *
8865
8880
  * The whole string must be query-encoded.
8866
8881
  */
@@ -8902,7 +8917,7 @@ interface operations {
8902
8917
  * The attribute names are case-sensitive, PascalCase, and
8903
8918
  * expected in a comma-separated list format as in the JSON encoding.
8904
8919
  *
8905
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
8920
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
8906
8921
  *
8907
8922
  * The whole string must be query-encoded.
8908
8923
  */
@@ -10800,6 +10815,8 @@ interface operations {
10800
10815
  protect?: boolean;
10801
10816
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
10802
10817
  clearance?: string;
10818
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
10819
+ guards?: string;
10803
10820
  /** @description Must match ChangeSetID of affected Units unless in dry run mode; not valid when invoked on Revisions */
10804
10821
  change_set_id?: string;
10805
10822
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
@@ -12197,6 +12214,10 @@ interface operations {
12197
12214
  DownstreamSetters?: (Record<string, never> | null)[] | null;
12198
12215
  /** Format: uuid */
12199
12216
  FromUnitID?: string | null;
12217
+ /** @description Guards to record on the paths this link's resolve writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Refused on UpgradeUnit and MergeUnits links, whose guards arrive by propagation from upstream. */
12218
+ Guards?: {
12219
+ [key: string]: string | null;
12220
+ } | null;
12200
12221
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
12201
12222
  Labels?: {
12202
12223
  [key: string]: string | null;
@@ -12608,6 +12629,10 @@ interface operations {
12608
12629
  DownstreamSetters?: (Record<string, never> | null)[] | null;
12609
12630
  /** Format: uuid */
12610
12631
  FromUnitID?: string | null;
12632
+ /** @description Guards to record on the paths this link's resolve writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Refused on UpgradeUnit and MergeUnits links, whose guards arrive by propagation from upstream. */
12633
+ Guards?: {
12634
+ [key: string]: string | null;
12635
+ } | null;
12611
12636
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
12612
12637
  Labels?: {
12613
12638
  [key: string]: string | null;
@@ -17407,7 +17432,7 @@ interface operations {
17407
17432
  * An example conjunction is:
17408
17433
  * `CreatedAt >= '2025-01-07' AND Slug = 'test' AND Labels.mykey = 'myvalue'`.
17409
17434
  *
17410
- * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedSpaceIDs, ResolvedSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
17435
+ * Supported attributes for filtering on ChangeOrder: AbortedReason, AdoptedEndTagID, Annotations, ChangeOrderID, CreatedAt, DeleteGates, Description, DisplayName, EndTagID, InScopeSpaceIDs, Labels, OrganizationID, ReleasedRestoredSpaceIDs, ReleasedSpaceIDs, ResolvedSpaceIDs, RestoreTagID, RestoredSpaceIDs, SkippedUnits, Slug, SpaceID, StartTagID, State, UpdateType, UpdatedAt.
17411
17436
  *
17412
17437
  * The whole string must be query-encoded.
17413
17438
  */
@@ -17449,7 +17474,7 @@ interface operations {
17449
17474
  * The attribute names are case-sensitive, PascalCase, and
17450
17475
  * expected in a comma-separated list format as in the JSON encoding.
17451
17476
  *
17452
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
17477
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
17453
17478
  *
17454
17479
  * The whole string must be query-encoded.
17455
17480
  */
@@ -17641,7 +17666,7 @@ interface operations {
17641
17666
  * The attribute names are case-sensitive, PascalCase, and
17642
17667
  * expected in a comma-separated list format as in the JSON encoding.
17643
17668
  *
17644
- * Supported attributes for ChangeOrder are EndTagID, OrganizationID, SpaceID, StartTagID.
17669
+ * Supported attributes for ChangeOrder are EndTagID, OrganizationID, RestoreTagID, SpaceID, StartTagID.
17645
17670
  *
17646
17671
  * The whole string must be query-encoded.
17647
17672
  */
@@ -19520,6 +19545,8 @@ interface operations {
19520
19545
  protect?: boolean;
19521
19546
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
19522
19547
  clearance?: string;
19548
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
19549
+ guards?: string;
19523
19550
  /** @description Must match ChangeSetID of affected Units unless in dry run mode; not valid when invoked on Revisions */
19524
19551
  change_set_id?: string;
19525
19552
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
@@ -21001,6 +21028,10 @@ interface operations {
21001
21028
  DownstreamSetters?: (Record<string, never> | null)[] | null;
21002
21029
  /** Format: uuid */
21003
21030
  FromUnitID?: string | null;
21031
+ /** @description Guards to record on the paths this link's resolve writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Refused on UpgradeUnit and MergeUnits links, whose guards arrive by propagation from upstream. */
21032
+ Guards?: {
21033
+ [key: string]: string | null;
21034
+ } | null;
21004
21035
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
21005
21036
  Labels?: {
21006
21037
  [key: string]: string | null;
@@ -23916,6 +23947,10 @@ interface operations {
23916
23947
  FailOpenAfter?: number | null;
23917
23948
  /** @description Function name */
23918
23949
  FunctionName?: string | null;
23950
+ /** @description Guards to record on the paths this trigger's function writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Only meaningful for a mutating trigger, and part of the trigger's Hash, unlike Protect. */
23951
+ Guards?: {
23952
+ [key: string]: string | null;
23953
+ } | null;
23919
23954
  /** Format: uuid */
23920
23955
  InvocationID?: string | null;
23921
23956
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -24436,6 +24471,8 @@ interface operations {
24436
24471
  protect?: boolean;
24437
24472
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
24438
24473
  clearance?: string;
24474
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
24475
+ guards?: string;
24439
24476
  /** @description Merge the range as one rebased diff and record it as one Revision, instead of walking it. By default a merge replays: it takes the source's Revisions in order and, where a Revision records function invocations that can be re-executed, runs them against this Unit rather than rebasing their recorded paths onto it -- so a change lands where this Unit's own structure puts it -- and records each source Revision that has an effect here as a Revision of its own, carrying that Revision's change description, its own conflicts, and one Mutation per source Mutation. Squashing gives up both: the range arrives as a single rebased patch in a single Revision, which is what a merge did before replay existed. Accepted with upgrade, merge_source, and resolve of an UpgradeUnit or MergeUnits Link, and refused elsewhere, since there is no range to walk. A Link can ask for it standingly with its Squash field. */
24440
24477
  squash?: boolean;
24441
24478
  /** @description Upgrade the unit to the latest version of its upstream unit */
@@ -24514,7 +24551,7 @@ interface operations {
24514
24551
  tag?: string;
24515
24552
  /** @description Must match ChangeSetID of affected Units if config Data is changed unless in dry run mode */
24516
24553
  change_set_id?: string;
24517
- /** @description ChangeOrder to promote, with upgrade or resolve. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. */
24554
+ /** @description ChangeOrder to promote, with upgrade or resolve, or to undo, with restore. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. With restore the change order is being undone rather than promoted: the restore must be 'Before:ChangeOrder:' the same change order, the change order must have an AbortedReason -- undoing a change nobody has said is not coming is a race with whoever is still promoting it -- and a Unit the change order never marked is an error rather than passed over, since naming it says the Unit is part of the undoing. The first restore mints the change order's restore Tag and records it as RestoreTagID; every restore after that marks with the same Tag, which is what RestoredSpaceIDs is read off. A Unit the change order carried nothing for takes the restore Tag on the revision its start and end Tags are already on, and no revision is made. A Unit already carrying the restore Tag has had the change order taken back out of it and is passed over, since undoing one in a Unit happens once as promoting it into one does -- so the revisions a Unit has taken since it was undone are its own work rather than this undoing's to drop. Restoring also advances the merge pointers of the Links of the change order's UpdateType that follow the restored Unit onto the revision the restore made, so a later upgrade does not replay the change that was just taken out; the downstream Units are not restored with it, since each has to be restored and released on its own account. */
24518
24555
  change_order?: string;
24519
24556
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
24520
24557
  subgroup?: string;
@@ -24736,6 +24773,8 @@ interface operations {
24736
24773
  protect?: boolean;
24737
24774
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
24738
24775
  clearance?: string;
24776
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
24777
+ guards?: string;
24739
24778
  /** @description Merge the range as one rebased diff and record it as one Revision, instead of walking it. By default a merge replays: it takes the source's Revisions in order and, where a Revision records function invocations that can be re-executed, runs them against this Unit rather than rebasing their recorded paths onto it -- so a change lands where this Unit's own structure puts it -- and records each source Revision that has an effect here as a Revision of its own, carrying that Revision's change description, its own conflicts, and one Mutation per source Mutation. Squashing gives up both: the range arrives as a single rebased patch in a single Revision, which is what a merge did before replay existed. Accepted with upgrade, merge_source, and resolve of an UpgradeUnit or MergeUnits Link, and refused elsewhere, since there is no range to walk. A Link can ask for it standingly with its Squash field. */
24740
24779
  squash?: boolean;
24741
24780
  /** @description Upgrade the unit to the latest version of its upstream unit */
@@ -24814,7 +24853,7 @@ interface operations {
24814
24853
  tag?: string;
24815
24854
  /** @description Must match ChangeSetID of affected Units if config Data is changed unless in dry run mode */
24816
24855
  change_set_id?: string;
24817
- /** @description ChangeOrder to promote, with upgrade or resolve. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. */
24856
+ /** @description ChangeOrder to promote, with upgrade or resolve, or to undo, with restore. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. With restore the change order is being undone rather than promoted: the restore must be 'Before:ChangeOrder:' the same change order, the change order must have an AbortedReason -- undoing a change nobody has said is not coming is a race with whoever is still promoting it -- and a Unit the change order never marked is an error rather than passed over, since naming it says the Unit is part of the undoing. The first restore mints the change order's restore Tag and records it as RestoreTagID; every restore after that marks with the same Tag, which is what RestoredSpaceIDs is read off. A Unit the change order carried nothing for takes the restore Tag on the revision its start and end Tags are already on, and no revision is made. A Unit already carrying the restore Tag has had the change order taken back out of it and is passed over, since undoing one in a Unit happens once as promoting it into one does -- so the revisions a Unit has taken since it was undone are its own work rather than this undoing's to drop. Restoring also advances the merge pointers of the Links of the change order's UpdateType that follow the restored Unit onto the revision the restore made, so a later upgrade does not replay the change that was just taken out; the downstream Units are not restored with it, since each has to be restored and released on its own account. */
24818
24857
  change_order?: string;
24819
24858
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
24820
24859
  subgroup?: string;
@@ -25236,6 +25275,8 @@ interface operations {
25236
25275
  protect?: boolean;
25237
25276
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
25238
25277
  clearance?: string;
25278
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
25279
+ guards?: string;
25239
25280
  /** @description Merge base revision, which provides the base configuration data of the changes to merge. With merge_source, this is a revision of the merge source unit. With merge_external_source, this is a revision of the unit being updated and overrides the default selection of the latest MergeExternal revision. Supports: Named revisions ('HeadRevisionNum', 'LastReleasedRevisionNum'), direct revision number (e.g., '42'), or entity references ('Tag:uuid', 'ChangeSet:uuid', 'ChangeOrder:uuid', 'Revision:uuid'). Can be prefixed with 'Before:' to select the revision immediately before the specified one (e.g., 'Before:LastReleasedRevisionNum', 'Before:42'). When using Tag or ChangeSet references, the latest revision associated with that entity is selected. 'ChangeOrder:uuid' selects the revision the change order ended at on this Unit and 'Before:ChangeOrder:uuid' the one before it began, which is what undoes a promotion however many revisions it made. */
25240
25281
  merge_base?: string;
25241
25282
  /** @description Identifier of the external source for merge-on-update. When set, computes mutations between the last MergeExternal revision and the provided data, then patches the current unit data with those mutations. */
@@ -29663,6 +29704,10 @@ interface operations {
29663
29704
  FailOpenAfter?: number | null;
29664
29705
  /** @description Function name */
29665
29706
  FunctionName?: string | null;
29707
+ /** @description Guards to record on the paths this trigger's function writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Only meaningful for a mutating trigger, and part of the trigger's Hash, unlike Protect. */
29708
+ Guards?: {
29709
+ [key: string]: string | null;
29710
+ } | null;
29666
29711
  /** Format: uuid */
29667
29712
  InvocationID?: string | null;
29668
29713
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -30069,6 +30114,10 @@ interface operations {
30069
30114
  FailOpenAfter?: number | null;
30070
30115
  /** @description Function name */
30071
30116
  FunctionName?: string | null;
30117
+ /** @description Guards to record on the paths this trigger's function writes, naming the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. Sibling to Protect: Protect claims the paths, Guards say why. Add and overwrite only -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). Only meaningful for a mutating trigger, and part of the trigger's Hash, unlike Protect. */
30118
+ Guards?: {
30119
+ [key: string]: string | null;
30120
+ } | null;
30072
30121
  /** Format: uuid */
30073
30122
  InvocationID?: string | null;
30074
30123
  /** @description An optional map of Label key/value pairs to specify identifying attributes of entities for the purpose of grouping and filtering them. */
@@ -30989,6 +31038,8 @@ interface operations {
30989
31038
  protect?: boolean;
30990
31039
  /** @description The classes of guarded reason this operation is cleared for, as a JSON Clearance -- a list of {Key, Operator, Values} requirements, where Operator is Exists, In, NotIn, or DoesNotExist. A path whose guards this does not cover is not written, and the withheld change is reported as a Guarded conflict. An absent or empty clearance clears nothing, which only matters for a Unit that has guards. */
30991
31040
  clearance?: string;
31041
+ /** @description The guards this operation records on the paths it writes, as a JSON object of guard key to value -- the reasons those paths hold what they hold, so a later operation must be cleared for them before overwriting. The guard analogue of protect: protect claims the paths, this says why. It only ever adds and overwrites the keys it names -- retiring a guard is the /guard API (cub unit set-guard --remove-guard). */
31042
+ guards?: string;
30992
31043
  /** @description Merge the range as one rebased diff and record it as one Revision, instead of walking it. By default a merge replays: it takes the source's Revisions in order and, where a Revision records function invocations that can be re-executed, runs them against this Unit rather than rebasing their recorded paths onto it -- so a change lands where this Unit's own structure puts it -- and records each source Revision that has an effect here as a Revision of its own, carrying that Revision's change description, its own conflicts, and one Mutation per source Mutation. Squashing gives up both: the range arrives as a single rebased patch in a single Revision, which is what a merge did before replay existed. Accepted with upgrade, merge_source, and resolve of an UpgradeUnit or MergeUnits Link, and refused elsewhere, since there is no range to walk. A Link can ask for it standingly with its Squash field. */
30993
31044
  squash?: boolean;
30994
31045
  /** @description Upgrade the unit to the latest version of its upstream unit */
@@ -31067,7 +31118,7 @@ interface operations {
31067
31118
  tag?: string;
31068
31119
  /** @description Must match ChangeSetID of affected Units if config Data is changed unless in dry run mode */
31069
31120
  change_set_id?: string;
31070
- /** @description ChangeOrder to promote, with upgrade or resolve. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. */
31121
+ /** @description ChangeOrder to promote, with upgrade or resolve, or to undo, with restore. The change order fixed the range when it was created -- the interval on each source Unit, marked with its Tags -- so it supplies both ends of the merge and merge_end is refused alongside it. A Unit whose source the change order does not cover is passed over rather than failed, which is what lets a bulk upgrade name a whole Space and take only the Units the change is in. A Unit whose last merged revision is not where the change order starts is an error, since merging anyway would replay what it already has or skip what it does not, and with resolve a selected Link whose UpdateType the change order does not follow is an error too. The revisions the promotion creates carry the ChangeOrder, and its start Tag is placed on the revision before them and its end Tag on the one it arrives at, so 'restore Before:ChangeOrder:uuid' undoes it whether it landed as one revision or as one per source revision. With restore the change order is being undone rather than promoted: the restore must be 'Before:ChangeOrder:' the same change order, the change order must have an AbortedReason -- undoing a change nobody has said is not coming is a race with whoever is still promoting it -- and a Unit the change order never marked is an error rather than passed over, since naming it says the Unit is part of the undoing. The first restore mints the change order's restore Tag and records it as RestoreTagID; every restore after that marks with the same Tag, which is what RestoredSpaceIDs is read off. A Unit the change order carried nothing for takes the restore Tag on the revision its start and end Tags are already on, and no revision is made. A Unit already carrying the restore Tag has had the change order taken back out of it and is passed over, since undoing one in a Unit happens once as promoting it into one does -- so the revisions a Unit has taken since it was undone are its own work rather than this undoing's to drop. Restoring also advances the merge pointers of the Links of the change order's UpdateType that follow the restored Unit onto the revision the restore made, so a later upgrade does not replay the change that was just taken out; the downstream Units are not restored with it, since each has to be restored and released on its own account. */
31071
31122
  change_order?: string;
31072
31123
  /** @description User-defined category for the Mutation. Must be alphanumeric, at most 64 characters. The prefix 'ConfigHub' is reserved. */
31073
31124
  subgroup?: string;
@@ -34149,4 +34200,20 @@ declare function getRevisionMutationSources(client: ConfigHubClient, ref: Revisi
34149
34200
  };
34150
34201
  }, `${string}/${string}`>>;
34151
34202
 
34152
- export { type ConfigHubClient, type ConfigHubClientOptions, type MutationSourcesResponse, type ReadDataOptions, type ReadDataResult, type ReleaseRef, type RevisionRef, type UnitCreateOrUpdateResponse, type UnitRef, type WriteDataOptions, type WriteDataResult, type components, createConfigHubClient, getReleaseData, getRevisionData, getRevisionMutationSources, getUnitData, getUnitMutationSources, type operations, type paths, putUnitData };
34203
+ declare const SLUG_PATTERN: RegExp;
34204
+ declare const SLUG_MAX_LENGTH = 128;
34205
+ declare const SLUG_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), and periods (.)";
34206
+ declare const LABEL_KEY_PATTERN: RegExp;
34207
+ declare const LABEL_KEY_MAX_LENGTH = 128;
34208
+ declare const LABEL_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
34209
+ declare const LABEL_VALUE_PATTERN: RegExp;
34210
+ declare const LABEL_VALUE_MAX_LENGTH = 128;
34211
+ declare const LABEL_VALUE_PATTERN_MESSAGE = "Must start and end with a printable character (no leading/trailing spaces). Quotes, backslashes, and wildcards are not allowed";
34212
+ declare const ANNOTATION_KEY_PATTERN: RegExp;
34213
+ declare const ANNOTATION_KEY_MAX_LENGTH = 128;
34214
+ declare const ANNOTATION_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
34215
+ declare const ANNOTATION_VALUE_PATTERN: RegExp;
34216
+ declare const ANNOTATION_VALUE_MAX_LENGTH = 1024;
34217
+ declare const ANNOTATION_VALUE_PATTERN_MESSAGE = "Any content is allowed, including multiline text";
34218
+
34219
+ export { ANNOTATION_KEY_MAX_LENGTH, ANNOTATION_KEY_PATTERN, ANNOTATION_KEY_PATTERN_MESSAGE, ANNOTATION_VALUE_MAX_LENGTH, ANNOTATION_VALUE_PATTERN, ANNOTATION_VALUE_PATTERN_MESSAGE, type ConfigHubClient, type ConfigHubClientOptions, LABEL_KEY_MAX_LENGTH, LABEL_KEY_PATTERN, LABEL_KEY_PATTERN_MESSAGE, LABEL_VALUE_MAX_LENGTH, LABEL_VALUE_PATTERN, LABEL_VALUE_PATTERN_MESSAGE, type MutationSourcesResponse, type ReadDataOptions, type ReadDataResult, type ReleaseRef, type RevisionRef, SLUG_MAX_LENGTH, SLUG_PATTERN, SLUG_PATTERN_MESSAGE, type UnitCreateOrUpdateResponse, type UnitRef, type WriteDataOptions, type WriteDataResult, type components, createConfigHubClient, getReleaseData, getRevisionData, getRevisionMutationSources, getUnitData, getUnitMutationSources, type operations, type paths, putUnitData };
package/dist/index.js CHANGED
@@ -123,6 +123,23 @@ function getRevisionMutationSources(client, ref) {
123
123
  });
124
124
  }
125
125
 
126
- export { createConfigHubClient, getReleaseData, getRevisionData, getRevisionMutationSources, getUnitData, getUnitMutationSources, putUnitData };
126
+ // src/validation.ts
127
+ var SLUG_PATTERN = /^[A-Za-z0-9]([\-_.A-Za-z0-9]*[A-Za-z0-9])?$/;
128
+ var SLUG_MAX_LENGTH = 128;
129
+ var SLUG_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), and periods (.)";
130
+ var LABEL_KEY_PATTERN = /^[A-Za-z0-9]([\-_\./A-Za-z0-9]*[A-Za-z0-9])?$/;
131
+ var LABEL_KEY_MAX_LENGTH = 128;
132
+ var LABEL_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
133
+ var LABEL_VALUE_PATTERN = /^[\-_@/#$%&~+=!?.,:;(){}\[\]<>|A-Za-z0-9](([\-_@/#$%&~+=!?.,:;(){}\[\]<>|A-Za-z0-9]| )*[\-_@/#$%&~+=!?.,:;(){}\[\]<>|A-Za-z0-9])?$/;
134
+ var LABEL_VALUE_MAX_LENGTH = 128;
135
+ var LABEL_VALUE_PATTERN_MESSAGE = "Must start and end with a printable character (no leading/trailing spaces). Quotes, backslashes, and wildcards are not allowed";
136
+ var ANNOTATION_KEY_PATTERN = /^[A-Za-z0-9]([\-_\./A-Za-z0-9]*[A-Za-z0-9])?$/;
137
+ var ANNOTATION_KEY_MAX_LENGTH = 128;
138
+ var ANNOTATION_KEY_PATTERN_MESSAGE = "Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)";
139
+ var ANNOTATION_VALUE_PATTERN = /^(.|\n)*$/;
140
+ var ANNOTATION_VALUE_MAX_LENGTH = 1024;
141
+ var ANNOTATION_VALUE_PATTERN_MESSAGE = "Any content is allowed, including multiline text";
142
+
143
+ export { ANNOTATION_KEY_MAX_LENGTH, ANNOTATION_KEY_PATTERN, ANNOTATION_KEY_PATTERN_MESSAGE, ANNOTATION_VALUE_MAX_LENGTH, ANNOTATION_VALUE_PATTERN, ANNOTATION_VALUE_PATTERN_MESSAGE, LABEL_KEY_MAX_LENGTH, LABEL_KEY_PATTERN, LABEL_KEY_PATTERN_MESSAGE, LABEL_VALUE_MAX_LENGTH, LABEL_VALUE_PATTERN, LABEL_VALUE_PATTERN_MESSAGE, SLUG_MAX_LENGTH, SLUG_PATTERN, SLUG_PATTERN_MESSAGE, createConfigHubClient, getReleaseData, getRevisionData, getRevisionMutationSources, getUnitData, getUnitMutationSources, putUnitData };
127
144
  //# sourceMappingURL=index.js.map
128
145
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../src/data.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport createClient, { type Client, type Middleware } from 'openapi-fetch';\nimport type { paths } from './schema';\n\nexport interface ConfigHubClientOptions {\n /**\n * Base URL of the ConfigHub instance, e.g. `https://hub.confighub.com` — the same\n * value passed to the auth provider. The ConfigHub API is mounted under `/api`\n * (the spec's paths are relative to it), so the client targets `{baseUrl}/api`.\n * Passing a URL that already ends in `/api` is accepted as-is.\n */\n baseUrl: string;\n\n /**\n * Returns the current bearer token, or undefined when unauthenticated. May be\n * async so the caller can await a refresh. Wired as an openapi-fetch middleware\n * that sets `Authorization: Bearer <token>` per request. The client never stores\n * or refreshes tokens itself — that is the auth layer's job (see\n * `@confighub/react-auth`).\n */\n getToken?: () => string | undefined | Promise<string | undefined>;\n\n /**\n * Called when a request returns 401. A library must not redirect on its own, so\n * this hands control back to the caller — typically to trigger a token refresh\n * or re-login. The originating request is not retried automatically.\n */\n onUnauthorized?: () => void | Promise<void>;\n\n /** Override the fetch implementation (tests, non-browser runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\nexport type ConfigHubClient = Client<paths>;\n\nconst trimTrailingSlash = (s: string): string => s.replace(/\\/+$/, '');\n\n// The ConfigHub API lives under /api and the OpenAPI paths are relative to it. Accept\n// either the instance origin or a URL that already includes /api.\nconst apiBaseUrl = (baseUrl: string): string => {\n const trimmed = trimTrailingSlash(baseUrl);\n return trimmed.endsWith('/api') ? trimmed : trimmed + '/api';\n};\n\n/**\n * Create a typed ConfigHub API client. Every path, param, and response is derived\n * from the pinned OpenAPI spec (`src/schema.d.ts`), so it stays in lockstep with\n * the server.\n *\n * ```ts\n * const api = createConfigHubClient({ baseUrl, getToken: () => session.accessToken });\n * const { data, error } = await api.GET('/me');\n * const units = await api.GET('/space/{space_id}/unit', { params: { path: { space_id } } });\n * ```\n */\nexport function createConfigHubClient(options: ConfigHubClientOptions): ConfigHubClient {\n const { baseUrl, getToken, onUnauthorized, fetch: fetchImpl } = options;\n\n const client = createClient<paths>({\n baseUrl: apiBaseUrl(baseUrl),\n fetch: fetchImpl,\n });\n\n const middleware: Middleware = {\n async onRequest({ request }) {\n if (getToken) {\n const token = await getToken();\n if (token) request.headers.set('Authorization', `Bearer ${token}`);\n }\n // ConfigHub's PATCH endpoints expect RFC 7386 merge-patch semantics. This\n // mirrors the first-party UI, which sets the same content type for its\n // patch/bulk-patch operations.\n if (request.method === 'PATCH' && request.body != null) {\n request.headers.set('Content-Type', 'application/merge-patch+json');\n }\n return request;\n },\n async onResponse({ response }) {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized();\n }\n return response;\n },\n };\n\n client.use(middleware);\n return client;\n}\n","// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport type { ConfigHubClient } from './client';\nimport type { components } from './schema';\n\n/**\n * Configuration data is not a field of a Unit, a Revision, or a Release. It is read from\n * and written to its own endpoints, which serve the document itself as\n * `application/octet-stream` rather than a JSON envelope around it.\n *\n * These helpers exist because the two defaults of the underlying fetch client are both\n * wrong for that shape, and neither failure is visible to the type checker:\n *\n * - a read is parsed with `response.json()`, which throws on YAML, and\n * - a write is serialized with `JSON.stringify`, which would upload a quoted string.\n *\n * Everything else in the API is ordinary JSON and needs no wrapper — call the client\n * directly. In particular the bulk reads (`/unit_data`, `/revision_data`,\n * `/unit_mutation_sources`, `/revision_mutation_sources`) return JSON arrays, and a list\n * view should use those rather than one request per Unit.\n */\n\nexport type UnitCreateOrUpdateResponse = components['schemas']['UnitCreateOrUpdateResponse'];\nexport type MutationSourcesResponse = components['schemas']['MutationSourcesResponse'];\n\n/** Identifies a Unit. Both ids are required: the data endpoints are Space-scoped. */\nexport interface UnitRef {\n spaceId: string;\n unitId: string;\n}\n\n/** Identifies one Revision of a Unit. */\nexport interface RevisionRef extends UnitRef {\n revisionId: string;\n}\n\n/** Identifies a Release. */\nexport interface ReleaseRef {\n spaceId: string;\n releaseId: string;\n}\n\nexport interface ReadDataOptions {\n /**\n * A `DataHash` a previous read served, sent as `If-None-Match`. The server answers 304\n * when the configuration has not changed, which surfaces as `notModified: true` and no\n * `data` — keep what you already had.\n */\n ifNoneMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface ReadDataResult {\n /** The configuration, as text. Undefined on a 304 or an error. */\n data?: string;\n /** The `DataHash`, taken from the ETag. Pass it back as `ifNoneMatch` or `ifMatch`. */\n dataHash?: string;\n /** True when the server answered 304 because `ifNoneMatch` still matched. */\n notModified: boolean;\n /** The parsed error body, when the request failed. */\n error?: unknown;\n response: Response;\n}\n\n/**\n * Everything describing *how* a configuration should land belongs on the write that\n * carries it, not on a metadata update that precedes it. A metadata call changes no\n * configuration, so each of these has nothing to act on there and is silently dropped —\n * `mergeExternalSource` degrades to a plain overwrite that ignores protected paths, and\n * `dryRun` leaves the metadata call a dry run while this one really writes.\n */\nexport interface WriteDataOptions {\n /** Description recorded on the Revision this write creates. */\n lastChangeDescription?: string;\n /**\n * Extra parts of the result to return: `'ConfigData'`, `'MutationSources'`, or both,\n * comma-separated. For a `dryRun` nothing is stored, so this is the only way to see what\n * the operation produced. A name that is neither of these nor an expandable field is a 400.\n */\n include?: string;\n /** Compute the result and report it without storing anything. */\n dryRun?: boolean;\n /** Record the paths this write sets as protected local overrides. */\n protect?: boolean;\n /** The classes of guarded reason this write is cleared for, as a JSON Clearance. */\n clearance?: string;\n /** Revision providing the base configuration for a merge. */\n mergeBase?: string;\n /** Merge the body against the Unit as an external source rather than replacing it. */\n mergeExternalSource?: string;\n /** Also subtract the target's local differences from the source patch. */\n mergeEnableSubtraction?: boolean;\n /** Tag id to attach to the head Revision. */\n tag?: string;\n /** ChangeSet the write belongs to. */\n changeSetId?: string;\n /** User-defined category for the Mutation. */\n subgroup?: string;\n /**\n * A `DataHash` a read served, sent as `If-Match`, so the write fails rather than\n * clobbering a configuration somebody else changed in the meantime.\n */\n ifMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface WriteDataResult {\n /**\n * The operation's result. The Unit is in its `Unit` field — a write answers with what\n * it did, not with the entity.\n */\n data?: UnitCreateOrUpdateResponse;\n error?: unknown;\n response: Response;\n}\n\n// An ETag is the quoted DataHash, optionally weak. Give callers back the hash itself, so\n// it can go straight into If-Match / If-None-Match or be compared with Unit.DataHash.\nconst etagToHash = (response: Response): string | undefined => {\n const etag = response.headers.get('ETag');\n if (!etag) return undefined;\n return etag.replace(/^W\\//, '').replace(/^\"|\"$/g, '');\n};\n\nconst readData = async (\n call: Promise<{ data?: unknown; error?: unknown; response: Response }>,\n): Promise<ReadDataResult> => {\n const { data, error, response } = await call;\n if (response.status === 304) {\n return { notModified: true, dataHash: etagToHash(response), response };\n }\n if (!response.ok) {\n return { notModified: false, error, response };\n }\n // parseAs: 'text' below makes this a string; an empty body is an empty configuration,\n // which is a configuration, so it is not normalized away.\n return { data: (data as string | undefined) ?? '', dataHash: etagToHash(response), notModified: false, response };\n};\n\n/** A Unit's configuration, as text. */\nexport function getUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/data', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** One Revision's configuration, as text. */\nexport function getRevisionData(\n client: ConfigHubClient,\n ref: RevisionRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** A Release's bundle. Its ETag is the Release digest rather than a DataHash. */\nexport function getReleaseData(\n client: ConfigHubClient,\n ref: ReleaseRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/release/{release_id}/data', {\n params: { path: { space_id: ref.spaceId, release_id: ref.releaseId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/**\n * Replace a Unit's configuration. This is the only way configuration reaches a Unit other\n * than a clone, which copies it server-side: a metadata write has nowhere to put one, and\n * therefore nowhere to lose one.\n *\n * `data` is the document. An empty string is a real configuration — emptying a Unit is how\n * its resources are withdrawn — so never guard this call on the string being non-empty.\n * Track whether a configuration was *supplied* separately from what it contains.\n */\nexport function putUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n data: string,\n options: WriteDataOptions = {},\n): Promise<WriteDataResult> {\n const headers: Record<string, string> = { 'Content-Type': 'application/octet-stream' };\n if (options.ifMatch) headers['If-Match'] = `\"${options.ifMatch}\"`;\n\n return client.PUT('/space/{space_id}/unit/{unit_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId },\n query: {\n last_change_description: options.lastChangeDescription,\n include: options.include,\n dry_run: options.dryRun,\n protect: options.protect,\n clearance: options.clearance,\n merge_base: options.mergeBase,\n merge_external_source: options.mergeExternalSource,\n merge_enable_subtraction: options.mergeEnableSubtraction,\n tag: options.tag,\n change_set_id: options.changeSetId,\n subgroup: options.subgroup,\n },\n },\n headers,\n signal: options.signal,\n body: data,\n // The body is the configuration. The default serializer would JSON.stringify it and\n // upload a quoted string.\n bodySerializer: (body: string | undefined) => body ?? '',\n });\n}\n\n/** What set each value in a Unit's configuration. Ordinary JSON. */\nexport function getUnitMutationSources(client: ConfigHubClient, ref: UnitRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/mutation_sources', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n });\n}\n\n/** The Revision counterpart of {@link getUnitMutationSources}. */\nexport function getRevisionMutationSources(client: ConfigHubClient, ref: RevisionRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/mutation_sources', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/client.ts","../src/data.ts","../src/validation.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport createClient, { type Client, type Middleware } from 'openapi-fetch';\nimport type { paths } from './schema';\n\nexport interface ConfigHubClientOptions {\n /**\n * Base URL of the ConfigHub instance, e.g. `https://hub.confighub.com` — the same\n * value passed to the auth provider. The ConfigHub API is mounted under `/api`\n * (the spec's paths are relative to it), so the client targets `{baseUrl}/api`.\n * Passing a URL that already ends in `/api` is accepted as-is.\n */\n baseUrl: string;\n\n /**\n * Returns the current bearer token, or undefined when unauthenticated. May be\n * async so the caller can await a refresh. Wired as an openapi-fetch middleware\n * that sets `Authorization: Bearer <token>` per request. The client never stores\n * or refreshes tokens itself — that is the auth layer's job (see\n * `@confighub/react-auth`).\n */\n getToken?: () => string | undefined | Promise<string | undefined>;\n\n /**\n * Called when a request returns 401. A library must not redirect on its own, so\n * this hands control back to the caller — typically to trigger a token refresh\n * or re-login. The originating request is not retried automatically.\n */\n onUnauthorized?: () => void | Promise<void>;\n\n /** Override the fetch implementation (tests, non-browser runtimes). */\n fetch?: typeof globalThis.fetch;\n}\n\nexport type ConfigHubClient = Client<paths>;\n\nconst trimTrailingSlash = (s: string): string => s.replace(/\\/+$/, '');\n\n// The ConfigHub API lives under /api and the OpenAPI paths are relative to it. Accept\n// either the instance origin or a URL that already includes /api.\nconst apiBaseUrl = (baseUrl: string): string => {\n const trimmed = trimTrailingSlash(baseUrl);\n return trimmed.endsWith('/api') ? trimmed : trimmed + '/api';\n};\n\n/**\n * Create a typed ConfigHub API client. Every path, param, and response is derived\n * from the pinned OpenAPI spec (`src/schema.d.ts`), so it stays in lockstep with\n * the server.\n *\n * ```ts\n * const api = createConfigHubClient({ baseUrl, getToken: () => session.accessToken });\n * const { data, error } = await api.GET('/me');\n * const units = await api.GET('/space/{space_id}/unit', { params: { path: { space_id } } });\n * ```\n */\nexport function createConfigHubClient(options: ConfigHubClientOptions): ConfigHubClient {\n const { baseUrl, getToken, onUnauthorized, fetch: fetchImpl } = options;\n\n const client = createClient<paths>({\n baseUrl: apiBaseUrl(baseUrl),\n fetch: fetchImpl,\n });\n\n const middleware: Middleware = {\n async onRequest({ request }) {\n if (getToken) {\n const token = await getToken();\n if (token) request.headers.set('Authorization', `Bearer ${token}`);\n }\n // ConfigHub's PATCH endpoints expect RFC 7386 merge-patch semantics. This\n // mirrors the first-party UI, which sets the same content type for its\n // patch/bulk-patch operations.\n if (request.method === 'PATCH' && request.body != null) {\n request.headers.set('Content-Type', 'application/merge-patch+json');\n }\n return request;\n },\n async onResponse({ response }) {\n if (response.status === 401 && onUnauthorized) {\n await onUnauthorized();\n }\n return response;\n },\n };\n\n client.use(middleware);\n return client;\n}\n","// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n\nimport type { ConfigHubClient } from './client';\nimport type { components } from './schema';\n\n/**\n * Configuration data is not a field of a Unit, a Revision, or a Release. It is read from\n * and written to its own endpoints, which serve the document itself as\n * `application/octet-stream` rather than a JSON envelope around it.\n *\n * These helpers exist because the two defaults of the underlying fetch client are both\n * wrong for that shape, and neither failure is visible to the type checker:\n *\n * - a read is parsed with `response.json()`, which throws on YAML, and\n * - a write is serialized with `JSON.stringify`, which would upload a quoted string.\n *\n * Everything else in the API is ordinary JSON and needs no wrapper — call the client\n * directly. In particular the bulk reads (`/unit_data`, `/revision_data`,\n * `/unit_mutation_sources`, `/revision_mutation_sources`) return JSON arrays, and a list\n * view should use those rather than one request per Unit.\n */\n\nexport type UnitCreateOrUpdateResponse = components['schemas']['UnitCreateOrUpdateResponse'];\nexport type MutationSourcesResponse = components['schemas']['MutationSourcesResponse'];\n\n/** Identifies a Unit. Both ids are required: the data endpoints are Space-scoped. */\nexport interface UnitRef {\n spaceId: string;\n unitId: string;\n}\n\n/** Identifies one Revision of a Unit. */\nexport interface RevisionRef extends UnitRef {\n revisionId: string;\n}\n\n/** Identifies a Release. */\nexport interface ReleaseRef {\n spaceId: string;\n releaseId: string;\n}\n\nexport interface ReadDataOptions {\n /**\n * A `DataHash` a previous read served, sent as `If-None-Match`. The server answers 304\n * when the configuration has not changed, which surfaces as `notModified: true` and no\n * `data` — keep what you already had.\n */\n ifNoneMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface ReadDataResult {\n /** The configuration, as text. Undefined on a 304 or an error. */\n data?: string;\n /** The `DataHash`, taken from the ETag. Pass it back as `ifNoneMatch` or `ifMatch`. */\n dataHash?: string;\n /** True when the server answered 304 because `ifNoneMatch` still matched. */\n notModified: boolean;\n /** The parsed error body, when the request failed. */\n error?: unknown;\n response: Response;\n}\n\n/**\n * Everything describing *how* a configuration should land belongs on the write that\n * carries it, not on a metadata update that precedes it. A metadata call changes no\n * configuration, so each of these has nothing to act on there and is silently dropped —\n * `mergeExternalSource` degrades to a plain overwrite that ignores protected paths, and\n * `dryRun` leaves the metadata call a dry run while this one really writes.\n */\nexport interface WriteDataOptions {\n /** Description recorded on the Revision this write creates. */\n lastChangeDescription?: string;\n /**\n * Extra parts of the result to return: `'ConfigData'`, `'MutationSources'`, or both,\n * comma-separated. For a `dryRun` nothing is stored, so this is the only way to see what\n * the operation produced. A name that is neither of these nor an expandable field is a 400.\n */\n include?: string;\n /** Compute the result and report it without storing anything. */\n dryRun?: boolean;\n /** Record the paths this write sets as protected local overrides. */\n protect?: boolean;\n /** The classes of guarded reason this write is cleared for, as a JSON Clearance. */\n clearance?: string;\n /** Revision providing the base configuration for a merge. */\n mergeBase?: string;\n /** Merge the body against the Unit as an external source rather than replacing it. */\n mergeExternalSource?: string;\n /** Also subtract the target's local differences from the source patch. */\n mergeEnableSubtraction?: boolean;\n /** Tag id to attach to the head Revision. */\n tag?: string;\n /** ChangeSet the write belongs to. */\n changeSetId?: string;\n /** User-defined category for the Mutation. */\n subgroup?: string;\n /**\n * A `DataHash` a read served, sent as `If-Match`, so the write fails rather than\n * clobbering a configuration somebody else changed in the meantime.\n */\n ifMatch?: string;\n signal?: AbortSignal;\n}\n\nexport interface WriteDataResult {\n /**\n * The operation's result. The Unit is in its `Unit` field — a write answers with what\n * it did, not with the entity.\n */\n data?: UnitCreateOrUpdateResponse;\n error?: unknown;\n response: Response;\n}\n\n// An ETag is the quoted DataHash, optionally weak. Give callers back the hash itself, so\n// it can go straight into If-Match / If-None-Match or be compared with Unit.DataHash.\nconst etagToHash = (response: Response): string | undefined => {\n const etag = response.headers.get('ETag');\n if (!etag) return undefined;\n return etag.replace(/^W\\//, '').replace(/^\"|\"$/g, '');\n};\n\nconst readData = async (\n call: Promise<{ data?: unknown; error?: unknown; response: Response }>,\n): Promise<ReadDataResult> => {\n const { data, error, response } = await call;\n if (response.status === 304) {\n return { notModified: true, dataHash: etagToHash(response), response };\n }\n if (!response.ok) {\n return { notModified: false, error, response };\n }\n // parseAs: 'text' below makes this a string; an empty body is an empty configuration,\n // which is a configuration, so it is not normalized away.\n return { data: (data as string | undefined) ?? '', dataHash: etagToHash(response), notModified: false, response };\n};\n\n/** A Unit's configuration, as text. */\nexport function getUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/data', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** One Revision's configuration, as text. */\nexport function getRevisionData(\n client: ConfigHubClient,\n ref: RevisionRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/** A Release's bundle. Its ETag is the Release digest rather than a DataHash. */\nexport function getReleaseData(\n client: ConfigHubClient,\n ref: ReleaseRef,\n options: ReadDataOptions = {},\n): Promise<ReadDataResult> {\n return readData(\n client.GET('/space/{space_id}/release/{release_id}/data', {\n params: { path: { space_id: ref.spaceId, release_id: ref.releaseId } },\n headers: options.ifNoneMatch ? { 'If-None-Match': `\"${options.ifNoneMatch}\"` } : undefined,\n signal: options.signal,\n parseAs: 'text',\n }),\n );\n}\n\n/**\n * Replace a Unit's configuration. This is the only way configuration reaches a Unit other\n * than a clone, which copies it server-side: a metadata write has nowhere to put one, and\n * therefore nowhere to lose one.\n *\n * `data` is the document. An empty string is a real configuration — emptying a Unit is how\n * its resources are withdrawn — so never guard this call on the string being non-empty.\n * Track whether a configuration was *supplied* separately from what it contains.\n */\nexport function putUnitData(\n client: ConfigHubClient,\n ref: UnitRef,\n data: string,\n options: WriteDataOptions = {},\n): Promise<WriteDataResult> {\n const headers: Record<string, string> = { 'Content-Type': 'application/octet-stream' };\n if (options.ifMatch) headers['If-Match'] = `\"${options.ifMatch}\"`;\n\n return client.PUT('/space/{space_id}/unit/{unit_id}/data', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId },\n query: {\n last_change_description: options.lastChangeDescription,\n include: options.include,\n dry_run: options.dryRun,\n protect: options.protect,\n clearance: options.clearance,\n merge_base: options.mergeBase,\n merge_external_source: options.mergeExternalSource,\n merge_enable_subtraction: options.mergeEnableSubtraction,\n tag: options.tag,\n change_set_id: options.changeSetId,\n subgroup: options.subgroup,\n },\n },\n headers,\n signal: options.signal,\n body: data,\n // The body is the configuration. The default serializer would JSON.stringify it and\n // upload a quoted string.\n bodySerializer: (body: string | undefined) => body ?? '',\n });\n}\n\n/** What set each value in a Unit's configuration. Ordinary JSON. */\nexport function getUnitMutationSources(client: ConfigHubClient, ref: UnitRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/mutation_sources', {\n params: { path: { space_id: ref.spaceId, unit_id: ref.unitId } },\n });\n}\n\n/** The Revision counterpart of {@link getUnitMutationSources}. */\nexport function getRevisionMutationSources(client: ConfigHubClient, ref: RevisionRef) {\n return client.GET('/space/{space_id}/unit/{unit_id}/revision/{revision_id}/mutation_sources', {\n params: {\n path: { space_id: ref.spaceId, unit_id: ref.unitId, revision_id: ref.revisionId },\n },\n });\n}\n","// Copyright (C) ConfigHub, Inc.\n// SPDX-License-Identifier: MIT\n//\n// Generated by the ConfigHub server from its own validation rules; synced by\n// scripts/sync-spec.mjs at the pinned version. Do not edit.\n\nexport const SLUG_PATTERN = /^[A-Za-z0-9]([\\-_.A-Za-z0-9]*[A-Za-z0-9])?$/;\nexport const SLUG_MAX_LENGTH = 128;\nexport const SLUG_PATTERN_MESSAGE =\n 'Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), and periods (.)';\n\nexport const LABEL_KEY_PATTERN = /^[A-Za-z0-9]([\\-_\\./A-Za-z0-9]*[A-Za-z0-9])?$/;\nexport const LABEL_KEY_MAX_LENGTH = 128;\nexport const LABEL_KEY_PATTERN_MESSAGE =\n 'Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)';\n\nexport const LABEL_VALUE_PATTERN = /^[\\-_@/#$%&~+=!?.,:;(){}\\[\\]<>|A-Za-z0-9](([\\-_@/#$%&~+=!?.,:;(){}\\[\\]<>|A-Za-z0-9]| )*[\\-_@/#$%&~+=!?.,:;(){}\\[\\]<>|A-Za-z0-9])?$/;\nexport const LABEL_VALUE_MAX_LENGTH = 128;\nexport const LABEL_VALUE_PATTERN_MESSAGE =\n 'Must start and end with a printable character (no leading/trailing spaces). Quotes, backslashes, and wildcards are not allowed';\n\nexport const ANNOTATION_KEY_PATTERN = /^[A-Za-z0-9]([\\-_\\./A-Za-z0-9]*[A-Za-z0-9])?$/;\nexport const ANNOTATION_KEY_MAX_LENGTH = 128;\nexport const ANNOTATION_KEY_PATTERN_MESSAGE =\n 'Must start and end with a letter or number. May contain letters, numbers, hyphens (-), underscores (_), periods (.), and forward slashes (/)';\n\nexport const ANNOTATION_VALUE_PATTERN = /^(.|\\n)*$/;\nexport const ANNOTATION_VALUE_MAX_LENGTH = 1024;\nexport const ANNOTATION_VALUE_PATTERN_MESSAGE =\n 'Any content is allowed, including multiline text';\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@confighub/api",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Typed, framework-agnostic client for the ConfigHub API",
5
5
  "license": "MIT",
6
6
  "repository": {