@credibledata/cred-cli 0.0.7 → 0.0.102

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.
Files changed (159) hide show
  1. package/README-DEV.md +2 -2
  2. package/bun.lock +113 -337
  3. package/dist/client/api.js +2999 -1953
  4. package/dist/client/api.js.map +1 -1
  5. package/dist/client/base.js +1 -1
  6. package/dist/client/common.js +1 -1
  7. package/dist/client/configuration.js +1 -1
  8. package/dist/client/index.js +1 -1
  9. package/dist/clientconfiguration.js +59 -24
  10. package/dist/clientconfiguration.js.map +1 -1
  11. package/dist/clientconfiguration.spec.js +69 -37
  12. package/dist/clientconfiguration.spec.js.map +1 -1
  13. package/dist/commands/add.js +18 -5
  14. package/dist/commands/add.js.map +1 -1
  15. package/dist/commands/connection/createconnections.js +4 -4
  16. package/dist/commands/connection/createconnections.js.map +1 -1
  17. package/dist/commands/connection/createconnections.spec.js +11 -1
  18. package/dist/commands/connection/createconnections.spec.js.map +1 -1
  19. package/dist/commands/connection/deleteconnection.js +4 -4
  20. package/dist/commands/connection/deleteconnection.js.map +1 -1
  21. package/dist/commands/connection/deleteconnection.spec.js +1 -1
  22. package/dist/commands/connection/deleteconnection.spec.js.map +1 -1
  23. package/dist/commands/connection/listconnections.js +4 -4
  24. package/dist/commands/connection/listconnections.js.map +1 -1
  25. package/dist/commands/connection/listconnections.spec.js +1 -1
  26. package/dist/commands/connection/listconnections.spec.js.map +1 -1
  27. package/dist/commands/{project/createproject.js → environment/createenvironment.js} +17 -14
  28. package/dist/commands/environment/createenvironment.js.map +1 -0
  29. package/dist/commands/{project/createproject.spec.js → environment/createenvironment.spec.js} +46 -46
  30. package/dist/commands/environment/createenvironment.spec.js.map +1 -0
  31. package/dist/commands/{project/deleteproject.js → environment/deleteenvironment.js} +9 -9
  32. package/dist/commands/environment/deleteenvironment.js.map +1 -0
  33. package/dist/commands/{project/deleteproject.spec.js → environment/deleteenvironment.spec.js} +29 -29
  34. package/dist/commands/environment/deleteenvironment.spec.js.map +1 -0
  35. package/dist/commands/{project/getproject.js → environment/getenvironment.js} +8 -8
  36. package/dist/commands/environment/getenvironment.js.map +1 -0
  37. package/dist/commands/{project/getproject.spec.js → environment/getenvironment.spec.js} +32 -33
  38. package/dist/commands/environment/getenvironment.spec.js.map +1 -0
  39. package/dist/commands/{project/listprojects.js → environment/listenvironments.js} +10 -10
  40. package/dist/commands/environment/listenvironments.js.map +1 -0
  41. package/dist/commands/{project/listprojects.spec.js → environment/listenvironments.spec.js} +35 -35
  42. package/dist/commands/environment/listenvironments.spec.js.map +1 -0
  43. package/dist/commands/{project/setproject.js → environment/setenvironment.js} +6 -5
  44. package/dist/commands/environment/setenvironment.js.map +1 -0
  45. package/dist/commands/{project/setproject.spec.js → environment/setenvironment.spec.js} +9 -9
  46. package/dist/commands/environment/setenvironment.spec.js.map +1 -0
  47. package/dist/commands/{project/updateproject.js → environment/updateenvironment.js} +13 -13
  48. package/dist/commands/environment/updateenvironment.js.map +1 -0
  49. package/dist/commands/{project/updateproject.spec.js → environment/updateenvironment.spec.js} +44 -44
  50. package/dist/commands/environment/updateenvironment.spec.js.map +1 -0
  51. package/dist/commands/get.js +15 -5
  52. package/dist/commands/get.js.map +1 -1
  53. package/dist/commands/legacy.js +9 -0
  54. package/dist/commands/legacy.js.map +1 -0
  55. package/dist/commands/list.js +17 -4
  56. package/dist/commands/list.js.map +1 -1
  57. package/dist/commands/misc/login.js +2 -2
  58. package/dist/commands/misc/login.js.map +1 -1
  59. package/dist/commands/misc/login.spec.js +41 -5
  60. package/dist/commands/misc/login.spec.js.map +1 -1
  61. package/dist/commands/package/deletepackage.js +4 -4
  62. package/dist/commands/package/deletepackage.js.map +1 -1
  63. package/dist/commands/package/deletepackage.spec.js +1 -1
  64. package/dist/commands/package/deletepackage.spec.js.map +1 -1
  65. package/dist/commands/package/listpackages.js +4 -4
  66. package/dist/commands/package/listpackages.js.map +1 -1
  67. package/dist/commands/package/listpackages.spec.js +1 -1
  68. package/dist/commands/package/listpackages.spec.js.map +1 -1
  69. package/dist/commands/package/publish.js +10 -10
  70. package/dist/commands/package/publish.js.map +1 -1
  71. package/dist/commands/package/publish.spec.js +34 -6
  72. package/dist/commands/package/publish.spec.js.map +1 -1
  73. package/dist/commands/package/updatepackage.js +4 -4
  74. package/dist/commands/package/updatepackage.js.map +1 -1
  75. package/dist/commands/package/updatepackage.spec.js +1 -1
  76. package/dist/commands/package/updatepackage.spec.js.map +1 -1
  77. package/dist/commands/rm.js +15 -4
  78. package/dist/commands/rm.js.map +1 -1
  79. package/dist/commands/set.js +12 -4
  80. package/dist/commands/set.js.map +1 -1
  81. package/dist/commands/update.js +19 -6
  82. package/dist/commands/update.js.map +1 -1
  83. package/dist/commands/version/archive-unarchive-version.js +4 -5
  84. package/dist/commands/version/archive-unarchive-version.js.map +1 -1
  85. package/dist/commands/version/archive-unarchive-version.spec.js +4 -4
  86. package/dist/commands/version/archive-unarchive-version.spec.js.map +1 -1
  87. package/dist/commands/version/listversions.js +4 -4
  88. package/dist/commands/version/listversions.js.map +1 -1
  89. package/dist/commands/version/listversions.spec.js +1 -1
  90. package/dist/commands/version/listversions.spec.js.map +1 -1
  91. package/dist/constants.js +47 -19
  92. package/dist/constants.js.map +1 -1
  93. package/dist/constants.spec.js +90 -0
  94. package/dist/constants.spec.js.map +1 -0
  95. package/dist/index.js +74 -16
  96. package/dist/index.js.map +1 -1
  97. package/package.json +7 -8
  98. package/src/client/api.ts +3552 -2182
  99. package/src/client/base.ts +1 -1
  100. package/src/client/common.ts +1 -1
  101. package/src/client/configuration.ts +1 -1
  102. package/src/client/index.ts +1 -1
  103. package/src/clientconfiguration.spec.ts +113 -114
  104. package/src/clientconfiguration.ts +69 -28
  105. package/src/commands/add.ts +35 -12
  106. package/src/commands/connection/createconnections.spec.ts +11 -1
  107. package/src/commands/connection/createconnections.ts +4 -4
  108. package/src/commands/connection/deleteconnection.spec.ts +1 -1
  109. package/src/commands/connection/deleteconnection.ts +4 -4
  110. package/src/commands/connection/listconnections.spec.ts +1 -1
  111. package/src/commands/connection/listconnections.ts +4 -4
  112. package/src/commands/{project/createproject.spec.ts → environment/createenvironment.spec.ts} +56 -54
  113. package/src/commands/{project/createproject.ts → environment/createenvironment.ts} +17 -14
  114. package/src/commands/{project/deleteproject.spec.ts → environment/deleteenvironment.spec.ts} +59 -30
  115. package/src/commands/{project/deleteproject.ts → environment/deleteenvironment.ts} +10 -10
  116. package/src/commands/environment/getenvironment.spec.ts +110 -0
  117. package/src/commands/{project/getproject.ts → environment/getenvironment.ts} +9 -9
  118. package/src/commands/{project/listprojects.spec.ts → environment/listenvironments.spec.ts} +37 -35
  119. package/src/commands/{project/listprojects.ts → environment/listenvironments.ts} +13 -8
  120. package/src/commands/{project/setproject.spec.ts → environment/setenvironment.spec.ts} +8 -8
  121. package/src/commands/{project/setproject.ts → environment/setenvironment.ts} +4 -4
  122. package/src/commands/{project/updateproject.spec.ts → environment/updateenvironment.spec.ts} +53 -51
  123. package/src/commands/{project/updateproject.ts → environment/updateenvironment.ts} +19 -17
  124. package/src/commands/get.ts +22 -9
  125. package/src/commands/legacy.ts +5 -0
  126. package/src/commands/list.ts +33 -9
  127. package/src/commands/misc/login.spec.ts +47 -5
  128. package/src/commands/misc/login.ts +6 -2
  129. package/src/commands/package/deletepackage.spec.ts +1 -1
  130. package/src/commands/package/deletepackage.ts +4 -4
  131. package/src/commands/package/listpackages.spec.ts +1 -1
  132. package/src/commands/package/listpackages.ts +4 -4
  133. package/src/commands/package/publish.spec.ts +36 -6
  134. package/src/commands/package/publish.ts +12 -8
  135. package/src/commands/package/updatepackage.spec.ts +1 -1
  136. package/src/commands/package/updatepackage.ts +4 -4
  137. package/src/commands/rm.ts +25 -9
  138. package/src/commands/set.ts +13 -4
  139. package/src/commands/update.ts +32 -12
  140. package/src/commands/version/archive-unarchive-version.spec.ts +4 -4
  141. package/src/commands/version/archive-unarchive-version.ts +4 -7
  142. package/src/commands/version/listversions.spec.ts +1 -1
  143. package/src/commands/version/listversions.ts +4 -4
  144. package/src/constants.spec.ts +111 -0
  145. package/src/constants.ts +81 -18
  146. package/src/index.ts +103 -17
  147. package/dist/commands/project/createproject.js.map +0 -1
  148. package/dist/commands/project/createproject.spec.js.map +0 -1
  149. package/dist/commands/project/deleteproject.js.map +0 -1
  150. package/dist/commands/project/deleteproject.spec.js.map +0 -1
  151. package/dist/commands/project/getproject.js.map +0 -1
  152. package/dist/commands/project/getproject.spec.js.map +0 -1
  153. package/dist/commands/project/listprojects.js.map +0 -1
  154. package/dist/commands/project/listprojects.spec.js.map +0 -1
  155. package/dist/commands/project/setproject.js.map +0 -1
  156. package/dist/commands/project/setproject.spec.js.map +0 -1
  157. package/dist/commands/project/updateproject.js.map +0 -1
  158. package/dist/commands/project/updateproject.spec.js.map +0 -1
  159. package/src/commands/project/getproject.spec.ts +0 -109
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable */
3
3
  /**
4
4
  * Credible Admin API
5
- * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Project & Package Lifecycle**: Full CRUD operations for projects, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, project, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Projects │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
5
+ * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Environment & Package Lifecycle**: Full CRUD operations for environments, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, environment, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Environments │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
6
6
  *
7
7
  * The version of the OpenAPI document: v0
8
8
  * Contact: support@credibledata.com
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable */
3
3
  /**
4
4
  * Credible Admin API
5
- * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Project & Package Lifecycle**: Full CRUD operations for projects, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, project, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Projects │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
5
+ * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Environment & Package Lifecycle**: Full CRUD operations for environments, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, environment, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Environments │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
6
6
  *
7
7
  * The version of the OpenAPI document: v0
8
8
  * Contact: support@credibledata.com
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable */
3
3
  /**
4
4
  * Credible Admin API
5
- * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Project & Package Lifecycle**: Full CRUD operations for projects, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, project, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Projects │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
5
+ * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Environment & Package Lifecycle**: Full CRUD operations for environments, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, environment, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Environments │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
6
6
  *
7
7
  * The version of the OpenAPI document: v0
8
8
  * Contact: support@credibledata.com
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable */
3
3
  /**
4
4
  * Credible Admin API
5
- * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Project & Package Lifecycle**: Full CRUD operations for projects, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, project, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Projects │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
5
+ * The Credible Admin API is a comprehensive REST API that empowers organizations to manage their Malloy data modeling ecosystem with enterprise-grade security and governance. This API provides programmatic access to all administrative functions, enabling seamless integration with existing workflows and automation systems. ## Key Features - **Organization Management**: Create and manage organizations with fine-grained access controls - **Environment & Package Lifecycle**: Full CRUD operations for environments, packages, and versions - **Connection Management**: Secure database connection configuration and management - **Permission Management**: Granular role-based access control (RBAC) at organization, environment, package, workspace, and document levels - **Workspace Management**: Collaborative workspaces for data modeling and analysis - **User & Group Management**: Comprehensive user administration with group-based permissions ## Resource Hierarchy The API follows a hierarchical resource structure with fine-grained permission management at each level: ``` Organizations ├── Permissions ├── Environments │ ├── Permissions │ ├── Packages │ │ ├── Permissions │ │ └── Versions │ └── Connections ├── Workspaces │ ├── Permissions │ └── Documents │ └── Permissions └── Groups ├── Permissions └── Members System-Level Resources: ├── Users ├── System Permissions └── Demo Operations ``` ## Authentication & Authorization All API endpoints require proper authentication. The API implements fine-grained authorization using role-based permissions: - **Admin**: Full access to all resources within scope - **Modeler**: Can create and modify data models and packages - **Viewer**: Read-only access to resources - **Manager**: Workspace management capabilities - **Editor**: Document editing permissions ## Rate Limiting & Best Practices - API requests are rate-limited to ensure system stability - Implement proper error handling and retry logic - Cache responses when appropriate to reduce API calls ## Support & Documentation For additional support, examples, and integration guides, visit our developer documentation or contact our support team.
6
6
  *
7
7
  * The version of the OpenAPI document: v0
8
8
  * Contact: support@credibledata.com
@@ -22,8 +22,21 @@ describe("ClientConfiguration", () => {
22
22
  let clientConfig: ClientConfiguration;
23
23
  let readFileSyncStub: sinon.SinonStub;
24
24
  let writeFileSyncStub: sinon.SinonStub;
25
+ let renameSyncStub: sinon.SinonStub;
25
26
  let customConfigPath: string;
26
27
 
28
+ // Simulate a real ENOENT from readFileSync (has `.code = "ENOENT"`).
29
+ // A bare `Error("File not found")` no longer triggers first-time-setup —
30
+ // loadConfig now rethrows non-ENOENT errors instead of silently masking them.
31
+ const enoent = () => Object.assign(new Error("ENOENT"), { code: "ENOENT" });
32
+
33
+ // Pull the most-recent persisted config payload off the stubs. Atomic writes
34
+ // go through writeFileSync(tmpPath, json) followed by renameSync(tmp, path).
35
+ const lastWrittenConfig = () => {
36
+ const args = writeFileSyncStub.lastCall.args;
37
+ return JSON.parse(args[1] as string);
38
+ };
39
+
27
40
  beforeEach(() => {
28
41
  customConfigPath = join(os.homedir(), ".cred_test");
29
42
  clientConfig = new ClientConfiguration(customConfigPath);
@@ -32,6 +45,7 @@ describe("ClientConfiguration", () => {
32
45
 
33
46
  readFileSyncStub = sinon.stub(fs, "readFileSync");
34
47
  writeFileSyncStub = sinon.stub(fs, "writeFileSync");
48
+ renameSyncStub = sinon.stub(fs, "renameSync");
35
49
  });
36
50
 
37
51
  afterEach(() => {
@@ -43,7 +57,7 @@ describe("ClientConfiguration", () => {
43
57
  });
44
58
 
45
59
  it("should load the default config if the file does not exist", () => {
46
- readFileSyncStub.throws(new Error("File not found"));
60
+ readFileSyncStub.throws(enoent());
47
61
  clientConfig.loadConfig();
48
62
  expect(clientConfig["config"]).to.deep.equal({
49
63
  configPerEnvironment: fullPerEnv(),
@@ -51,6 +65,21 @@ describe("ClientConfiguration", () => {
51
65
  });
52
66
  });
53
67
 
68
+ it("should throw loudly when the config file is unparseable", () => {
69
+ // Non-atomic writes from older binaries can leave `.cred` truncated.
70
+ // loadConfig must fail loud instead of silently overwriting — a silent
71
+ // reset erases the access token for every subsequent caller.
72
+ readFileSyncStub.returns("{ not json");
73
+ expect(() => clientConfig.loadConfig()).to.throw(/may be corrupt/);
74
+ expect(writeFileSyncStub.called).to.be.false;
75
+ });
76
+
77
+ it("should throw when readFileSync fails with a non-ENOENT error", () => {
78
+ const eacces = Object.assign(new Error("EACCES"), { code: "EACCES" });
79
+ readFileSyncStub.throws(eacces);
80
+ expect(() => clientConfig.loadConfig()).to.throw(/EACCES/);
81
+ });
82
+
54
83
  it("should load the config file correctly", () => {
55
84
  const mockConfig = {
56
85
  configPerEnvironment: {
@@ -92,134 +121,106 @@ describe("ClientConfiguration", () => {
92
121
  });
93
122
 
94
123
  it("should set and get the project correctly", () => {
95
- readFileSyncStub.throws(new Error("File not found"));
124
+ readFileSyncStub.throws(enoent());
96
125
  clientConfig.setProject("new-project");
97
126
 
98
- expect(
99
- writeFileSyncStub.calledWith(
100
- customConfigPath,
101
- JSON.stringify({
102
- configPerEnvironment: fullPerEnv({
103
- production: { project: "new-project" },
104
- }),
105
- activeEnvironment: "production",
106
- }),
107
- ),
108
- ).to.be.true;
127
+ expect(lastWrittenConfig()).to.deep.equal({
128
+ configPerEnvironment: fullPerEnv({
129
+ production: { project: "new-project" },
130
+ }),
131
+ activeEnvironment: "production",
132
+ });
133
+ expect(renameSyncStub.lastCall.args[1]).to.equal(customConfigPath);
109
134
  });
110
135
 
111
136
  it("should set and get the access token correctly", () => {
112
- readFileSyncStub.throws(new Error("File not found"));
137
+ readFileSyncStub.throws(enoent());
113
138
  clientConfig.setAccessToken(false, "token-123");
114
139
 
115
- expect(
116
- writeFileSyncStub.calledWith(
117
- customConfigPath,
118
- JSON.stringify({
119
- configPerEnvironment: fullPerEnv({
120
- production: {
121
- isServiceAccountToken: true,
122
- accessToken: "token-123",
123
- },
124
- }),
125
- activeEnvironment: "production",
126
- }),
127
- ),
128
- ).to.be.true;
140
+ expect(lastWrittenConfig()).to.deep.equal({
141
+ configPerEnvironment: fullPerEnv({
142
+ production: {
143
+ isServiceAccountToken: true,
144
+ accessToken: "token-123",
145
+ },
146
+ }),
147
+ activeEnvironment: "production",
148
+ });
129
149
  });
130
150
 
131
- it("should clear auth when setting access token", () => {
151
+ it("should preserve other per-env fields when setting access token", () => {
152
+ // Valid initial config (with an activeEnvironment so loadConfig accepts it).
132
153
  readFileSyncStub.returns(
133
- JSON.stringify({ auth: { username: "user", password: "pass" } }),
154
+ JSON.stringify({
155
+ configPerEnvironment: {
156
+ production: {
157
+ auth: { username: "user", password: "pass" },
158
+ },
159
+ },
160
+ activeEnvironment: "production",
161
+ }),
134
162
  );
135
163
  clientConfig.setAccessToken(true, "new-token");
136
- expect(
137
- writeFileSyncStub.calledWith(
138
- customConfigPath,
139
- JSON.stringify({
140
- configPerEnvironment: fullPerEnv({
141
- production: {
142
- isServiceAccountToken: false,
143
- accessToken: "new-token",
144
- },
145
- }),
146
- activeEnvironment: "production",
147
- }),
148
- ),
149
- ).to.be.true;
164
+ expect(lastWrittenConfig().configPerEnvironment.production).to.deep.equal(
165
+ {
166
+ auth: { username: "user", password: "pass" },
167
+ isServiceAccountToken: false,
168
+ accessToken: "new-token",
169
+ },
170
+ );
150
171
  });
151
172
 
152
173
  it("should set and get organization", () => {
153
- readFileSyncStub.throws(new Error("File not found"));
174
+ readFileSyncStub.throws(enoent());
154
175
  clientConfig.setOrganization("my-org");
155
176
 
156
- expect(
157
- writeFileSyncStub.calledWith(
158
- customConfigPath,
159
- JSON.stringify({
160
- configPerEnvironment: fullPerEnv({
161
- production: { organization: "my-org" },
162
- }),
163
- activeEnvironment: "production",
164
- }),
165
- ),
166
- ).to.be.true;
177
+ expect(lastWrittenConfig()).to.deep.equal({
178
+ configPerEnvironment: fullPerEnv({
179
+ production: { organization: "my-org" },
180
+ }),
181
+ activeEnvironment: "production",
182
+ });
167
183
  });
168
184
 
169
185
  it("should set and get refresh token", () => {
170
- readFileSyncStub.throws(new Error("File not found"));
186
+ readFileSyncStub.throws(enoent());
171
187
  clientConfig.setRefreshToken("refresh-token-123");
172
188
 
173
- expect(
174
- writeFileSyncStub.calledWith(
175
- customConfigPath,
176
- JSON.stringify({
177
- configPerEnvironment: fullPerEnv({
178
- production: { refreshToken: "refresh-token-123" },
179
- }),
180
- activeEnvironment: "production",
181
- }),
182
- ),
183
- ).to.be.true;
189
+ expect(lastWrittenConfig()).to.deep.equal({
190
+ configPerEnvironment: fullPerEnv({
191
+ production: { refreshToken: "refresh-token-123" },
192
+ }),
193
+ activeEnvironment: "production",
194
+ });
184
195
  });
185
196
 
186
197
  it("should set and get VSCode user", () => {
187
- readFileSyncStub.throws(new Error("File not found"));
198
+ readFileSyncStub.throws(enoent());
188
199
  clientConfig.setVSCodeUser("testuser", "test@example.com");
189
200
 
190
- expect(
191
- writeFileSyncStub.calledWith(
192
- customConfigPath,
193
- JSON.stringify({
194
- configPerEnvironment: fullPerEnv({
195
- production: {
196
- vsCodeUser: {
197
- username: "testuser",
198
- email: "test@example.com",
199
- },
200
- },
201
- }),
202
- activeEnvironment: "production",
203
- }),
204
- ),
205
- ).to.be.true;
201
+ expect(lastWrittenConfig()).to.deep.equal({
202
+ configPerEnvironment: fullPerEnv({
203
+ production: {
204
+ vsCodeUser: {
205
+ username: "testuser",
206
+ email: "test@example.com",
207
+ },
208
+ },
209
+ }),
210
+ activeEnvironment: "production",
211
+ });
206
212
  });
207
213
 
208
214
  it("should set and get JWT access token", () => {
209
- readFileSyncStub.throws(new Error("File not found"));
215
+ readFileSyncStub.throws(enoent());
210
216
  clientConfig.setJwtAccessToken("jwt-token-abc");
211
217
 
212
- expect(
213
- writeFileSyncStub.calledWith(
214
- customConfigPath,
215
- JSON.stringify({
216
- configPerEnvironment: fullPerEnv({
217
- production: { jwtAccessToken: "jwt-token-abc" },
218
- }),
219
- activeEnvironment: "production",
220
- }),
221
- ),
222
- ).to.be.true;
218
+ expect(lastWrittenConfig()).to.deep.equal({
219
+ configPerEnvironment: fullPerEnv({
220
+ production: { jwtAccessToken: "jwt-token-abc" },
221
+ }),
222
+ activeEnvironment: "production",
223
+ });
223
224
  });
224
225
 
225
226
  it("should return true for doesConfigExists when environment config exists", () => {
@@ -248,26 +249,20 @@ describe("ClientConfiguration", () => {
248
249
  readFileSyncStub.returns(JSON.stringify(mockConfig));
249
250
  clientConfig.destroyConfig();
250
251
 
251
- const lastWrite = writeFileSyncStub.lastCall.args[1] as string;
252
- expect(JSON.parse(lastWrite)).to.deep.equal({
252
+ expect(lastWrittenConfig()).to.deep.equal({
253
253
  configPerEnvironment: fullPerEnv(),
254
254
  activeEnvironment: "production",
255
255
  });
256
256
  });
257
257
 
258
258
  it("should set and get environment", () => {
259
- readFileSyncStub.throws(new Error("File not found"));
259
+ readFileSyncStub.throws(enoent());
260
260
  clientConfig.setEnvironment("staging");
261
261
 
262
- expect(
263
- writeFileSyncStub.calledWith(
264
- customConfigPath,
265
- JSON.stringify({
266
- configPerEnvironment: fullPerEnv(),
267
- activeEnvironment: "staging",
268
- }),
269
- ),
270
- ).to.be.true;
262
+ expect(lastWrittenConfig()).to.deep.equal({
263
+ configPerEnvironment: fullPerEnv(),
264
+ activeEnvironment: "staging",
265
+ });
271
266
  });
272
267
 
273
268
  it("should return headers with Bearer token for user tokens", () => {
@@ -308,11 +303,14 @@ describe("ClientConfiguration", () => {
308
303
  expect(headers.Authorization).to.equal("ApiKey service-token");
309
304
  });
310
305
 
311
- it("should reset to defaults when config file is corrupted (missing activeEnvironment)", () => {
306
+ it("should throw when config file is missing activeEnvironment", () => {
307
+ // Previously loadConfig silently reset to defaults — that turned one
308
+ // corrupt read into permanent state loss for every caller. Now we fail loud.
312
309
  readFileSyncStub.returns(JSON.stringify({ configPerEnvironment: {} }));
313
- clientConfig.loadConfig();
314
-
315
- expect(clientConfig["config"].activeEnvironment).to.equal("production");
310
+ expect(() => clientConfig.loadConfig()).to.throw(
311
+ /Invalid config structure/,
312
+ );
313
+ expect(writeFileSyncStub.called).to.be.false;
316
314
  });
317
315
 
318
316
  describe("isTokenValid", () => {
@@ -466,7 +464,8 @@ describe("ClientConfiguration", () => {
466
464
 
467
465
  expect(loggerStub.info.calledWith(sinon.match("Organization:"))).to.be
468
466
  .true;
469
- expect(loggerStub.info.calledWith(sinon.match("Project:"))).to.be.true;
467
+ expect(loggerStub.info.calledWith(sinon.match("Environment:"))).to.be
468
+ .true;
470
469
  });
471
470
 
472
471
  it("should print error when token is invalid", () => {
@@ -1,3 +1,4 @@
1
+ import crypto from "crypto";
1
2
  import fs from "fs";
2
3
  import { jwtDecode } from "jwt-decode";
3
4
  import kleur from "kleur";
@@ -44,28 +45,35 @@ export class ClientConfiguration {
44
45
  }
45
46
 
46
47
  public loadConfig(): ConfigFile {
48
+ let fileContents: Buffer | undefined;
47
49
  try {
48
- const fileContents = fs.readFileSync(this.configPath);
49
- this.config = JSON.parse(fileContents.toString());
50
- if (
51
- !this.config.activeEnvironment ||
52
- !this.config.configPerEnvironment
53
- ) {
54
- throw new Error(
55
- "Corrupted config file found, restoring to default settings.",
56
- );
57
- }
50
+ fileContents = fs.readFileSync(this.configPath);
58
51
  } catch (error) {
59
- logger.warn(error);
60
- const configPerEnvironment: ConfigFile["configPerEnvironment"] = {};
61
- for (const env of ALL_ENVIRONMENTS) {
62
- configPerEnvironment[env] = {};
52
+ if ((error as NodeJS.ErrnoException)?.code === "ENOENT") {
53
+ // First-time setup: create a default config on disk.
54
+ this.config = this.defaultConfig();
55
+ this.writeConfig();
56
+ return this.config;
63
57
  }
64
- this.config = {
65
- configPerEnvironment,
66
- activeEnvironment: "production",
67
- };
68
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
58
+ throw error;
59
+ }
60
+
61
+ try {
62
+ this.config = JSON.parse(fileContents.toString());
63
+ } catch (error) {
64
+ // Non-atomic writes from older binaries, or a manually corrupted file,
65
+ // can leave `.cred` unparseable. Fail loud rather than silently
66
+ // overwriting — a silent reset erases the access token for every
67
+ // subsequent caller on the same machine.
68
+ throw new Error(
69
+ `Failed to parse ${this.configPath}: ${error}. The file may be corrupt; re-run \`cred login\` to reset.`,
70
+ );
71
+ }
72
+
73
+ if (!this.config.activeEnvironment || !this.config.configPerEnvironment) {
74
+ throw new Error(
75
+ `Invalid config structure in ${this.configPath}; re-run \`cred login\` to reset.`,
76
+ );
69
77
  }
70
78
 
71
79
  for (const env of ALL_ENVIRONMENTS) {
@@ -77,13 +85,46 @@ export class ClientConfiguration {
77
85
  return this.config;
78
86
  }
79
87
 
88
+ private defaultConfig(): ConfigFile {
89
+ const configPerEnvironment: ConfigFile["configPerEnvironment"] = {};
90
+ for (const env of ALL_ENVIRONMENTS) {
91
+ configPerEnvironment[env] = {};
92
+ }
93
+ return { configPerEnvironment, activeEnvironment: "production" };
94
+ }
95
+
96
+ // Atomic: write to a sibling temp file, then rename into place.
97
+ // Readers either see the old file or the new file, never a truncated
98
+ // zero-byte snapshot (the window that `writeFileSync` exposes between
99
+ // open(O_TRUNC) and write).
100
+ //
101
+ // The temp suffix uses 16 bytes of crypto-random hex so the temp
102
+ // path is unguessable — a predictable name (pid + Date.now()) lets a
103
+ // co-located attacker pre-create a symlink at that path and trick
104
+ // us into clobbering an arbitrary file (CodeQL js/insecure-temporary-file).
105
+ // O_EXCL on open further refuses to follow a pre-existing entry.
106
+ private writeConfig(): void {
107
+ const tmp = `${this.configPath}.${crypto.randomBytes(16).toString("hex")}.tmp`;
108
+ const fd = fs.openSync(
109
+ tmp,
110
+ fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL,
111
+ 0o600,
112
+ );
113
+ try {
114
+ fs.writeFileSync(fd, JSON.stringify(this.config));
115
+ } finally {
116
+ fs.closeSync(fd);
117
+ }
118
+ fs.renameSync(tmp, this.configPath);
119
+ }
120
+
80
121
  public setOrganization(organizationName: string) {
81
122
  this.loadConfig();
82
123
  // TODO: Validate organization exists and user has access.
83
124
  const environment = this.getEnvironment();
84
125
  this.config.configPerEnvironment[environment].organization =
85
126
  organizationName;
86
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
127
+ this.writeConfig();
87
128
  }
88
129
 
89
130
  public setProject(projectName: string) {
@@ -91,7 +132,7 @@ export class ClientConfiguration {
91
132
  // TODO: Validate project exists and user has access.
92
133
  const environment = this.getEnvironment();
93
134
  this.config.configPerEnvironment[environment].project = projectName;
94
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
135
+ this.writeConfig();
95
136
  }
96
137
 
97
138
  public getOrganization() {
@@ -112,7 +153,7 @@ export class ClientConfiguration {
112
153
  this.config.configPerEnvironment[environment].isServiceAccountToken =
113
154
  !userToken;
114
155
  this.config.configPerEnvironment[environment].accessToken = accessToken;
115
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
156
+ this.writeConfig();
116
157
  }
117
158
 
118
159
  public getAuthenticationHeader() {
@@ -135,7 +176,7 @@ export class ClientConfiguration {
135
176
  const environment = this.getEnvironment();
136
177
  this.config.configPerEnvironment[environment].jwtAccessToken =
137
178
  jwtAccessToken;
138
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
179
+ this.writeConfig();
139
180
  }
140
181
 
141
182
  public getJwtAccessToken(): string | undefined {
@@ -154,7 +195,7 @@ export class ClientConfiguration {
154
195
  username,
155
196
  email,
156
197
  };
157
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
198
+ this.writeConfig();
158
199
  }
159
200
 
160
201
  public getVSCodeUser(): { username: string; email: string } | undefined {
@@ -167,7 +208,7 @@ export class ClientConfiguration {
167
208
  this.loadConfig();
168
209
  const environment = this.getEnvironment();
169
210
  this.config.configPerEnvironment[environment].refreshToken = refreshToken;
170
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
211
+ this.writeConfig();
171
212
  }
172
213
 
173
214
  public getRefreshToken(): string | undefined {
@@ -192,13 +233,13 @@ export class ClientConfiguration {
192
233
  this.loadConfig();
193
234
  const environment = this.getEnvironment();
194
235
  this.config.configPerEnvironment[environment] = {};
195
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
236
+ this.writeConfig();
196
237
  }
197
238
 
198
239
  public setEnvironment(environment: Environment) {
199
240
  this.loadConfig();
200
241
  this.config.activeEnvironment = environment;
201
- fs.writeFileSync(this.configPath, JSON.stringify(this.config));
242
+ this.writeConfig();
202
243
  }
203
244
 
204
245
  public getEnvironment() {
@@ -252,7 +293,7 @@ export class ClientConfiguration {
252
293
 
253
294
  console.log(kleur.green(ASCII_TITLE));
254
295
  logger.info(`Organization: ${kleur.green(organization || "Not set")}`);
255
- logger.info(`Project: ${kleur.green(project || "Not set")}`);
296
+ logger.info(`Environment: ${kleur.green(project || "Not set")}`);
256
297
  } else {
257
298
  logger.error("Failed to get status");
258
299
  logger.error(
@@ -1,10 +1,12 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { Command } from "commander";
2
3
  import { controlPlanesByEnv, Environment } from "../constants";
3
4
  import { createConnections } from "./connection/createconnections";
4
5
  import { addMember } from "./group/addmember";
5
6
  import { createGroup } from "./group/creategroup";
6
7
  import { createGroupAccessToken } from "./groupaccesstoken/createToken";
7
- import { createProject } from "./project/createproject";
8
+ import { createEnvironment } from "./environment/createenvironment";
9
+ import { warnProjectDeprecated } from "./legacy";
8
10
 
9
11
  export const registerAddCommands = (cli: Command, environment: Environment) => {
10
12
  const add = cli
@@ -12,14 +14,41 @@ export const registerAddCommands = (cli: Command, environment: Environment) => {
12
14
  .description("Add a resource")
13
15
  .argument("<resource>", "The resource to add");
14
16
 
17
+ const addEnvironmentAction = (environmentName: string, options: any) => {
18
+ createEnvironment(
19
+ controlPlanesByEnv[environment],
20
+ environmentName,
21
+ options.readmeFile,
22
+ options.replication,
23
+ options.debug,
24
+ options.yes,
25
+ );
26
+ };
27
+
28
+ add.command("environment")
29
+ .description("Add an environment.")
30
+ .argument("<environmentName>", "The name of the environment to create.")
31
+ .option("--debug")
32
+ .option("-y, --yes", "Skip confirmation.")
33
+ .option(
34
+ "--readmeFile <readmeFile>",
35
+ "The path to the readme file for the environment.",
36
+ )
37
+ .option(
38
+ "--replication <replicationCount>",
39
+ "The replication count (must be at least 1).",
40
+ parseInt,
41
+ )
42
+ .action(addEnvironmentAction);
43
+
15
44
  add.command("project")
16
- .description("Add a project.")
17
- .argument("<projectName>", "The name of the project to create.")
45
+ .description("[deprecated] Alias for 'add environment'.")
46
+ .argument("<projectName>", "The name of the environment to create.")
18
47
  .option("--debug")
19
48
  .option("-y, --yes", "Skip confirmation.")
20
49
  .option(
21
50
  "--readmeFile <readmeFile>",
22
- "The path to the readme file for the project.",
51
+ "The path to the readme file for the environment.",
23
52
  )
24
53
  .option(
25
54
  "--replication <replicationCount>",
@@ -27,14 +56,8 @@ export const registerAddCommands = (cli: Command, environment: Environment) => {
27
56
  parseInt,
28
57
  )
29
58
  .action((projectName, options) => {
30
- createProject(
31
- controlPlanesByEnv[environment],
32
- projectName,
33
- options.readmeFile,
34
- options.replication,
35
- options.debug,
36
- options.yes,
37
- );
59
+ warnProjectDeprecated("add environment");
60
+ addEnvironmentAction(projectName, options);
38
61
  });
39
62
 
40
63
  add.command("connection")