@pptb/types 1.1.3-beta.2 → 1.2.1

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/dataverseAPI.d.ts CHANGED
@@ -480,7 +480,7 @@ declare namespace DataverseAPI {
480
480
  *
481
481
  * @param entityLogicalName - Logical name of the entity
482
482
  * @param searchByLogicalName - Whether to search by logical name (true) or metadata ID (false)
483
- * @param selectColumns - Optional array of column names to retrieve (retrieves all if not specified)
483
+ * @param entityProperties - Optional array of property names to retrieve (retrieves all if not specified)
484
484
  * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
485
485
  * @returns Object containing entity metadata
486
486
  *
@@ -500,11 +500,11 @@ declare namespace DataverseAPI {
500
500
  * // Multi-connection tool using secondary connection
501
501
  * const metadata = await dataverseAPI.getEntityMetadata('account', true, ['LogicalName'], 'secondary');
502
502
  */
503
- getEntityMetadata: (entityLogicalName: string, searchByLogicalName: boolean, selectColumns?: string[], connectionTarget?: "primary" | "secondary") => Promise<EntityMetadata>;
503
+ getEntityMetadata: (entityLogicalName: string, searchByLogicalName: boolean, entityProperties?: string[], connectionTarget?: "primary" | "secondary") => Promise<EntityMetadata>;
504
504
 
505
505
  /**
506
506
  * Get metadata for all entities
507
- * @param selectColumns - Optional array of column names to retrieve (retrieves LogicalName, DisplayName, MetadataId by default)
507
+ * @param entityProperties - Optional array of property names to retrieve (retrieves LogicalName, DisplayName, MetadataId by default)
508
508
  * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
509
509
  * @returns Object with value array containing all entity metadata
510
510
  *
@@ -519,14 +519,14 @@ declare namespace DataverseAPI {
519
519
  * // Multi-connection tool using secondary connection
520
520
  * const allEntities = await dataverseAPI.getAllEntitiesMetadata(['LogicalName'], 'secondary');
521
521
  */
522
- getAllEntitiesMetadata: (selectColumns?: string[], connectionTarget?: "primary" | "secondary") => Promise<EntityMetadataCollection>;
522
+ getAllEntitiesMetadata: (entityProperties?: string[], connectionTarget?: "primary" | "secondary") => Promise<EntityMetadataCollection>;
523
523
 
524
524
  /**
525
525
  * Get related metadata for a specific entity (attributes, relationships, etc.)
526
526
  *
527
527
  * @param entityLogicalName - Logical name of the entity
528
528
  * @param relatedPath - Path after EntityDefinitions(LogicalName='name') (e.g., 'Attributes', 'OneToManyRelationships', 'ManyToOneRelationships', 'ManyToManyRelationships', 'Keys')
529
- * @param selectColumns - Optional array of column names to retrieve (retrieves all if not specified)
529
+ * @param relatedProperties - Optional array of property names to retrieve (retrieves all if not specified)
530
530
  * @param connectionTarget - Optional connection target for multi-connection tools ('primary' or 'secondary'). Defaults to 'primary'.
531
531
  * @returns Object containing the related metadata
532
532
  *
@@ -600,7 +600,7 @@ declare namespace DataverseAPI {
600
600
  getEntityRelatedMetadata: <P extends EntityRelatedMetadataPath>(
601
601
  entityLogicalName: string,
602
602
  relatedPath: P,
603
- selectColumns?: string[],
603
+ relatedProperties?: string[],
604
604
  connectionTarget?: "primary" | "secondary",
605
605
  ) => Promise<EntityRelatedMetadataResponse<P>>;
606
606
 
package/lib/validate.js CHANGED
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  /** @typedef {{ name: string; url?: string }} Contributor */
10
- /** @typedef {{ "connect-src"?: string[]; "script-src"?: string[]; "style-src"?: string[]; "img-src"?: string[]; "font-src"?: string[]; "frame-src"?: string[] }} CspExceptions */
10
+ /** @typedef {{ "connect-src"?: string[]; "script-src"?: string[]; "style-src"?: string[]; "img-src"?: string[]; "font-src"?: string[]; "frame-src"?: string[]; "media-src"?: string[] }} CspExceptions */
11
11
  /** @typedef {{ repository?: string; website?: string; funding?: string; readmeUrl?: string }} Configurations */
12
12
  /** @typedef {{ multiConnection?: "required" | "optional" | "none"; minAPI?: string }} Features */
13
13
  /**
@@ -85,6 +85,16 @@ function validateIconPath(fieldName, iconPath, errors) {
85
85
  errors.push(`${fieldName} must be a relative path (e.g., 'icon.svg' or 'icons/icon.svg')`);
86
86
  return;
87
87
  }
88
+ // Reject Windows absolute paths like "C:\..." or "C:/"
89
+ if (/^[a-zA-Z]:/.test(iconPath)) {
90
+ errors.push(`${fieldName} must be a relative path (e.g., 'icon.svg' or 'icons/icon.svg')`);
91
+ return;
92
+ }
93
+ // Reject backslashes — icon paths must use forward slashes
94
+ if (iconPath.includes("\\")) {
95
+ errors.push(`${fieldName} must use forward slashes, not backslashes (e.g., 'icons/icon.svg')`);
96
+ return;
97
+ }
88
98
  if (iconPath.includes("..")) {
89
99
  errors.push(`${fieldName} cannot contain '..' (path traversal not allowed)`);
90
100
  return;
@@ -205,14 +215,14 @@ async function validatePackageJson(packageJson, options = {}) {
205
215
  }
206
216
 
207
217
  // Funding validation (optional but recommended)
208
- if (!configs.funding) {
209
- warnings.push("configurations.funding is not set; consider adding a sponsorship or funding URL to support contributors");
210
- } else if (!isValidUrl(configs.funding)) {
211
- warnings.push("configurations.funding has an invalid URL format");
212
- } else if (!skipUrlChecks) {
213
- const accessible = await isUrlAccessible(configs.funding);
214
- if (!accessible) {
215
- warnings.push("configurations.funding URL is not accessible");
218
+ if (configs.funding) {
219
+ if (!isValidUrl(configs.funding)) {
220
+ warnings.push("configurations.funding has an invalid URL format");
221
+ } else if (!skipUrlChecks) {
222
+ const accessible = await isUrlAccessible(configs.funding);
223
+ if (!accessible) {
224
+ warnings.push("configurations.funding URL is not accessible");
225
+ }
216
226
  }
217
227
  }
218
228
 
@@ -233,45 +243,57 @@ async function validatePackageJson(packageJson, options = {}) {
233
243
 
234
244
  // CSP Exceptions validation (optional, but validated if present)
235
245
  if (packageJson.cspExceptions) {
236
- const validCspDirectives = ["connect-src", "script-src", "style-src", "img-src", "font-src", "frame-src"];
246
+ const cspExceptions = packageJson.cspExceptions;
237
247
 
238
- const hasAnyDirectives = Object.keys(packageJson.cspExceptions).length > 0;
239
- if (!hasAnyDirectives) {
240
- errors.push("cspExceptions cannot be empty. If CSP exceptions are not needed, remove the cspExceptions field");
241
- }
248
+ if (typeof cspExceptions !== "object" || cspExceptions === null || Array.isArray(cspExceptions)) {
249
+ errors.push("cspExceptions must be an object mapping CSP directives to arrays of strings");
250
+ } else {
251
+ const validCspDirectives = ["connect-src", "script-src", "style-src", "img-src", "font-src", "frame-src", "media-src"];
242
252
 
243
- Object.keys(packageJson.cspExceptions).forEach((directive) => {
244
- if (!validCspDirectives.includes(directive)) {
245
- warnings.push(`Unknown CSP directive: ${directive}`);
246
- }
247
- const values = packageJson.cspExceptions?.[/** @type {keyof CspExceptions} */ (directive)];
248
- if (values && !Array.isArray(values)) {
249
- errors.push(`CSP directive "${directive}" must be an array of strings`);
250
- } else if (values && values.length === 0) {
251
- errors.push(`CSP directive "${directive}" cannot be an empty array`);
253
+ const hasAnyDirectives = Object.keys(cspExceptions).length > 0;
254
+ if (!hasAnyDirectives) {
255
+ errors.push("cspExceptions cannot be empty. If CSP exceptions are not needed, remove the cspExceptions field");
252
256
  }
253
- });
257
+
258
+ Object.keys(cspExceptions).forEach((directive) => {
259
+ if (!validCspDirectives.includes(directive)) {
260
+ warnings.push(`Unknown CSP directive: ${directive}`);
261
+ }
262
+ const values = cspExceptions[/** @type {keyof CspExceptions} */ (directive)];
263
+ if (values && !Array.isArray(values)) {
264
+ errors.push(`CSP directive "${directive}" must be an array of strings`);
265
+ } else if (values && values.length === 0) {
266
+ errors.push(`CSP directive "${directive}" cannot be an empty array`);
267
+ }
268
+ });
269
+ }
254
270
  }
