Documentation
¶
Index ¶
- Constants
- func ApplyCreateOpOverrides(resources []*Resource)
- func ApplyFileFields(resources []*Resource)
- func ApplyGetDetailPaths(resources []*Resource)
- func ApplyListDetailPaths(resources []*Resource)
- func ApplyLookupFields(resources []*Resource)
- func ApplyNameFieldOverrides(resources []*Resource)
- func ApplyNameOverrides(resources []*Resource)
- func ApplyTableColumns(resources []*Resource)
- func ApplyUpdateTokenOpOverrides(resources []*Resource)
- func BaseTag(tag string) string
- func ClassicIsCountElement(name string, prop *Property, siblings *Schema) bool
- func ClassicRepeatedElement(items *Schema) string
- func HasScaffoldShape(s *Schema) bool
- func KeepPath(path string, tags []string) bool
- func MergeDocuments(docs []*openapi3.T) (*openapi3.T, []string, error)
- func ScaffoldJSON(s *Schema) (string, error)
- func ScaffoldXML(s *Schema, root string) (string, error)
- func SecurityScopeForFile(specPath string) string
- type FileField
- type Generator
- type LookupField
- type OpPathMethod
- type Operation
- type Parameter
- type PathGroup
- type Property
- type RequestBody
- type Resource
- func FlattenResources(resources []*Resource) []*Resource
- func LoadDocuments(paths []string) (resources []*Resource, notes []string, err error)
- func ParseLoadedSpec(doc *openapi3.T, specPath string) ([]*Resource, error)
- func ParseMonolith(doc *openapi3.T) ([]*Resource, error)
- func ParsePlatformSpec(specPath string) ([]*Resource, error)
- func ParseSecuritySpec(specPath string) ([]*Resource, error)
- func ParseSpec(specPath string) ([]*Resource, error)
- type Response
- type ScalarField
- type Schema
- type StatusResult
- type TableColumn
- type TaggedPath
Constants ¶
const ClassicCountElement = "size"
ClassicCountElement is the name of the count element the Jamf Pro Classic API puts inside every repeated-element wrapper: `<criteria><size>1</size>…`.
It is server-computed and the spec does not mark it readOnly — it appears 104 times, 98 of them as a plain `$ref` to a shared integer schema — so nothing but ClassicIsCountElement keeps it out of request templates. Wire-checked 2026-09-02: a create carrying `<size>` and one omitting it both answer 201, so dropping it is safe as well as correct.
const CodegenHeader = "// Code generated by jamf-cli generator. DO NOT EDIT."
CodegenHeader is the marker line at the top of every modern API generated file. Must match the first line of resourceTemplate and registryTemplate.
Variables ¶
This section is empty.
Functions ¶
func ApplyCreateOpOverrides ¶ added in v1.12.0
func ApplyCreateOpOverrides(resources []*Resource)
ApplyCreateOpOverrides renames operations listed in resourceCreateOpOverrides to "create" so the generator emits them as the resource's canonical create command. Must be called after ApplyNameOverrides so resource names are canonical.
func ApplyFileFields ¶ added in v1.11.0
func ApplyFileFields(resources []*Resource)
ApplyFileFields sets FileFields on resources listed in resourceFileFields. Must be called after ApplyNameOverrides so names are canonical.
func ApplyGetDetailPaths ¶
func ApplyGetDetailPaths(resources []*Resource)
ApplyGetDetailPaths configures "get" commands to use a richer detail endpoint. For resources whose get has a section parameter (e.g. computers-inventory), the detail path is stored in GetDetailPath and used as the default — specifying --section overrides back to the original path. For resources without section filtering (e.g. mobile-devices), the get path is swapped outright. Must be called after ApplyNameOverrides.
func ApplyListDetailPaths ¶
func ApplyListDetailPaths(resources []*Resource)
ApplyListDetailPaths swaps the "list" operation's path to a richer detail endpoint and injects a section query parameter. Must be called after ApplyNameOverrides and before ApplyTableColumns.
func ApplyLookupFields ¶
func ApplyLookupFields(resources []*Resource)
ApplyLookupFields sets LookupFields and GroupsClassicPath on resources. Must be called after ApplyNameOverrides so resource names are canonical.
func ApplyNameFieldOverrides ¶
func ApplyNameFieldOverrides(resources []*Resource)
ApplyNameFieldOverrides corrects NameField and IDField values that the auto-detection heuristics got wrong. Must be called after ApplyNameOverrides so resource names are in their final canonical form.
func ApplyNameOverrides ¶
func ApplyNameOverrides(resources []*Resource)
ApplyNameOverrides corrects resource names that auto-pluralization got wrong.
func ApplyTableColumns ¶
func ApplyTableColumns(resources []*Resource)
ApplyTableColumns sets TableColumns and DefaultSections on resources that have preferred column configuration. Must be called after ApplyNameOverrides.
func ApplyUpdateTokenOpOverrides ¶ added in v1.12.0
func ApplyUpdateTokenOpOverrides(resources []*Resource)
ApplyUpdateTokenOpOverrides detaches the configured auxiliary token-update op from the resource's Operations slice and records it on r.UpdateTokenOp. The main update command then composes a token PUT + a body PUT based on which flags are supplied.
func BaseTag ¶ added in v1.29.0
BaseTag returns the tag a path's operations belong to, with any `-preview` suffix removed.
func ClassicIsCountElement ¶ added in v1.28.0
ClassicIsCountElement reports whether a property named `size` is the Classic API's collection counter rather than a field in its own right.
The name is overloaded in the spec and a blanket drop would delete real data. Of the 104 occurrences, two are physical capacities in MB, not counts: computer_post's `hardware.storage[].device.size` (example 512287) and the `partition.size` beneath it. Neither is reachable today — no Classic resource in specs/classic/resources.yaml binds computer_post, since Pro's modern computers-inventory covers computers — and TestNoBoundResourceCarriesASemanticSizeField fails if an ingest ever binds one.
The discriminator is a repeated sibling: a counter counts something, so it only ever appears beside an array or, in an array-item wrapper, beside the object being repeated. `partition`, whose twelve siblings are all scalars, is correctly kept by that test. `device` is not — it has a `partition` array beside it — which is exactly why the guard test exists rather than a cleverer rule: the honest fix when that case becomes reachable is to read the spec again, not to guess harder now.
func ClassicRepeatedElement ¶ added in v1.28.0
ClassicRepeatedElement returns the element name a Classic array's members are wrapped in, or "" when the array does not have that shape.
The Classic API is XML, and its JSON representation renders a repeated element as an array of single-key objects:
<criteria> criteria: {type: array, items: {properties: {
<size>1</size> criterion: {…},
<criterion>…</criterion> size: {$ref: size}
</criteria> }}}
So the element name lives one level below the array, as the name of the items schema's sole object-valued property. It is not derivable from the array's own name: `criteria` holds `criterion`, `computers` holds `computer`, and `scope.limit_to_users.user_groups` holds `user_group`.
Returns "" for an array of scalars and for an items schema with more than one object-valued property, neither of which has an unambiguous element name.
func HasScaffoldShape ¶ added in v1.28.0
HasScaffoldShape reports whether a request-body schema carries enough shape for --scaffold to be worth offering: named properties, or an array whose element has them.
The array arm is not hypothetical padding. The Jamf Pro generator gated on "has properties" alone, and a bare-array request body has none — so `pro app-requests update`, the one Pro endpoint whose body is a top-level array, shipped with no --scaffold flag at all rather than with an unhelpful one. A schema with neither still gets no flag, because a scaffold of "{}" tells a caller nothing.
func KeepPath ¶ added in v1.29.0
KeepPath reports whether a document path should be ingested at all, given the tags its operations carry.
This is the declared "do not turn this into a command" list, and it is the only thing standing between the command surface and upstream's legacy endpoints. Grouping by path is faithful to the document, which means it is also faithful to the parts of the document nobody should be calling.
func MergeDocuments ¶ added in v1.29.0
MergeDocuments unions several OpenAPI documents into one.
It exists so there is a single parse path. Route A (`make sync-specs`) copies per-resource files out of a jamf/jss checkout and route B ingests one consolidated document; merging the first into the shape of the second means the file boundary becomes an input detail rather than something that decides command names.
Components are unioned across every document, the shared library file included. A per-resource file references cross-resource definitions by external $ref, so its own Components block holds only part of what its operations reach — and a closure computed against that part would silently come up short, which is how detectNameField would start answering from nothing.
A path declared by two documents is a hard error: one URL meaning two things is exactly what a silent overwrite hides, and upstream shipping a duplicate basename is an occurrence this repo already guards against elsewhere.
A *component* declared by two documents is not, and must not be. The splitter inlines a component into every file that reaches it, so the same schema name legitimately appears in dozens of per-resource files — `ApiError` is in most of them. Identical declarations merge silently; a genuine disagreement takes the first and is reported, because refusing the whole ingest over a cosmetic difference in an error schema would block route A for nothing. Returns the merged document and any such reports.
func ScaffoldJSON ¶ added in v1.28.0
ScaffoldJSON returns a pretty-printed JSON template for a request body, derived from its parsed schema. It backs every generator's --scaffold output: the modern Jamf Pro generator, the Platform Gateway generator and the Jamf Security Cloud generator all call this, so a scaffold means the same thing whichever API a command belongs to.
Before this was shared, the three had drifted into three different answers for the same schema. Pro skipped read-only fields and honoured spec examples but never descended into nested objects; platform and security descended into objects but ignored both examples and read-only. All three rendered an array as "[]" regardless of what it held, which is the gap this exists to close — `platform-device-groups create --scaffold` emitted "criteria": [] for a five-field element, and the only feedback on a wrong guess was a 400.
The rules, and why:
- Read-only properties are omitted. This is a request template and the server rejects or ignores them.
- Write-only properties are kept. They are the ones a caller most needs prompting for — passwords, secrets, keystores — and they never appear in a GET, so a scaffold is the only place they surface. See docs/solutions/logic-errors/write-only-fields-dropped-by-update-set-2026-07-22.md.
- A spec example wins over a synthesised placeholder. A real value teaches the format; "" does not.
- An array shows one element when the element is an object, and stays empty otherwise. The object shape is the information a caller cannot guess; a scalar element's type is evident from the field and its help text, and rendering [""] would imply an empty string is a meaningful entry.
Returns "{}" for a nil schema, so a template can embed the output unconditionally. A marshalling failure is returned, not swallowed: this runs at generation time, and the alternative is an operation that ships a scaffold of "{}" while `make generate` exits 0 — the silent-shortening failure mode that TestParseSchema_DepthCapUnreachedByLiveSpecs exists to prevent one tier up.
func ScaffoldXML ¶ added in v1.28.0
ScaffoldXML returns an indented XML template for a Classic API request body, derived from its parsed schema and wrapped in the given root element.
It is the XML sibling of ScaffoldJSON and shares its rules — read-only properties omitted, write-only kept, a spec example preferred over a placeholder, one element shown for an array of objects — so a scaffold means the same thing whichever API a command belongs to (docs/solutions/conventions/one-scaffold-walker-2026-08-20.md).
It is a separate renderer rather than a re-marshal of ScaffoldJSON's output because the JSON is not the wire format here: the Classic API takes XML, and three of its shapes have no faithful JSON round trip. Repeated elements collapse a wrapper level (see ClassicRepeatedElement), the `size` count element has to be dropped, and element order carries meaning in XML while a JSON object's key order does not — so the template is built straight from the schema.
Two extra rules of its own, both wire-checked against a live tenant on 2026-09-02:
- The `size` count element is dropped. It is server-computed, and a create carrying it and one omitting it both answer 201.
- Every `id` the spec declares is kept, including a resource's own. A body `id` is inert on the Classic API: a create sending `<id>99999</id>` answered 201 and assigned 226, and a PUT to /networksegments/id/228 carrying `<id>229</id>` updated 228 while leaving 229 untouched — the URL wins. So there is nothing to protect a caller from, and the alternative is worse: most `id` elements in a Classic body are foreign keys the caller is supposed to supply (a policy's category, site, dock item and directory binding all reference one), so a rule that stripped them would have to distinguish identity from reference, and getting that wrong silently removes the field that binds a policy to its category.
func SecurityScopeForFile ¶ added in v1.23.0
SecurityScopeForFile returns the internal/security.Client scope name ("Risk", "Lifecycle", or "SSE") that owns every resource parsed out of the given spec filename — used by generator/security to pick which DoExpect{Scope} method generated commands call. Empty when the file isn't a recognized Security Cloud spec.
Types ¶
type FileField ¶ added in v1.11.0
type FileField struct {
Flag string // CLI flag name, e.g. "script-file"
Field string // Request-body property that receives the file contents, e.g. "scriptContents"
Encoding string // "raw" (string) or "base64"
Desc string // Flag description shown in --help
CompanionField string // Optional: body property auto-populated with filepath.Base(path) when absent (e.g. "tokenFileName" for DEP)
NameFallback string // "none" | "keep-ext" | "strip-ext" — when the body lacks a name, derive one from the filename
NameFlag bool // When true, emit a --name flag on create/apply/upload-style ops that sets the body's name field (for tokens whose filename makes a poor record name).
RenameAfterUpload bool // When true, and --name is supplied on an upload-style op whose request schema rejects a name field (e.g. DEP /upload-token → DeviceEnrollmentTokenDto has only encodedToken + tokenFileName), the generator emits a follow-up GET+PUT on the standard update path to apply the name.
}
FileField declares a resource field whose value is sourced from a local file via a dedicated CLI flag on create/update/apply/patch. The file contents are injected into the request body pre-marshal, overwriting any value the caller may have supplied in the body. Encoding, companion-field population, and name fallback are all driven per entry.
type Generator ¶
type Generator struct {
// contains filtered or unexported fields
}
Generator generates Go code from parsed resources
func NewGenerator ¶
NewGenerator creates a new code generator
type LookupField ¶
type LookupField struct {
Flag string // CLI flag name (e.g. "serial")
RSQLField string // RSQL filter field path (e.g. "hardware.serialNumber")
Desc string // Flag description shown in --help
Section string // Optional inventory section to request so the RSQLField is present in the response (e.g. "HARDWARE"); empty when the field is in the default section.
}
LookupField represents an alternate identifier that can be used to resolve a resource ID instead of the primary name field (e.g. serial number for computers).
type OpPathMethod ¶ added in v1.12.0
OpPathMethod is a (path, method) pair used to identify an operation for overrides.
type Operation ¶
type Operation struct {
Name string // e.g., "list", "get", "create"
Method string // HTTP method
Path string // API path
Summary string
Description string
Parameters []*Parameter
RequestBody *RequestBody
Responses map[string]*Response
IsAction bool // x-action: true
IsDestructive bool // Requires confirmation (delete, erase, etc.)
IsList bool // List operation with pagination support
IsPaginated bool // Any GET with pagination params (broader than IsList); gates --all/--limit auto-pagination
APIVersion string // v1, v2, preview, etc.
Privileges []string // x-required-privileges
// FallbackPaths holds lower-version base paths for GET/DELETE ops where the
// same endpoint exists at multiple API versions. Listed in descending version
// order so the runtime tries the newest fallback first.
FallbackPaths []string
// BulkActionPath is set on a per-{id} x-action when the spec also declares a
// sibling collection-level action of the same name (e.g. the per-deployment
// installation-retry and the no-{id} bulk installation-retry). It holds the
// bulk endpoint's path; the generator surfaces it as an --all flag that hits
// the collection-level endpoint in a single call instead of the {id} one.
BulkActionPath string
// StatusResults lists non-2xx statuses this operation documents as results
// rather than failures (see documentedStatusResults in parser.go). The
// generated command carries them through registry.WithAllowedStatuses and
// renders their body instead of letting the client map them to an
// exit-code error. Empty for all but a handful of check-style endpoints.
StatusResults []StatusResult
// NoContentDescription is the 204 response's description, set only when
// StatusResults is non-empty — a 204 has no body, so the generated command
// synthesizes one from this so the success case is machine-readable too.
NoContentDescription string
// ExpectedStatus is the success status the server actually answers, from
// the published spec's x-jamf-expected-status extension. Non-zero only
// where the SDK found the declared status wrong by probing the wire; it
// overrides the status derived from the responses map.
ExpectedStatus int
// GatewayLevel, GatewayBasis and GatewayDetail record whether the Jamf
// Platform gateway exposes this operation, from specs/gateway/coverage.json.
// Empty when the gateway serves it or when no manifest was available. Basis
// is the evidence ("probe" or "unpublished") and selects the wording of the
// refusal, not whether there is one. See generator/gateway.
GatewayLevel string
GatewayBasis string
GatewayDetail string
// GatewayPrivileges are the Jamf Account capability permissions the gateway
// requires for this operation, also from specs/gateway/coverage.json. A
// different vocabulary from Privileges above, not a translation of it: that
// field holds the Jamf Pro API-role privilege names an instance enforces,
// and the GA consolidation folded several of those into one capability. Both
// are surfaced in the commands catalog so an integration can be sized
// without provoking a 403.
//
// Empty for an unserved operation — the published spec declares no scope for
// what it does not publish — and for the 44 unauthenticated Jamf Pro
// endpoints.
GatewayPrivileges []string
// ScopeTypes are the Jamf Platform API scope levels the published spec
// declares this operation's credential must be created at — some subset of
// "organization", "environment" and "tenant", from the spec-root
// x-scope-types extension. Platform operations only; empty for a Jamf Pro
// or Classic one, whose scope is a property of the gateway route rather
// than of the endpoint.
//
// Per-operation although the extension is per-spec, because two specs can
// merge into one resource and disagree: uem-connect and the enrollment API
// both tag a resource "activation-profiles", and a resource-level field
// would have had to pick one of their answers.
//
// This is what the SPEC claims, which is currently stricter than what the
// gateway serves — build v2082 moved six Platform specs to
// environment-only while a tenant credential still reaches at least
// platform-devices and platform-device-groups (probed 2026-09-05). So it
// is reported and hinted with, never used to refuse a command.
ScopeTypes []string
}
Operation represents an API operation (endpoint)
type Parameter ¶
type Parameter struct {
Name string
In string // "query", "path"
Description string
Required bool
Type string
Default any
IsArray bool
}
Parameter represents a query/path parameter
type PathGroup ¶ added in v1.29.0
type PathGroup struct {
// Name is the kebab-case command name, derived from Root unless an override
// replaces it.
Name string
// Root is the literal (non-parameter, non-version) path segments that
// identify the resource.
Root []string
// Paths are the document paths assigned to this group, sorted.
Paths []string
// Tag is the OpenAPI tag that names the group, with any `-preview` suffix
// removed. It is the resource's name unless the tag covers more than one
// group. Not every path in the group need carry it: a root can hold paths
// from two tags, and groupTag decides which one names the resource.
Tag string
// Versions are the API versions the group's paths are served at. A group
// spanning several is normal and is not itself a consolidation event —
// deduplicateVersionedOps decides that per version-stripped path shape.
Versions []int
}
PathGroup is one resource: the literal path segments that identify it, and every path that belongs to it.
func GroupPathsByTagAndCollection ¶ added in v1.29.0
func GroupPathsByTagAndCollection(paths []TaggedPath) []*PathGroup
GroupPathsByTagAndCollection assigns every path to a resource, using the tag to bound what may be grouped together and the path structure to decide the boundary inside a tag.
type Property ¶
type Property struct {
Name string
Type string
Description string
Example any
Nullable bool
ReadOnly bool
WriteOnly bool // true when the field is accepted in requests but never returned in responses (e.g. passwords, secrets)
SchemaRef string // name of the referenced component schema for object/array types (e.g. "ComputerGeneralUpdate")
Nested *Schema // resolved nested schema for object types (may be nil)
// VariantOnly marks a property that only a non-scaffolded variant of a
// discriminated-union body declares. It carries enum values for the help and
// nothing else — no type, no example — so a scaffold must not render it: it
// is not a field of the body the scaffold shows.
VariantOnly bool
// Enum holds the values this property is restricted to, in the order the
// spec lists them, rendered as literals. Empty for unconstrained
// properties. Not string-only: an integer enum is carried the same way,
// because a required field constrained to five specific durations is
// exactly the case help has to name.
//
// Carried so generated help can name the choices. A scaffold renders an
// enum field as an empty string like any other, which tells a caller
// nothing about what it accepts — and Security Cloud's ZTNA gateway vendor
// is a case-sensitive eleven-value enum whose rejection is a 400 that does
// not name the offending field, so guessing is expensive.
Enum []string
// Items is the element schema for an array-typed property, so a scaffold can
// show one element instead of a bare "[]". Nil when the element is a scalar
// or the spec declares no items.
//
// This is the array counterpart of Nested, and it is populated under a
// recursion cap that Nested never needed: an object property whose own
// properties are empty ends the walk, but an array property can name its
// parent's schema as its element type (a tree with a children[] of itself),
// which would recurse forever.
Items *Schema
}
Property represents a schema property
type RequestBody ¶
type RequestBody struct {
Description string
Required bool
Schema *Schema
IsMultipart bool // true when content type is multipart/form-data
IsMergePatch bool // true when content type is application/merge-patch+json
FileField string // schema property that holds the binary file (e.g. "file")
}
RequestBody represents a request body
type Resource ¶
type Resource struct {
Name string // e.g., "buildings"
NameSingular string // e.g., "building"
GoName string // e.g., "Buildings"
Description string
Operations []*Operation
Schemas map[string]*Schema
NameField string // Filter field for name lookups (default "name", some use "displayName")
IDField string // Response field for ID extraction in name resolution (default "id", some use "templateId", "groupId", etc.)
IsSingleton bool // True for settings-style resources: single object, GET+PUT, no {id} in any path
LookupFields []LookupField // Alternate identifier fields for patch-by-name / delete-by-name (e.g. serial number)
NameLookupPath string // Override list path for name resolution (when the standard list endpoint ignores RSQL)
NameLookupIDField string // Override ID field extracted from NameLookupPath response (when it differs from IDField)
HasVersionLock bool // True when PUT/POST request body includes versionLock (optimistic locking for prestages)
GroupsClassicPath string // When set, delete gets --group resolved via Classic API group list (e.g. "computergroups")
FileFields []FileField // File-sourced request-body fields (attached via --script-file, --token-file, etc.)
TableColumns []TableColumn // Preferred columns for list table output (when set, overrides generic column selection)
DefaultSections []string // Default --section values for list (when set, fetches these sections for table output)
GetDetailPath string // When set, "get" uses this path by default (returns all sections). If the get op has a section param, --section overrides back to the original path.
UpdateTokenOp *Operation // Optional: auxiliary PUT endpoint for file-field payloads (e.g. PUT /{id}/upload-token). When set, update/apply route the file-field flag to this endpoint instead of the main update body, and no standalone subcommand is emitted for it.
// Root is the literal (non-parameter, non-version) path segments that
// identify this resource — the group's own root, or a sub-resource's
// sub-path.
//
// Carried rather than re-derived, because every attempt to infer it has
// been wrong in a different way. "The shallowest no-param path" answers
// `/inventory-preload/csv` for a resource whose declared root
// `/v1/inventory-preload` is dropped, and `/mdm/commands` for `pro mdm`;
// "the path every other sits beneath" answers nothing for `enrollment`,
// whose group holds `/v1/adue-session-token-settings`. Three passes in
// parser.go took a root parameter for exactly this reason; a field is what
// stops the next consumer inventing a fourth heuristic.
Root []string
// Parent is the name of the resource this one nests under, empty for a
// top-level resource. See subresource.go: an independently-writable
// sub-path becomes a resource of its own so its verbs stop reading as the
// parent's.
Parent string
// SubResources are the nested sub-resources, each a Resource in its own
// right so every per-resource pass applies to it unchanged — singleton
// detection and the naming passes are exactly what has to run again over a
// sub-resource's own root, and reusing them is what makes `cert get`
// rather than `cert list` fall out.
SubResources []*Resource
}
Resource represents a parsed API resource (e.g., buildings, computers)
func FlattenResources ¶ added in v1.29.0
FlattenResources is Flatten over a slice.
func LoadDocuments ¶ added in v1.29.0
LoadDocuments loads every OpenAPI document at the given paths, merges them into one and derives every resource from the result.
One entry point so that "how many files was the spec split into" is not a question the rest of the generator can ask. Documents that fail to load are reported and skipped rather than aborting the run, matching the per-file behaviour it replaces — a single malformed spec should not take the whole command surface with it.
func ParseLoadedSpec ¶ added in v1.29.0
ParseLoadedSpec is ParseSpec over a document a caller has already loaded. specPath supplies the resource name and is not read. It exists for ParsePlatformSpec's untagged fallback, which holds the loaded document already: routing that through ParseSpec re-read and re-unmarshalled the same temp file, and cached it in specLoader under a path the caller then deletes.
func ParseMonolith ¶ added in v1.29.0
ParseMonolith derives every Jamf Pro resource from a single OpenAPI document, grouping paths by the collection they belong to.
This replaces splitting one document into 165 per-resource files and then naming each resource after the file it landed in. Those filenames came from upstream's jss module names, appear in no spec, and silently decided four things: the command name, the endpoint-version family, whether a `-preview` tag reached a command, and whether the splitter could delete the file.
Two consequences worth stating, because they are the reason this is not merely tidier:
- Version consolidation stops depending on a filename's `-vN` suffix. Every version of a path lands in one resource and deduplicateVersionedOps picks the highest per path shape, so the mis-keying that cost this CLI its v4 computer-inventory endpoints cannot be expressed.
- Each resource's schema set is the transitive $ref closure of its own operations, not "whatever else was in the same file". detectNameField and detectIDField scan that set, so scoping it is what keeps their answers the same as before — a merged document with one shared schema map would have them pick a field off an unrelated resource.
func ParsePlatformSpec ¶ added in v1.15.0
ParsePlatformSpec parses a Platform Gateway OpenAPI spec and returns one Resource per operation tag. Platform paths share an /api/{service}/{version}/ prefix that the runtime fills from auth context — it is not a per-call parameter. This loader strips the prefix to /v1/ and removes the tenantId path parameter from each operation before parsing.
Resources are grouped by the first tag on each operation. Operations without tags fall back to filename-based grouping via ParseSpec.
func ParseSecuritySpec ¶ added in v1.23.0
ParseSecuritySpec parses one Jamf Security Cloud OpenAPI spec (Risk, Device Lifecycle, or Shared Signals & Events) into Resources, using securityOpsByFile's hand-authored operation list. Strips the manually declared "authorization" header parameter every operation carries (the runtime injects the scoped bearer token itself, via internal/security.Client) and, for Device Lifecycle, the {customerId} path parameter (backfilled at request time from the login JWT, the same way the Platform parser backfills {tenantId}).
func (*Resource) AllOperations ¶ added in v1.29.0
AllOperations returns this resource's operations and every sub-resource's, which is what a consumer keyed on the endpoint rather than on the command needs.
Every such consumer has to use it, and the failure mode when one does not is silent: gateway stamping reads Operations, and an unstamped operation is not refused pre-flight, so a nested command on a withdrawn endpoint would go out to the bare 403 the refusal exists to pre-empt.
func (*Resource) CmdPath ¶ added in v1.29.0
CmdPath is the invocation path beneath `pro`, which for every resource is its qualified name. Named separately because that is what it means at the call sites that build --help examples.
func (*Resource) FileBase ¶ added in v1.29.0
FileBase is the stem of the generated file, distinct from Name because two sub-resources legitimately share a terminal segment (`settings` appears three times) and one file per resource is what the stale-file prune assumes.
func (*Resource) Flatten ¶ added in v1.29.0
Flatten returns this resource and every sub-resource, depth first, for the passes that key on a resource name.
func (*Resource) QualifiedName ¶ added in v1.29.0
QualifiedName is the resource's name prefixed by its parent's, the key a resource-name-keyed override table has to use to reach a sub-resource.
Separate from Name because Name is the cobra token: a sub-resource's Use is `cert`, and its identity across the generator is `sso-settings cert`.
type Response ¶
type Response struct {
StatusCode string
Description string
Schema *Schema
IsBinary bool // true for image/* content types, text/csv, or format:binary schemas
}
Response represents an API response
type ScalarField ¶
type ScalarField struct {
Path string // dot-notation path, e.g. "general.managed"
Type string // scalar type: "string", "integer", "boolean", "number"
}
ScalarField represents a patchable scalar field in dot-notation (e.g. "general.managed").
type Schema ¶
type Schema struct {
Name string
Type string
Properties map[string]*Property
Required []string
// Enum holds the values this schema is restricted to, when the schema is
// itself a constrained scalar rather than an object. For an array property
// that is where the constraint lives — the enum sits on the element schema,
// not on the array — so Items.Enum is how an "array of one of these" is
// discovered.
Enum []string
// Items is the element schema when Type is "array", for a schema that is
// itself an array rather than an object. Set only for arrays, and only as
// deep as parseSchema's recursion cap allows.
//
// Needed because a request body may be a bare array — the DNS whole-list
// replaces are — and without this such a body has no properties and no
// element shape, so a scaffold for it can only be "[]".
Items *Schema
// Variants names the alternative shapes of a discriminated union request
// body (a bare oneOf/anyOf), in spec order, and Discriminator the property
// that selects between them. Both empty for an ordinary schema.
//
// The schema itself carries the FIRST variant's properties, so every
// consumer — the scaffold, --set completion, the enum help — keeps working
// on a concrete shape rather than having to understand unions. Variants
// exists so the generated help can say that other shapes are legal, which is
// the part a caller cannot otherwise discover: uem-connectors create is one
// of these, and before this the whole body parsed to nothing, taking
// --scaffold and every "Allowed values:" line with it.
Variants []string
// Discriminator is the property whose value selects the variant.
Discriminator string
}
Schema represents a JSON schema
func ClassicArrayElementSchema ¶ added in v1.28.0
ClassicArrayElementSchema returns the schema of one member of a Classic array: the sole object-valued property's own schema when the array has the repeated-element shape, and the items schema itself otherwise.
This is what makes a dotted path skip the wrapper. A criterion's fields are addressed as `criteria[].name`, not `criteria[].criterion.name`, because the wrapper is an artefact of rendering XML as JSON rather than a level a caller should have to type.
func SchemaFromOpenAPI ¶ added in v1.28.0
SchemaFromOpenAPI parses one resolved OpenAPI schema into the generator's own Schema tree. It is the exported door onto parseSchema, opened for the Classic API generator: Classic resources are declared by a YAML manifest rather than by a spec, so generator/classic has schemas to parse but no operation to parse them from.
Exported rather than reimplemented because the schema walk is where the interesting decisions live — allOf composition, discriminated unions, the array-element recursion cap, enum value rendering — and a second copy of it would drift the way the three --scaffold builders did before docs/solutions/conventions/one-scaffold-walker-2026-08-20.md.
type StatusResult ¶ added in v1.27.0
StatusResult is a non-2xx response the API documents as a meaningful outcome of the operation rather than a failure of it.
type TableColumn ¶
type TableColumn struct {
Field string // JSON field path (e.g., "general.name") — may use dot-notation for nested fields
Label string // Display label (e.g., "name") — used as the column header
}
TableColumn defines a preferred column for list table output.
type TaggedPath ¶ added in v1.29.0
TaggedPath is one document path and the base tag its operations carry.