spitfirepm 23.9700.8 → 23.9700.9

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/README.md CHANGED
@@ -25,6 +25,7 @@ apiResult.then( (a) => {
25
25
  ### Change Log
26
26
 
27
27
  ```
28
+ 23.9700.9 - QueryCatalog and improve Attachment and Contact endpoints
28
29
  23.9700.8 - Improved ContactClient endpoints
29
30
  23.9700.7 - GetDV method clarifications
30
31
  23.9700.6 - Audit History Model enhanced
@@ -1373,6 +1373,21 @@ export declare class ConfigClient extends APIClientBase {
1373
1373
  private getManageToolsWithCallbacks;
1374
1374
  private processGetManageToolsWithCallbacks;
1375
1375
  protected processGetManageTools(xhr: any): MenuAction[] | null | null;
1376
+ /**
1377
+ * Returns the dynamic queries this site defines, each with its parameters
1378
+ */
1379
+ getQueries(): Promise<QueryDefinition[] | null>;
1380
+ private getQueriesWithCallbacks;
1381
+ private processGetQueriesWithCallbacks;
1382
+ protected processGetQueries(xhr: any): QueryDefinition[] | null | null;
1383
+ /**
1384
+ * Returns one dynamic query definition with its parameters
1385
+ * @param queryName Query name, e.g. qUserActivitySummary
1386
+ */
1387
+ getQuery(queryName: string | null): Promise<QueryDefinition | null>;
1388
+ private getQueryWithCallbacks;
1389
+ private processGetQueryWithCallbacks;
1390
+ protected processGetQuery(xhr: any): QueryDefinition | null | null;
1376
1391
  /**
1377
1392
  * Returns the list of regions
1378
1393
  */
@@ -1751,15 +1766,6 @@ export declare class DocumentToolsClient extends APIClientBase {
1751
1766
  private patchDocAddressWithCallbacks;
1752
1767
  private processPatchDocAddressWithCallbacks;
1753
1768
  protected processPatchDocAddress(xhr: any): string | null;
1754
- /**
1755
- * Inserts an attachment on the specified document, optionally from a template
1756
- * @param id Document Key
1757
- * @param newData New attachment data. To copy a template use DocKey:TemplateKey
1758
- */
1759
- addDocAttachments(id: string, newData: DocAttachment[]): Promise<DocAttachment | null>;
1760
- private addDocAttachmentsWithCallbacks;
1761
- private processAddDocAttachmentsWithCallbacks;
1762
- protected processAddDocAttachments(xhr: any): DocAttachment | null | null;
1763
1769
  /**
1764
1770
  * Returns the attachments for the specified document
1765
1771
  * @param id Document Key
@@ -1789,6 +1795,15 @@ export declare class DocumentToolsClient extends APIClientBase {
1789
1795
  private updateDocAttachmentsWithCallbacks;
1790
1796
  private processUpdateDocAttachmentsWithCallbacks;
1791
1797
  protected processUpdateDocAttachments(xhr: any): string | null;
1798
+ /**
1799
+ * Inserts an attachment on the specified document, optionally from a template
1800
+ * @param id Document Key
1801
+ * @param newData New attachment data. To copy a template use DocKey:TemplateKey
1802
+ */
1803
+ addDocAttachments(id: string, newData: DocAttachment[]): Promise<DocAttachment | null>;
1804
+ private addDocAttachmentsWithCallbacks;
1805
+ private processAddDocAttachmentsWithCallbacks;
1806
+ protected processAddDocAttachments(xhr: any): DocAttachment | null | null;
1792
1807
  /**
1793
1808
  * Creates a PDF from the Assembled Attachments specified on this document; returns a task key
1794
1809
  * @param id Document Key
@@ -4661,27 +4676,42 @@ export interface ContactFilters {
4661
4676
  CSIListLike?: string | undefined;
4662
4677
  /** Phone Like (matches any phone number) */
4663
4678
  PhoneLike?: string | undefined;
4664
- /** When true, result is limited to */
4679
+ /** When true, result is limited to contacts who can log in to sfPMS (sfUser=1).
4680
+ These six flags COMBINE WITH AND, not OR - see the remarks on this class. */
4665
4681
  Users?: boolean;
4666
- /** When true, result is limited to */
4682
+ /** When true, result is limited to customer contacts (ContactType='C'). */
4667
4683
  Customers?: boolean;
4668
- /** When true, result is limited to */
4684
+ /** When true, result is limited to employees (ContactType='E'). */
4669
4685
  Employee?: boolean;
4670
- /** When true, result is limited to */
4686
+ /** When true, result is limited to public contacts (IsPublic=1). Rare. */
4671
4687
  Public?: boolean;
4672
- /** When true, result is limited to primary company contacts */
4688
+ /** When true, result is limited to primary company contacts - the company itself
4689
+ rather than a person at it (xsfContactCompany.PrimaryContactKey). */
4673
4690
  Company?: boolean;
4674
- /** When true, result is limited to */
4691
+ /** When true, result is limited to vendor contacts (ContactType='V', or any contact
4692
+ carrying a VendorID). */
4675
4693
  Vendors?: boolean;
4676
- /** 1==Active;0==Inactive; 2==Both */
4677
- ContactState?: number;
4694
+ /** 1==Active; 0==Inactive; 2==Both. Omit (null) for active only.
4695
+ Null and 1 are the same thing. The nullability exists because this is a
4696
+ short: before it was nullable a caller who simply left the field out sent 0 and
4697
+ silently got INACTIVE contacts, which is nobody's intent. Callers that already send an
4698
+ explicit 0, 1 or 2 are unaffected. */
4699
+ ContactState?: number | undefined;
4678
4700
  /** UCRole Key, or use 00000000-0000-0000-0000-000000000000 for unspecified */
4679
4701
  RoleKey?: string | undefined;
4680
4702
  /** Use 00000000-0000-0000-0000-000000000000 for unspecified */
4681
4703
  UserKey?: string | undefined;
4682
- /** Default 2000-01-01 */
4704
+ /** Earliest LastLogin to include. Omit for no lower bound.
4705
+ THIS IS A LOGIN-DATE FILTER, and supplying either bound therefore limits the
4706
+ result to contacts who have signed in at least once - which in practice means system
4707
+ users, since only they have a LastLogin at all. Contacts that have NEVER logged in
4708
+ have no LastLogin and so satisfy no range; if "never signed in" is part of the question,
4709
+ ask for it without a date bound and look for a null LastLogin on the rows. */
4683
4710
  FromDate?: Date | undefined;
4684
- /** Default today */
4711
+ /** Latest LastLogin to include. Omit for no upper bound.
4712
+ Inclusive. A date with no time component covers the whole of that day, so
4713
+ ThruDate 2026-02-04 includes a login at 2026-02-04 16:20. See FromDate
4714
+ for what a login-date bound does to the result set. */
4685
4715
  ThruDate?: Date | undefined;
4686
4716
  }
4687
4717
  /** Summary information about a contact */
@@ -4710,8 +4740,14 @@ export interface ContactSummary {
4710
4740
  Company?: string | undefined;
4711
4741
  /** For Vendors, indicate related CSI */
4712
4742
  CSIList?: string | undefined;
4713
- /** Readonly. Specifies when this user last logged in. Kept for inactive and former users. */
4714
- LastLogin?: Date;
4743
+ /** Readonly. Specifies when this user last logged in. Kept for inactive and former users.
4744
+ NULL means never signed in, and that is a different fact from "signed in a long
4745
+ time ago" - for a seat-licensing question it is usually the more actionable one.
4746
+ Nullable for exactly that reason: as a plain DateTime a never-logged-in contact
4747
+ serialises as 0001-01-01, which reads like a date and buckets like an ancient login.
4748
+ Matches Contact.LastLogin, which is already nullable.
4749
+ Only contacts who can log in (sfUser=1) ever carry a value here. */
4750
+ LastLogin?: Date | undefined;
4715
4751
  /** When false, this row is ignored and ineffective */
4716
4752
  Active?: boolean;
4717
4753
  /** When true, there are no references to this contact */
@@ -8098,6 +8134,57 @@ export interface ProjKPIFact {
8098
8134
  /** UI CFG Item Name */
8099
8135
  ItemName?: string | undefined;
8100
8136
  }
8137
+ /** Describes one dynamic query a site can run - what it answers, what it needs, and who may see it. This is the catalog entry for a query executed through api/query/{queryName}/{dataContext}. */
8138
+ export interface QueryDefinition {
8139
+ /** Name of the query, unique within the rule, and the value passed to api/query. By
8140
+ convention these begin with a lower case q */
8141
+ QueryName: string;
8142
+ /** Document type this definition applies to, or null when it applies everywhere. A site
8143
+ may define the same query name differently per document type */
8144
+ DocTypeKey?: string | undefined;
8145
+ /** Caller-facing description of what this query answers. Carries more weight than the
8146
+ name when choosing between candidates, and is the only prose a caller gets */
8147
+ Purpose?: string | undefined;
8148
+ /** Agent when safe to expose to an external or AI caller; Internal otherwise. Null is
8149
+ unclassified and is treated as Internal, so an unreviewed entry is never exposed.
8150
+ Same vocabulary and the same fail-closed rule as LookupResult.Audience */
8151
+ Audience?: string | undefined;
8152
+ /** The TSQL this query runs, normally a thin EXEC wrapper over a stored procedure.
8153
+ Returned only to a caller entitled to administer the rule; blank otherwise, because
8154
+ this is an execution recipe rather than a description */
8155
+ Alias?: string | undefined;
8156
+ /** Adjustment to the command timeout: a positive value adds that many seconds, a negative
8157
+ value multiplies by its magnitude, and -1 means leave the connection default alone */
8158
+ TimeoutAdjust?: number;
8159
+ /** Role the caller must hold to run this query, or null when unrestricted. Enforced by
8160
+ the engine, which answers with a single explanatory Message row rather than an error
8161
+ when the caller does not hold it */
8162
+ RequiredRole?: string | undefined;
8163
+ /** True when this definition is one Spitfire distributes. A site may override any facet
8164
+ with its own row, which takes precedence - so a distributed definition is a default,
8165
+ not a guarantee of what will run */
8166
+ IsDistributed?: boolean;
8167
+ /** True when the resolved definition includes at least one row the site supplied itself.
8168
+ Worth surfacing: it is the difference between what we shipped and what will run */
8169
+ IsOverridden?: boolean;
8170
+ /** Number of caller-supplied parameters this query expects. Derived from the QPList */
8171
+ DependsCount?: number | undefined;
8172
+ /** True when the query's text references @pDocMasterKey, @pDocTypeKey or @pProject
8173
+ respectively, so a caller knows what document context to supply. A hint derived by
8174
+ inspecting the text, not a contract - a commented-out reference counts */
8175
+ UsesDocMasterKey?: boolean;
8176
+ /** See UsesDocMasterKey */
8177
+ UsesDocTypeKey?: boolean;
8178
+ /** See UsesDocMasterKey */
8179
+ UsesProject?: boolean;
8180
+ /** Caller-supplied parameters, in DependsOn order. Never null; a query taking none has
8181
+ an empty array */
8182
+ Parameters?: QueryParameter[] | undefined;
8183
+ /** Collection of commands for this row */
8184
+ MenuCommands?: MenuAction[] | undefined;
8185
+ /** eTag */
8186
+ ETag?: string | undefined;
8187
+ }
8101
8188
  /** Various common filters - not every filter is supported by every query */
8102
8189
  export interface QueryFilters {
8103
8190
  /** Project Mask (eg GC%) */
@@ -8163,6 +8250,46 @@ export interface QueryFilters {
8163
8250
  /** Key Value pairs of Keys and ETags, applicable to change/diffgram endpoints */
8164
8251
  ClientDataSummary?: CurrentDataSummary[] | undefined;
8165
8252
  }
8253
+ /** Describes one caller-supplied parameter of a dynamic query: what it means, what type of value belongs there, and where it lands in the DependsOn array. */
8254
+ export interface QueryParameter {
8255
+ /** Query this parameter belongs to, matching QueryDefinition.QueryName */
8256
+ QueryName: string;
8257
+ /** SQL parameter name including the @, exactly as it appears in the query's QPList - or,
8258
+ for a context parameter, the engine slot it describes such as @pDocMasterKey */
8259
+ ParameterName: string;
8260
+ /** True where the engine binds this parameter from the REQUEST rather than from DependsOn:
8261
+ @pDocMasterKey, @pProject and @pDocTypeKey are supplied as context, not by position */
8262
+ IsContext?: boolean;
8263
+ /** Zero-based position in the DependsOn array, taken from this parameter's position in the
8264
+ QPList. The engine maps DependsOn positionally, so this is the number a caller needs.
8265
+ Null when IsContext is set, because a context parameter has no
8266
+ position - it is nullable precisely so that a consumer cannot read a meaningful zero
8267
+ where there is no index at all */
8268
+ DependsIndex?: number | undefined;
8269
+ /** What this parameter means to a caller, for example As Of Date or Project ID */
8270
+ Label?: string | undefined;
8271
+ /** Semantic type of the value, for example DATE, GUID or STRING. Advisory only - every
8272
+ parameter is bound as a VarChar regardless, so the query itself must convert */
8273
+ PVType?: string | undefined;
8274
+ /** False where the query tolerates a blank here. Note that an omitted parameter arrives
8275
+ as an empty string rather than NULL, so a query that wants NULL must say so itself */
8276
+ IsRequired?: boolean;
8277
+ /** A concrete sample value; grounds a caller better than the type name alone. Dates
8278
+ should be given in ISO form, since the bound value is interpreted by SQL Server and a
8279
+ day/month ordering depends on the session */
8280
+ ExampleValue?: string | undefined;
8281
+ /** Name of the Lookup that produces a valid value for this parameter, letting a caller
8282
+ chain rather than guess. A soft reference by name, so it may not resolve */
8283
+ SourceLookup?: string | undefined;
8284
+ /** Free-text caveats about this parameter */
8285
+ Notes?: string | undefined;
8286
+ /** Flag */
8287
+ Active?: boolean;
8288
+ /** Collection of commands for this row */
8289
+ MenuCommands?: MenuAction[] | undefined;
8290
+ /** eTag */
8291
+ ETag?: string | undefined;
8292
+ }
8166
8293
  export interface RangeConditionHeaderValue {
8167
8294
  Date?: Date | undefined;
8168
8295
  EntityTag?: EntityTagHeaderValue | undefined;