255
271
 
256
272
  // Features validation (optional, but validated if present)
257
- if (packageJson.features) {
258
- const VALID_FEATURE_KEYS = ["multiConnection", "minAPI"];
259
- const featureKeys = Object.keys(packageJson.features);
260
- const invalidKeys = featureKeys.filter((key) => !VALID_FEATURE_KEYS.includes(key));
261
-
262
- if (invalidKeys.length > 0) {
263
- errors.push(`features can only contain ${VALID_FEATURE_KEYS.map((k) => `'${k}'`).join(", ")} properties. Invalid properties: ${invalidKeys.join(", ")}`);
264
- }
273
+ if (packageJson.features !== undefined) {
274
+ const features = packageJson.features;
275
+
276
+ if (features === null || typeof features !== "object" || Array.isArray(features)) {
277
+ errors.push("features must be a non-array object with optional 'multiConnection' and 'minAPI' properties");
278
+ } else {
279
+ const VALID_FEATURE_KEYS = ["multiConnection", "minAPI"];
280
+ const featureKeys = Object.keys(features);
281
+ const invalidKeys = featureKeys.filter((key) => !VALID_FEATURE_KEYS.includes(key));
282
+
283
+ if (invalidKeys.length > 0) {
284
+ errors.push(`features can only contain ${VALID_FEATURE_KEYS.map((k) => `'${k}'`).join(", ")} properties. Invalid properties: ${invalidKeys.join(", ")}`);
285
+ }
265
286
 
266
- if (packageJson.features.multiConnection === undefined) {
267
- errors.push("features.multiConnection is required when features object is provided");
268
- } else if (!VALID_MULTI_CONNECTION_VALUES.includes(packageJson.features.multiConnection)) {
269
- errors.push(`features.multiConnection must be one of: ${VALID_MULTI_CONNECTION_VALUES.join(", ")}`);
270
- }
287
+ if (features.multiConnection === undefined) {
288
+ errors.push("features.multiConnection is required when features object is provided");
289
+ } else if (!VALID_MULTI_CONNECTION_VALUES.includes(features.multiConnection)) {
290
+ errors.push(`features.multiConnection must be one of: ${VALID_MULTI_CONNECTION_VALUES.join(", ")}`);
291
+ }
271
292
 
272
- if (packageJson.features.minAPI !== undefined) {
273
- if (typeof packageJson.features.minAPI !== "string" || !SEMVER_REGEX.test(packageJson.features.minAPI)) {
274
- errors.push("features.minAPI must be a valid semantic version string (e.g., '1.0.0')");
293
+ if (features.minAPI !== undefined) {
294
+ if (typeof features.minAPI !== "string" || !SEMVER_REGEX.test(features.minAPI)) {
295
+ errors.push("features.minAPI must be a valid semantic version string (e.g., '1.0.0')");
296
+ }
275
297
  }
276
298
  }
277
299
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pptb/types",
3
- "version": "1.1.3-beta.2",
3
+ "version": "1.2.1",
4
4
  "description": "Type definitions for Power Platform ToolBox APIs and validity checks for tool packages",
5
5
  "main": "index.d.ts",
6
6
  "types": "index.d.ts",
package/toolboxAPI.d.ts CHANGED
@@ -191,11 +191,13 @@ declare namespace ToolBoxAPI {
191
191
  /**
192
192
  * Show a loading screen in the tool's context
193
193
  * @param message Optional message to display (default: "Loading...")
194
+ * @deprecated Use a tool-level loading pattern instead. Will be removed in a future version.
194
195
  */
195
196
  showLoading: (message?: string) => Promise<void>;
196
197
 
197
198
  /**
198
199
  * Hide the loading screen in the tool's context
200
+ * @deprecated Use a tool-level loading pattern instead. Will be removed in a future version.
199
201
  */
200
202
  hideLoading: () => Promise<void>;
201
203
  }