@twin.org/node-core 0.0.2-next.9 → 0.0.3-next.10

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 (195) hide show
  1. package/README.md +1 -1
  2. package/dist/es/builders/engineEnvBuilder.js +1132 -0
  3. package/dist/es/builders/engineEnvBuilder.js.map +1 -0
  4. package/dist/es/builders/engineServerEnvBuilder.js +206 -0
  5. package/dist/es/builders/engineServerEnvBuilder.js.map +1 -0
  6. package/dist/es/builders/extensionsBuilder.js +109 -0
  7. package/dist/es/builders/extensionsBuilder.js.map +1 -0
  8. package/dist/es/cli.js +255 -0
  9. package/dist/es/cli.js.map +1 -0
  10. package/dist/es/commands/bootstrapLegacy.js +175 -0
  11. package/dist/es/commands/bootstrapLegacy.js.map +1 -0
  12. package/dist/es/commands/help.js +85 -0
  13. package/dist/es/commands/help.js.map +1 -0
  14. package/dist/es/commands/identityCreate.js +310 -0
  15. package/dist/es/commands/identityCreate.js.map +1 -0
  16. package/dist/es/commands/identityImports.js +76 -0
  17. package/dist/es/commands/identityImports.js.map +1 -0
  18. package/dist/es/commands/identityVerifiableCredentialCreate.js +140 -0
  19. package/dist/es/commands/identityVerifiableCredentialCreate.js.map +1 -0
  20. package/dist/es/commands/identityVerificationMethodCreate.js +208 -0
  21. package/dist/es/commands/identityVerificationMethodCreate.js.map +1 -0
  22. package/dist/es/commands/identityVerificationMethodImport.js +120 -0
  23. package/dist/es/commands/identityVerificationMethodImport.js.map +1 -0
  24. package/dist/es/commands/nodeSetIdentity.js +51 -0
  25. package/dist/es/commands/nodeSetIdentity.js.map +1 -0
  26. package/dist/es/commands/nodeSetTenant.js +49 -0
  27. package/dist/es/commands/nodeSetTenant.js.map +1 -0
  28. package/dist/es/commands/tenantCreate.js +120 -0
  29. package/dist/es/commands/tenantCreate.js.map +1 -0
  30. package/dist/es/commands/tenantImport.js +78 -0
  31. package/dist/es/commands/tenantImport.js.map +1 -0
  32. package/dist/es/commands/userCreate.js +197 -0
  33. package/dist/es/commands/userCreate.js.map +1 -0
  34. package/dist/es/commands/vaultKeyCreate.js +185 -0
  35. package/dist/es/commands/vaultKeyCreate.js.map +1 -0
  36. package/dist/es/commands/vaultKeyImport.js +98 -0
  37. package/dist/es/commands/vaultKeyImport.js.map +1 -0
  38. package/dist/es/defaults.js +28 -0
  39. package/dist/es/defaults.js.map +1 -0
  40. package/dist/es/index.js +27 -0
  41. package/dist/es/index.js.map +1 -0
  42. package/dist/es/models/ICacheMetadata.js +4 -0
  43. package/dist/es/models/ICacheMetadata.js.map +1 -0
  44. package/dist/es/models/ICliArgs.js +4 -0
  45. package/dist/es/models/ICliArgs.js.map +1 -0
  46. package/dist/es/models/ICliCommand.js +2 -0
  47. package/dist/es/models/ICliCommand.js.map +1 -0
  48. package/dist/es/models/ICliCommandDefinition.js +2 -0
  49. package/dist/es/models/ICliCommandDefinition.js.map +1 -0
  50. package/dist/es/models/ICliCommandDefinitionParam.js +2 -0
  51. package/dist/es/models/ICliCommandDefinitionParam.js.map +1 -0
  52. package/dist/es/models/IEngineEnvironmentVariables.js +4 -0
  53. package/dist/es/models/IEngineEnvironmentVariables.js.map +1 -0
  54. package/dist/es/models/IEngineServerEnvironmentVariables.js +2 -0
  55. package/dist/es/models/IEngineServerEnvironmentVariables.js.map +1 -0
  56. package/dist/es/models/IModuleProtocol.js +2 -0
  57. package/dist/es/models/IModuleProtocol.js.map +1 -0
  58. package/dist/es/models/INodeEngineConfig.js +2 -0
  59. package/dist/es/models/INodeEngineConfig.js.map +1 -0
  60. package/dist/es/models/INodeEngineState.js +2 -0
  61. package/dist/es/models/INodeEngineState.js.map +1 -0
  62. package/dist/es/models/INodeEnvironmentVariables.js +2 -0
  63. package/dist/es/models/INodeEnvironmentVariables.js.map +1 -0
  64. package/dist/es/models/INodeOptions.js +2 -0
  65. package/dist/es/models/INodeOptions.js.map +1 -0
  66. package/dist/es/models/IProtocolHandlerResult.js +4 -0
  67. package/dist/es/models/IProtocolHandlerResult.js.map +1 -0
  68. package/dist/es/models/cliCommandParamType.js +4 -0
  69. package/dist/es/models/cliCommandParamType.js.map +1 -0
  70. package/dist/es/models/moduleProtocol.js +29 -0
  71. package/dist/es/models/moduleProtocol.js.map +1 -0
  72. package/dist/es/models/nodeExtensionMethods.js +2 -0
  73. package/dist/es/models/nodeExtensionMethods.js.map +1 -0
  74. package/dist/es/node.js +285 -0
  75. package/dist/es/node.js.map +1 -0
  76. package/dist/es/start.js +128 -0
  77. package/dist/es/start.js.map +1 -0
  78. package/dist/es/utils.js +397 -0
  79. package/dist/es/utils.js.map +1 -0
  80. package/dist/types/builders/engineEnvBuilder.d.ts +6 -2
  81. package/dist/types/builders/engineServerEnvBuilder.d.ts +7 -3
  82. package/dist/types/builders/extensionsBuilder.d.ts +32 -0
  83. package/dist/types/cli.d.ts +66 -0
  84. package/dist/types/commands/bootstrapLegacy.d.ts +66 -0
  85. package/dist/types/commands/help.d.ts +23 -0
  86. package/dist/types/commands/identityCreate.d.ts +39 -0
  87. package/dist/types/commands/identityImports.d.ts +24 -0
  88. package/dist/types/commands/identityVerifiableCredentialCreate.d.ts +43 -0
  89. package/dist/types/commands/identityVerificationMethodCreate.d.ts +47 -0
  90. package/dist/types/commands/identityVerificationMethodImport.d.ts +31 -0
  91. package/dist/types/commands/nodeSetIdentity.d.ts +22 -0
  92. package/dist/types/commands/nodeSetTenant.d.ts +22 -0
  93. package/dist/types/commands/tenantCreate.d.ts +35 -0
  94. package/dist/types/commands/tenantImport.d.ts +24 -0
  95. package/dist/types/commands/userCreate.d.ts +46 -0
  96. package/dist/types/commands/vaultKeyCreate.d.ts +43 -0
  97. package/dist/types/commands/vaultKeyImport.d.ts +28 -0
  98. package/dist/types/defaults.d.ts +16 -0
  99. package/dist/types/index.d.ts +24 -11
  100. package/dist/types/models/ICacheMetadata.d.ts +17 -0
  101. package/dist/types/models/ICliArgs.d.ts +20 -0
  102. package/dist/types/models/ICliCommand.d.ts +17 -0
  103. package/dist/types/models/ICliCommandDefinition.d.ts +46 -0
  104. package/dist/types/models/ICliCommandDefinitionParam.d.ts +35 -0
  105. package/dist/types/models/IEngineEnvironmentVariables.d.ts +154 -37
  106. package/dist/types/models/IEngineServerEnvironmentVariables.d.ts +12 -3
  107. package/dist/types/models/IModuleProtocol.d.ts +18 -0
  108. package/dist/types/models/INodeEngineConfig.d.ts +6 -0
  109. package/dist/types/models/INodeEngineState.d.ts +14 -0
  110. package/dist/types/models/INodeEnvironmentVariables.d.ts +17 -15
  111. package/dist/types/models/INodeOptions.d.ts +14 -3
  112. package/dist/types/models/IProtocolHandlerResult.d.ts +13 -0
  113. package/dist/types/models/cliCommandParamType.d.ts +4 -0
  114. package/dist/types/models/moduleProtocol.d.ts +29 -0
  115. package/dist/types/models/nodeExtensionMethods.d.ts +27 -0
  116. package/dist/types/node.d.ts +21 -7
  117. package/dist/types/start.d.ts +25 -0
  118. package/dist/types/utils.d.ts +83 -6
  119. package/docs/changelog.md +241 -0
  120. package/docs/detailed-guide.md +129 -0
  121. package/docs/reference/functions/buildConfiguration.md +2 -2
  122. package/docs/reference/functions/buildEngineConfiguration.md +8 -2
  123. package/docs/reference/functions/buildEngineServerConfiguration.md +9 -3
  124. package/docs/reference/functions/constructCliCommand.md +27 -0
  125. package/docs/reference/functions/createModuleImportUrl.md +21 -0
  126. package/docs/reference/functions/directoryExists.md +19 -0
  127. package/docs/reference/functions/executeCommand.md +29 -0
  128. package/docs/reference/functions/extensionsConfiguration.md +25 -0
  129. package/docs/reference/functions/extensionsInitialiseEngine.md +25 -0
  130. package/docs/reference/functions/extensionsInitialiseEngineServer.md +31 -0
  131. package/docs/reference/functions/getEnvDefaults.md +19 -0
  132. package/docs/reference/functions/getExtensionsCacheDir.md +31 -0
  133. package/docs/reference/functions/getFiles.md +19 -0
  134. package/docs/reference/functions/getSubFolders.md +19 -0
  135. package/docs/reference/functions/handleHttpsProtocol.md +49 -0
  136. package/docs/reference/functions/handleNpmProtocol.md +31 -0
  137. package/docs/reference/functions/hashUrl.md +19 -0
  138. package/docs/reference/functions/initCli.md +27 -0
  139. package/docs/reference/functions/isCacheExpired.md +31 -0
  140. package/docs/reference/functions/overrideModuleImport.md +8 -2
  141. package/docs/reference/functions/parseCommandLineArgs.md +19 -0
  142. package/docs/reference/functions/parseModuleProtocol.md +19 -0
  143. package/docs/reference/functions/processEnvOptions.md +27 -0
  144. package/docs/reference/functions/registerCommands.md +9 -0
  145. package/docs/reference/functions/resolvePackageEntryPoint.md +32 -0
  146. package/docs/reference/functions/run.md +9 -3
  147. package/docs/reference/functions/shutdownExtensions.md +25 -0
  148. package/docs/reference/functions/start.md +17 -5
  149. package/docs/reference/functions/substituteEnvOptions.md +25 -0
  150. package/docs/reference/index.md +47 -10
  151. package/docs/reference/interfaces/ICacheMetadata.md +27 -0
  152. package/docs/reference/interfaces/ICliArgs.md +35 -0
  153. package/docs/reference/interfaces/ICliCommand.md +23 -0
  154. package/docs/reference/interfaces/ICliCommandDefinition.md +101 -0
  155. package/docs/reference/interfaces/ICliCommandDefinitionParam.md +65 -0
  156. package/docs/reference/interfaces/IEngineEnvironmentVariables.md +303 -60
  157. package/docs/reference/interfaces/IEngineServerEnvironmentVariables.md +1737 -5
  158. package/docs/reference/interfaces/IModuleProtocol.md +27 -0
  159. package/docs/reference/interfaces/INodeEngineConfig.md +7 -0
  160. package/docs/reference/interfaces/INodeEngineState.md +23 -0
  161. package/docs/reference/interfaces/INodeEnvironmentVariables.md +599 -198
  162. package/docs/reference/interfaces/INodeOptions.md +27 -3
  163. package/docs/reference/interfaces/IProtocolHandlerResult.md +19 -0
  164. package/docs/reference/type-aliases/CliCommandParamType.md +5 -0
  165. package/docs/reference/type-aliases/ModuleProtocol.md +5 -0
  166. package/docs/reference/type-aliases/NodeExtensionInitialiseEngineMethod.md +18 -0
  167. package/docs/reference/type-aliases/NodeExtensionInitialiseEngineServerMethod.md +24 -0
  168. package/docs/reference/type-aliases/NodeExtensionInitialiseMethod.md +23 -0
  169. package/docs/reference/type-aliases/NodeExtensionShutdownMethod.md +10 -0
  170. package/docs/reference/variables/ATTESTATION_VERIFICATION_METHOD_ID.md +3 -0
  171. package/docs/reference/variables/AUTH_SIGNING_KEY_ID.md +3 -0
  172. package/docs/reference/variables/BLOB_STORAGE_ENCRYPTION_KEY_ID.md +3 -0
  173. package/docs/reference/variables/CONTEXT_ID_HANDLER_FEATURE_DID.md +3 -0
  174. package/docs/reference/variables/CONTEXT_ID_HANDLER_FEATURE_TENANT.md +3 -0
  175. package/docs/reference/variables/IMMUTABLE_PROOF_VERIFICATION_METHOD_ID.md +3 -0
  176. package/docs/reference/variables/ModuleProtocol.md +37 -0
  177. package/docs/reference/variables/SYNCHRONISED_STORAGE_BLOB_STORAGE_ENCRYPTION_KEY_ID.md +3 -0
  178. package/docs/reference/variables/VC_AUTHENTICATION_VERIFICATION_METHOD_ID.md +3 -0
  179. package/locales/en.json +479 -28
  180. package/package.json +29 -9
  181. package/dist/cjs/index.cjs +0 -1910
  182. package/dist/esm/index.mjs +0 -1870
  183. package/dist/types/bootstrap.d.ts +0 -59
  184. package/dist/types/models/nodeFeatures.d.ts +0 -21
  185. package/dist/types/server.d.ts +0 -17
  186. package/docs/reference/functions/bootstrap.md +0 -29
  187. package/docs/reference/functions/bootstrapAuth.md +0 -35
  188. package/docs/reference/functions/bootstrapBlobEncryption.md +0 -35
  189. package/docs/reference/functions/bootstrapImmutableProofMethod.md +0 -35
  190. package/docs/reference/functions/bootstrapNodeIdentity.md +0 -35
  191. package/docs/reference/functions/bootstrapNodeUser.md +0 -35
  192. package/docs/reference/functions/bootstrapSynchronisedStorage.md +0 -35
  193. package/docs/reference/functions/getFeatures.md +0 -19
  194. package/docs/reference/type-aliases/NodeFeatures.md +0 -5
  195. package/docs/reference/variables/NodeFeatures.md +0 -25
@@ -0,0 +1,120 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { TenantIdHelper } from "@twin.org/api-tenant-processor";
4
+ import { CLIDisplay, CLIUtils } from "@twin.org/cli-core";
5
+ import { ComponentFactory, GeneralError, Guards, I18n, Is } from "@twin.org/core";
6
+ const COMMAND_NAME = "tenant-create";
7
+ /**
8
+ * Get the command definition parameters.
9
+ * @param commandDefinitions The registered command definitions.
10
+ */
11
+ export function getCommandDefinitionTenantCreate(commandDefinitions) {
12
+ commandDefinitions[COMMAND_NAME] = {
13
+ command: COMMAND_NAME,
14
+ description: I18n.formatMessage("node.cli.commands.tenant-create.description"),
15
+ example: I18n.formatMessage("node.cli.commands.tenant-create.example"),
16
+ requiresTenantId: false,
17
+ params: [
18
+ {
19
+ key: "tenant-id",
20
+ type: "string",
21
+ extendedType: "hex(32)",
22
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.tenant-id.description"),
23
+ required: false
24
+ },
25
+ {
26
+ key: "api-key",
27
+ type: "string",
28
+ extendedType: "hex(32)",
29
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.api-key.description"),
30
+ required: false
31
+ },
32
+ {
33
+ key: "label",
34
+ type: "string",
35
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.label.description"),
36
+ required: false
37
+ },
38
+ {
39
+ key: "load-env",
40
+ type: "string",
41
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.load-env.description"),
42
+ required: false
43
+ },
44
+ {
45
+ key: "output-json",
46
+ type: "string",
47
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.output-json.description"),
48
+ required: false
49
+ },
50
+ {
51
+ key: "output-env",
52
+ type: "string",
53
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.output-env.description"),
54
+ required: false
55
+ },
56
+ {
57
+ key: "output-env-prefix",
58
+ type: "string",
59
+ description: I18n.formatMessage("node.cli.commands.tenant-create.params.output-env-prefix.description"),
60
+ required: false
61
+ }
62
+ ],
63
+ action: async (engineCore, envVars, params) => tenantCreate(engineCore, envVars, params)
64
+ };
65
+ }
66
+ /**
67
+ * Command for creating a tenant.
68
+ * @param engineCore The engine core.
69
+ * @param envVars The environment variables for the node.
70
+ * @param params The parameters for the command.
71
+ * @param params.apiKey The api key to add.
72
+ * @param params.tenantId The tenant ID to add the api key to.
73
+ * @param params.label The label for the api key.
74
+ * @param params.outputJson The output .json file to store the command output.
75
+ * @param params.outputEnv The output .env file to store the command output.
76
+ * @param params.outputEnvPrefix The prefix to use for variables in the output .env file.
77
+ * @returns The created tenant details.
78
+ */
79
+ export async function tenantCreate(engineCore, envVars, params) {
80
+ if (Is.stringValue(params.tenantId)) {
81
+ Guards.stringHexLength("tenantCreate", "tenant-id", params.tenantId, 32);
82
+ }
83
+ if (Is.stringValue(params.apiKey)) {
84
+ Guards.stringHexLength("tenantCreate", "api-key", params.apiKey, 32);
85
+ }
86
+ const tenantAdminServiceComponentType = engineCore.getRegisteredInstanceTypeOptional("tenantAdminComponent");
87
+ if (!Is.stringValue(tenantAdminServiceComponentType)) {
88
+ throw new GeneralError("tenantCreate", "tenantAdminComponentNotRegistered");
89
+ }
90
+ const tenantAdminService = ComponentFactory.get(tenantAdminServiceComponentType);
91
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.tenant-create.labels.creating"));
92
+ const apiKey = params.apiKey ?? TenantIdHelper.generateApiKey();
93
+ const tenantId = params.tenantId ?? TenantIdHelper.generateTenantId();
94
+ const label = params.label ?? "";
95
+ await tenantAdminService.set({
96
+ id: tenantId,
97
+ apiKey,
98
+ dateCreated: new Date(Date.now()).toISOString(),
99
+ label
100
+ });
101
+ CLIDisplay.break();
102
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.tenant-create.labels.tenantId"), tenantId);
103
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.tenant-create.labels.apiKey"), apiKey);
104
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.tenant-create.labels.label"), label);
105
+ CLIDisplay.break();
106
+ const json = { apiKey, tenantId, label };
107
+ if (Is.stringValue(params.outputJson)) {
108
+ await CLIUtils.writeJsonFile(params.outputJson, json, false);
109
+ }
110
+ if (Is.stringValue(params.outputEnv)) {
111
+ await CLIUtils.writeEnvFile(params.outputEnv, [
112
+ `${params.outputEnvPrefix}API_KEY="${apiKey}"`,
113
+ `${params.outputEnvPrefix}TENANT_ID="${tenantId}"`,
114
+ `${params.outputEnvPrefix}LABEL="${label}"`
115
+ ], false);
116
+ }
117
+ CLIDisplay.done();
118
+ return json;
119
+ }
120
+ //# sourceMappingURL=tenantCreate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenantCreate.js","sourceRoot":"","sources":["../../../src/commands/tenantCreate.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { TenantIdHelper, type ITenantAdminComponent } from \"@twin.org/api-tenant-processor\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { ComponentFactory, GeneralError, Guards, I18n, Is } from \"@twin.org/core\";\nimport type { IEngineCore } from \"@twin.org/engine-models\";\nimport type { ICliCommandDefinition } from \"../models/ICliCommandDefinition.js\";\nimport type { INodeEnvironmentVariables } from \"../models/INodeEnvironmentVariables.js\";\n\nconst COMMAND_NAME = \"tenant-create\";\n\n/**\n * Get the command definition parameters.\n * @param commandDefinitions The registered command definitions.\n */\nexport function getCommandDefinitionTenantCreate(commandDefinitions: {\n\t[id: string]: ICliCommandDefinition;\n}): void {\n\tcommandDefinitions[COMMAND_NAME] = {\n\t\tcommand: COMMAND_NAME,\n\t\tdescription: I18n.formatMessage(\"node.cli.commands.tenant-create.description\"),\n\t\texample: I18n.formatMessage(\"node.cli.commands.tenant-create.example\"),\n\t\trequiresTenantId: false,\n\t\tparams: [\n\t\t\t{\n\t\t\t\tkey: \"tenant-id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"hex(32)\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-create.params.tenant-id.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"api-key\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"hex(32)\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-create.params.api-key.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"label\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\"node.cli.commands.tenant-create.params.label.description\"),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"load-env\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-create.params.load-env.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"output-json\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-create.params.output-json.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"output-env\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-create.params.output-env.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"output-env-prefix\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-create.params.output-env-prefix.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t}\n\t\t],\n\t\taction: async (engineCore, envVars, params) => tenantCreate(engineCore, envVars, params)\n\t};\n}\n\n/**\n * Command for creating a tenant.\n * @param engineCore The engine core.\n * @param envVars The environment variables for the node.\n * @param params The parameters for the command.\n * @param params.apiKey The api key to add.\n * @param params.tenantId The tenant ID to add the api key to.\n * @param params.label The label for the api key.\n * @param params.outputJson The output .json file to store the command output.\n * @param params.outputEnv The output .env file to store the command output.\n * @param params.outputEnvPrefix The prefix to use for variables in the output .env file.\n * @returns The created tenant details.\n */\nexport async function tenantCreate(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tparams: {\n\t\tapiKey?: string;\n\t\ttenantId?: string;\n\t\tlabel?: string;\n\t\toutputJson?: string;\n\t\toutputEnv?: string;\n\t\toutputEnvPrefix?: string;\n\t}\n): Promise<{ apiKey: string; tenantId: string; label: string }> {\n\tif (Is.stringValue(params.tenantId)) {\n\t\tGuards.stringHexLength(\"tenantCreate\", \"tenant-id\", params.tenantId, 32);\n\t}\n\n\tif (Is.stringValue(params.apiKey)) {\n\t\tGuards.stringHexLength(\"tenantCreate\", \"api-key\", params.apiKey, 32);\n\t}\n\n\tconst tenantAdminServiceComponentType =\n\t\tengineCore.getRegisteredInstanceTypeOptional(\"tenantAdminComponent\");\n\n\tif (!Is.stringValue(tenantAdminServiceComponentType)) {\n\t\tthrow new GeneralError(\"tenantCreate\", \"tenantAdminComponentNotRegistered\");\n\t}\n\n\tconst tenantAdminService = ComponentFactory.get<ITenantAdminComponent>(\n\t\ttenantAdminServiceComponentType\n\t);\n\n\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.tenant-create.labels.creating\"));\n\n\tconst apiKey = params.apiKey ?? TenantIdHelper.generateApiKey();\n\tconst tenantId = params.tenantId ?? TenantIdHelper.generateTenantId();\n\tconst label = params.label ?? \"\";\n\n\tawait tenantAdminService.set({\n\t\tid: tenantId,\n\t\tapiKey,\n\t\tdateCreated: new Date(Date.now()).toISOString(),\n\t\tlabel\n\t});\n\n\tCLIDisplay.break();\n\tCLIDisplay.value(I18n.formatMessage(\"node.cli.commands.tenant-create.labels.tenantId\"), tenantId);\n\tCLIDisplay.value(I18n.formatMessage(\"node.cli.commands.tenant-create.labels.apiKey\"), apiKey);\n\tCLIDisplay.value(I18n.formatMessage(\"node.cli.commands.tenant-create.labels.label\"), label);\n\tCLIDisplay.break();\n\n\tconst json = { apiKey, tenantId, label };\n\tif (Is.stringValue(params.outputJson)) {\n\t\tawait CLIUtils.writeJsonFile(params.outputJson, json, false);\n\t}\n\n\tif (Is.stringValue(params.outputEnv)) {\n\t\tawait CLIUtils.writeEnvFile(\n\t\t\tparams.outputEnv,\n\t\t\t[\n\t\t\t\t`${params.outputEnvPrefix}API_KEY=\"${apiKey}\"`,\n\t\t\t\t`${params.outputEnvPrefix}TENANT_ID=\"${tenantId}\"`,\n\t\t\t\t`${params.outputEnvPrefix}LABEL=\"${label}\"`\n\t\t\t],\n\t\t\tfalse\n\t\t);\n\t}\n\n\tCLIDisplay.done();\n\n\treturn json;\n}\n"]}
@@ -0,0 +1,78 @@
1
+ import { CLIDisplay } from "@twin.org/cli-core";
2
+ import { ComponentFactory, GeneralError, Guards, I18n, Is } from "@twin.org/core";
3
+ const COMMAND_NAME = "tenant-import";
4
+ /**
5
+ * Get the command definition parameters.
6
+ * @param commandDefinitions The registered command definitions.
7
+ */
8
+ export function getCommandDefinitionTenantImport(commandDefinitions) {
9
+ commandDefinitions[COMMAND_NAME] = {
10
+ command: COMMAND_NAME,
11
+ description: I18n.formatMessage("node.cli.commands.tenant-import.description"),
12
+ example: I18n.formatMessage("node.cli.commands.tenant-import.example"),
13
+ requiresTenantId: false,
14
+ params: [
15
+ {
16
+ key: "tenant-id",
17
+ type: "string",
18
+ extendedType: "hex(32)",
19
+ description: I18n.formatMessage("node.cli.commands.tenant-import.params.tenant-id.description"),
20
+ required: true
21
+ },
22
+ {
23
+ key: "api-key",
24
+ type: "string",
25
+ extendedType: "hex(32)",
26
+ description: I18n.formatMessage("node.cli.commands.tenant-import.params.api-key.description"),
27
+ required: true
28
+ },
29
+ {
30
+ key: "label",
31
+ type: "string",
32
+ description: I18n.formatMessage("node.cli.commands.tenant-import.params.label.description"),
33
+ required: false
34
+ },
35
+ {
36
+ key: "load-env",
37
+ type: "string",
38
+ description: I18n.formatMessage("node.cli.commands.tenant-import.params.load-env.description"),
39
+ required: false
40
+ }
41
+ ],
42
+ action: async (engineCore, envVars, params) => tenantImport(engineCore, envVars, params)
43
+ };
44
+ }
45
+ /**
46
+ * Command for importing a tenant.
47
+ * @param engineCore The engine core.
48
+ * @param envVars The environment variables for the node.
49
+ * @param params The parameters for the command.
50
+ * @param params.apiKey The api key to import.
51
+ * @param params.tenantId The tenant ID to import the api key to.
52
+ * @param params.label The label for the api key.
53
+ */
54
+ export async function tenantImport(engineCore, envVars, params) {
55
+ Guards.stringHexLength("tenantImport", "tenant-id", params.tenantId, 32);
56
+ Guards.stringHexLength("tenantImport", "api-key", params.apiKey, 32);
57
+ const tenantAdminServiceComponentType = engineCore.getRegisteredInstanceTypeOptional("tenantAdminComponent");
58
+ if (!Is.stringValue(tenantAdminServiceComponentType)) {
59
+ throw new GeneralError("tenantImport", "tenantAdminComponentNotRegistered");
60
+ }
61
+ const tenantAdminService = ComponentFactory.get(tenantAdminServiceComponentType);
62
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.tenant-import.labels.importing"));
63
+ CLIDisplay.spinnerStart();
64
+ const apiKey = params.apiKey;
65
+ const tenantId = params.tenantId;
66
+ const label = params.label ?? "";
67
+ await tenantAdminService.set({
68
+ id: tenantId,
69
+ apiKey,
70
+ dateCreated: new Date(Date.now()).toISOString(),
71
+ label
72
+ });
73
+ CLIDisplay.spinnerStop();
74
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.tenant-import.labels.imported"));
75
+ CLIDisplay.break();
76
+ CLIDisplay.done();
77
+ }
78
+ //# sourceMappingURL=tenantImport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenantImport.js","sourceRoot":"","sources":["../../../src/commands/tenantImport.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenantAdminComponent } from \"@twin.org/api-tenant-processor\";\nimport { CLIDisplay } from \"@twin.org/cli-core\";\nimport { ComponentFactory, GeneralError, Guards, I18n, Is } from \"@twin.org/core\";\nimport type { IEngineCore } from \"@twin.org/engine-models\";\nimport type { ICliCommandDefinition } from \"../models/ICliCommandDefinition.js\";\nimport type { INodeEnvironmentVariables } from \"../models/INodeEnvironmentVariables.js\";\n\nconst COMMAND_NAME = \"tenant-import\";\n\n/**\n * Get the command definition parameters.\n * @param commandDefinitions The registered command definitions.\n */\nexport function getCommandDefinitionTenantImport(commandDefinitions: {\n\t[id: string]: ICliCommandDefinition;\n}): void {\n\tcommandDefinitions[COMMAND_NAME] = {\n\t\tcommand: COMMAND_NAME,\n\t\tdescription: I18n.formatMessage(\"node.cli.commands.tenant-import.description\"),\n\t\texample: I18n.formatMessage(\"node.cli.commands.tenant-import.example\"),\n\t\trequiresTenantId: false,\n\t\tparams: [\n\t\t\t{\n\t\t\t\tkey: \"tenant-id\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"hex(32)\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-import.params.tenant-id.description\"\n\t\t\t\t),\n\t\t\t\trequired: true\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"api-key\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"hex(32)\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-import.params.api-key.description\"\n\t\t\t\t),\n\t\t\t\trequired: true\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"label\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\"node.cli.commands.tenant-import.params.label.description\"),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"load-env\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.tenant-import.params.load-env.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t}\n\t\t],\n\t\taction: async (engineCore, envVars, params) => tenantImport(engineCore, envVars, params)\n\t};\n}\n\n/**\n * Command for importing a tenant.\n * @param engineCore The engine core.\n * @param envVars The environment variables for the node.\n * @param params The parameters for the command.\n * @param params.apiKey The api key to import.\n * @param params.tenantId The tenant ID to import the api key to.\n * @param params.label The label for the api key.\n */\nexport async function tenantImport(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tparams: {\n\t\tapiKey?: string;\n\t\ttenantId?: string;\n\t\tlabel?: string;\n\t}\n): Promise<void> {\n\tGuards.stringHexLength(\"tenantImport\", \"tenant-id\", params.tenantId, 32);\n\tGuards.stringHexLength(\"tenantImport\", \"api-key\", params.apiKey, 32);\n\n\tconst tenantAdminServiceComponentType =\n\t\tengineCore.getRegisteredInstanceTypeOptional(\"tenantAdminComponent\");\n\n\tif (!Is.stringValue(tenantAdminServiceComponentType)) {\n\t\tthrow new GeneralError(\"tenantImport\", \"tenantAdminComponentNotRegistered\");\n\t}\n\n\tconst tenantAdminService = ComponentFactory.get<ITenantAdminComponent>(\n\t\ttenantAdminServiceComponentType\n\t);\n\n\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.tenant-import.labels.importing\"));\n\tCLIDisplay.spinnerStart();\n\n\tconst apiKey = params.apiKey;\n\tconst tenantId = params.tenantId;\n\tconst label = params.label ?? \"\";\n\n\tawait tenantAdminService.set({\n\t\tid: tenantId,\n\t\tapiKey,\n\t\tdateCreated: new Date(Date.now()).toISOString(),\n\t\tlabel\n\t});\n\tCLIDisplay.spinnerStop();\n\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.tenant-import.labels.imported\"));\n\n\tCLIDisplay.break();\n\n\tCLIDisplay.done();\n}\n"]}
@@ -0,0 +1,197 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { PasswordHelper } from "@twin.org/api-auth-entity-storage-service";
4
+ import { CLIDisplay, CLIUtils } from "@twin.org/cli-core";
5
+ import { Converter, GeneralError, Guards, I18n, Is, RandomHelper } from "@twin.org/core";
6
+ import { PasswordGenerator } from "@twin.org/crypto";
7
+ import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
8
+ import { Did, IdentityProfileConnectorFactory } from "@twin.org/identity-models";
9
+ const COMMAND_NAME = "user-create";
10
+ /**
11
+ * Get the command definition parameters.
12
+ * @param commandDefinitions The registered command definitions.
13
+ */
14
+ export function getCommandDefinitionUserCreate(commandDefinitions) {
15
+ commandDefinitions[COMMAND_NAME] = {
16
+ command: COMMAND_NAME,
17
+ description: I18n.formatMessage("node.cli.commands.user-create.description"),
18
+ example: I18n.formatMessage("node.cli.commands.user-create.example"),
19
+ params: [
20
+ {
21
+ key: "user-identity",
22
+ type: "string",
23
+ extendedType: "DID",
24
+ description: I18n.formatMessage("node.cli.commands.user-create.params.user-identity.description")
25
+ },
26
+ {
27
+ key: "organization-identity",
28
+ type: "string",
29
+ extendedType: "DID",
30
+ description: I18n.formatMessage("node.cli.commands.user-create.params.organization-identity.description")
31
+ },
32
+ {
33
+ key: "email",
34
+ type: "string",
35
+ extendedType: "email",
36
+ description: I18n.formatMessage("node.cli.commands.user-create.params.email.description")
37
+ },
38
+ {
39
+ key: "password",
40
+ type: "string",
41
+ description: I18n.formatMessage("node.cli.commands.user-create.params.password.description"),
42
+ required: false
43
+ },
44
+ {
45
+ key: "given-name",
46
+ type: "string",
47
+ description: I18n.formatMessage("node.cli.commands.user-create.params.given-name.description"),
48
+ required: false
49
+ },
50
+ {
51
+ key: "family-name",
52
+ type: "string",
53
+ description: I18n.formatMessage("node.cli.commands.user-create.params.family-name.description"),
54
+ required: false
55
+ },
56
+ {
57
+ key: "overwrite-mode",
58
+ type: "string",
59
+ description: I18n.formatMessage("node.cli.commands.user-create.params.overwrite-mode.description"),
60
+ options: ["skip", "overwrite", "error"],
61
+ defaultValue: "skip",
62
+ required: false
63
+ },
64
+ {
65
+ key: "load-env",
66
+ type: "string",
67
+ description: I18n.formatMessage("node.cli.commands.user-create.params.load-env.description"),
68
+ required: false
69
+ },
70
+ {
71
+ key: "output-json",
72
+ type: "string",
73
+ description: I18n.formatMessage("node.cli.commands.user-create.params.output-json.description"),
74
+ required: false
75
+ },
76
+ {
77
+ key: "output-env",
78
+ type: "string",
79
+ description: I18n.formatMessage("node.cli.commands.user-create.params.output-env.description"),
80
+ required: false
81
+ },
82
+ {
83
+ key: "output-env-prefix",
84
+ type: "string",
85
+ description: I18n.formatMessage("node.cli.commands.user-create.params.output-env-prefix.description"),
86
+ required: false
87
+ }
88
+ ],
89
+ action: async (engineCore, envVars, params) => userCreate(engineCore, envVars, params)
90
+ };
91
+ }
92
+ /**
93
+ * Command for creating a user.
94
+ * @param engineCore The engine core.
95
+ * @param envVars The environment variables for the node.
96
+ * @param params The parameters for the command.
97
+ * @param params.userIdentity The DID for the user.
98
+ * @param params.organizationIdentity The organization DID for the user.
99
+ * @param params.email The email for the user.
100
+ * @param params.password The password for the user.
101
+ * @param params.givenName The given name for the user.
102
+ * @param params.familyName The family name for the user.
103
+ * @param params.overwriteMode The mode to use when a user with the same identity already exists.
104
+ * @param params.outputJson The output .json file to store the command output.
105
+ * @param params.outputEnv The output .env file to store the command output.
106
+ * @param params.outputEnvPrefix The prefix to use for variables in the output .env file.
107
+ * @returns The created user details or undefined if skipped.
108
+ */
109
+ export async function userCreate(engineCore, envVars, params) {
110
+ Did.guard("userCreate", "user-identity", params.userIdentity);
111
+ Did.guard("userCreate", "organization-identity", params.organizationIdentity);
112
+ Guards.email("userCreate", "email", params.email);
113
+ if (Is.stringValue(params.password) && params.password.length < 16) {
114
+ throw new GeneralError("userCreate", "passwordTooShort", { minLength: 16 });
115
+ }
116
+ const defaultIdentityProfileConnectorType = engineCore.getRegisteredInstanceType("identityProfileConnector");
117
+ const identityProfileConnector = IdentityProfileConnectorFactory.get(defaultIdentityProfileConnectorType);
118
+ const authUserEntityStorage = EntityStorageConnectorFactory.get("authentication-user");
119
+ let createUser = true;
120
+ let existingUser;
121
+ try {
122
+ existingUser = await authUserEntityStorage.get(params.userIdentity, "identity");
123
+ }
124
+ catch { }
125
+ if (!Is.empty(existingUser)) {
126
+ if (params.overwriteMode === "error") {
127
+ throw new GeneralError("userCreate", "userAlreadyExists");
128
+ }
129
+ else if (params.overwriteMode === "skip") {
130
+ createUser = false;
131
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.user-create.labels.skipping"));
132
+ }
133
+ else if (params.overwriteMode === "overwrite") {
134
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.user-create.labels.overwriting"));
135
+ await authUserEntityStorage.remove(existingUser.email);
136
+ await identityProfileConnector.remove(existingUser.identity);
137
+ }
138
+ }
139
+ let json;
140
+ if (createUser) {
141
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.user-create.labels.creating"));
142
+ const generatedPassword = params.password ?? PasswordGenerator.generate(16);
143
+ const passwordBytes = Converter.utf8ToBytes(generatedPassword);
144
+ const saltBytes = RandomHelper.generate(16);
145
+ const hashedPassword = await PasswordHelper.hashPassword(passwordBytes, saltBytes);
146
+ const user = {
147
+ email: params.email,
148
+ password: hashedPassword,
149
+ salt: Converter.bytesToBase64(saltBytes),
150
+ identity: params.userIdentity,
151
+ organization: params.organizationIdentity
152
+ };
153
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.user-create.labels.storingUser"));
154
+ await authUserEntityStorage.set(user);
155
+ const name = `${params.givenName ?? ""} ${params.familyName ?? ""}`.trim();
156
+ const publicProfile = {
157
+ "@context": "https://schema.org",
158
+ "@type": "Person",
159
+ name: name.length > 0 ? name : undefined
160
+ };
161
+ const privateProfile = {
162
+ "@context": "https://schema.org",
163
+ "@type": "Person",
164
+ givenName: params.givenName,
165
+ familyName: params.familyName,
166
+ email: params.email
167
+ };
168
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.user-create.labels.storingProfile"));
169
+ await identityProfileConnector.create(params.userIdentity, publicProfile, privateProfile);
170
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.user-create.labels.userCreated"));
171
+ CLIDisplay.break();
172
+ json = {
173
+ did: params.userIdentity,
174
+ organizationDid: params.organizationIdentity,
175
+ email: params.email,
176
+ password: generatedPassword,
177
+ givenName: params.givenName ?? "",
178
+ familyName: params.familyName ?? ""
179
+ };
180
+ if (Is.stringValue(params.outputJson)) {
181
+ await CLIUtils.writeJsonFile(params.outputJson, json, false);
182
+ }
183
+ if (Is.stringValue(params.outputEnv)) {
184
+ await CLIUtils.writeEnvFile(params.outputEnv, [
185
+ `${params.outputEnvPrefix}DID="${params.userIdentity}"`,
186
+ `${params.outputEnvPrefix}ORGANIZATION_DID="${params.organizationIdentity}"`,
187
+ `${params.outputEnvPrefix}EMAIL="${params.email}"`,
188
+ `${params.outputEnvPrefix}PASSWORD="${generatedPassword}"`,
189
+ `${params.outputEnvPrefix}GIVEN_NAME="${params.givenName ?? ""}"`,
190
+ `${params.outputEnvPrefix}FAMILY_NAME="${params.familyName ?? ""}"`
191
+ ], false);
192
+ }
193
+ }
194
+ CLIDisplay.done();
195
+ return json;
196
+ }
197
+ //# sourceMappingURL=userCreate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userCreate.js","sourceRoot":"","sources":["../../../src/commands/userCreate.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { type AuthenticationUser, PasswordHelper } from \"@twin.org/api-auth-entity-storage-service\";\nimport { CLIDisplay, CLIUtils } from \"@twin.org/cli-core\";\nimport { Converter, GeneralError, Guards, I18n, Is, RandomHelper } from \"@twin.org/core\";\nimport { PasswordGenerator } from \"@twin.org/crypto\";\nimport type { IEngineCore } from \"@twin.org/engine-models\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { Did, IdentityProfileConnectorFactory } from \"@twin.org/identity-models\";\nimport { nameofKebabCase } from \"@twin.org/nameof\";\nimport type { Person, WithContext } from \"schema-dts\";\nimport type { ICliCommandDefinition } from \"../models/ICliCommandDefinition.js\";\nimport type { INodeEnvironmentVariables } from \"../models/INodeEnvironmentVariables.js\";\n\nconst COMMAND_NAME = \"user-create\";\n\n/**\n * Get the command definition parameters.\n * @param commandDefinitions The registered command definitions.\n */\nexport function getCommandDefinitionUserCreate(commandDefinitions: {\n\t[id: string]: ICliCommandDefinition;\n}): void {\n\tcommandDefinitions[COMMAND_NAME] = {\n\t\tcommand: COMMAND_NAME,\n\t\tdescription: I18n.formatMessage(\"node.cli.commands.user-create.description\"),\n\t\texample: I18n.formatMessage(\"node.cli.commands.user-create.example\"),\n\t\tparams: [\n\t\t\t{\n\t\t\t\tkey: \"user-identity\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"DID\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.user-identity.description\"\n\t\t\t\t)\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"organization-identity\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"DID\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.organization-identity.description\"\n\t\t\t\t)\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"email\",\n\t\t\t\ttype: \"string\",\n\t\t\t\textendedType: \"email\",\n\t\t\t\tdescription: I18n.formatMessage(\"node.cli.commands.user-create.params.email.description\")\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"password\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.password.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"given-name\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.given-name.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"family-name\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.family-name.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"overwrite-mode\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.overwrite-mode.description\"\n\t\t\t\t),\n\t\t\t\toptions: [\"skip\", \"overwrite\", \"error\"],\n\t\t\t\tdefaultValue: \"skip\",\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"load-env\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.load-env.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"output-json\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.output-json.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"output-env\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.output-env.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"output-env-prefix\",\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: I18n.formatMessage(\n\t\t\t\t\t\"node.cli.commands.user-create.params.output-env-prefix.description\"\n\t\t\t\t),\n\t\t\t\trequired: false\n\t\t\t}\n\t\t],\n\t\taction: async (engineCore, envVars, params) => userCreate(engineCore, envVars, params)\n\t};\n}\n\n/**\n * Command for creating a user.\n * @param engineCore The engine core.\n * @param envVars The environment variables for the node.\n * @param params The parameters for the command.\n * @param params.userIdentity The DID for the user.\n * @param params.organizationIdentity The organization DID for the user.\n * @param params.email The email for the user.\n * @param params.password The password for the user.\n * @param params.givenName The given name for the user.\n * @param params.familyName The family name for the user.\n * @param params.overwriteMode The mode to use when a user with the same identity already exists.\n * @param params.outputJson The output .json file to store the command output.\n * @param params.outputEnv The output .env file to store the command output.\n * @param params.outputEnvPrefix The prefix to use for variables in the output .env file.\n * @returns The created user details or undefined if skipped.\n */\nexport async function userCreate(\n\tengineCore: IEngineCore,\n\tenvVars: INodeEnvironmentVariables,\n\tparams: {\n\t\tuserIdentity?: string;\n\t\torganizationIdentity?: string;\n\t\temail?: string;\n\t\tpassword?: string;\n\t\tgivenName?: string;\n\t\tfamilyName?: string;\n\t\toverwriteMode?: \"skip\" | \"overwrite\" | \"error\";\n\t\toutputJson?: string;\n\t\toutputEnv?: string;\n\t\toutputEnvPrefix?: string;\n\t}\n): Promise<\n\t| {\n\t\t\tdid: string;\n\t\t\torganizationDid: string;\n\t\t\temail: string;\n\t\t\tpassword: string;\n\t\t\tgivenName: string;\n\t\t\tfamilyName: string;\n\t }\n\t| undefined\n> {\n\tDid.guard(\"userCreate\", \"user-identity\", params.userIdentity);\n\tDid.guard(\"userCreate\", \"organization-identity\", params.organizationIdentity);\n\tGuards.email(\"userCreate\", \"email\", params.email);\n\n\tif (Is.stringValue(params.password) && params.password.length < 16) {\n\t\tthrow new GeneralError(\"userCreate\", \"passwordTooShort\", { minLength: 16 });\n\t}\n\n\tconst defaultIdentityProfileConnectorType = engineCore.getRegisteredInstanceType(\n\t\t\"identityProfileConnector\"\n\t);\n\tconst identityProfileConnector = IdentityProfileConnectorFactory.get(\n\t\tdefaultIdentityProfileConnectorType\n\t);\n\n\tconst authUserEntityStorage =\n\t\tEntityStorageConnectorFactory.get<IEntityStorageConnector<AuthenticationUser>>(\n\t\t\tnameofKebabCase<AuthenticationUser>()\n\t\t);\n\n\tlet createUser = true;\n\n\tlet existingUser;\n\ttry {\n\t\texistingUser = await authUserEntityStorage.get(params.userIdentity, \"identity\");\n\t} catch {}\n\n\tif (!Is.empty(existingUser)) {\n\t\tif (params.overwriteMode === \"error\") {\n\t\t\tthrow new GeneralError(\"userCreate\", \"userAlreadyExists\");\n\t\t} else if (params.overwriteMode === \"skip\") {\n\t\t\tcreateUser = false;\n\t\t\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.user-create.labels.skipping\"));\n\t\t} else if (params.overwriteMode === \"overwrite\") {\n\t\t\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.user-create.labels.overwriting\"));\n\t\t\tawait authUserEntityStorage.remove(existingUser.email);\n\t\t\tawait identityProfileConnector.remove(existingUser.identity);\n\t\t}\n\t}\n\n\tlet json;\n\tif (createUser) {\n\t\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.user-create.labels.creating\"));\n\n\t\tconst generatedPassword = params.password ?? PasswordGenerator.generate(16);\n\t\tconst passwordBytes = Converter.utf8ToBytes(generatedPassword);\n\t\tconst saltBytes = RandomHelper.generate(16);\n\t\tconst hashedPassword = await PasswordHelper.hashPassword(passwordBytes, saltBytes);\n\n\t\tconst user: AuthenticationUser = {\n\t\t\temail: params.email,\n\t\t\tpassword: hashedPassword,\n\t\t\tsalt: Converter.bytesToBase64(saltBytes),\n\t\t\tidentity: params.userIdentity,\n\t\t\torganization: params.organizationIdentity\n\t\t};\n\n\t\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.user-create.labels.storingUser\"));\n\t\tawait authUserEntityStorage.set(user);\n\n\t\tconst name = `${params.givenName ?? \"\"} ${params.familyName ?? \"\"}`.trim();\n\t\tconst publicProfile: WithContext<Person> = {\n\t\t\t\"@context\": \"https://schema.org\",\n\t\t\t\"@type\": \"Person\",\n\t\t\tname: name.length > 0 ? name : undefined\n\t\t};\n\t\tconst privateProfile: WithContext<Person> = {\n\t\t\t\"@context\": \"https://schema.org\",\n\t\t\t\"@type\": \"Person\",\n\t\t\tgivenName: params.givenName,\n\t\t\tfamilyName: params.familyName,\n\t\t\temail: params.email\n\t\t};\n\n\t\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.user-create.labels.storingProfile\"));\n\t\tawait identityProfileConnector.create(params.userIdentity, publicProfile, privateProfile);\n\n\t\tCLIDisplay.task(I18n.formatMessage(\"node.cli.commands.user-create.labels.userCreated\"));\n\n\t\tCLIDisplay.break();\n\n\t\tjson = {\n\t\t\tdid: params.userIdentity,\n\t\t\torganizationDid: params.organizationIdentity,\n\t\t\temail: params.email,\n\t\t\tpassword: generatedPassword,\n\t\t\tgivenName: params.givenName ?? \"\",\n\t\t\tfamilyName: params.familyName ?? \"\"\n\t\t};\n\n\t\tif (Is.stringValue(params.outputJson)) {\n\t\t\tawait CLIUtils.writeJsonFile(params.outputJson, json, false);\n\t\t}\n\n\t\tif (Is.stringValue(params.outputEnv)) {\n\t\t\tawait CLIUtils.writeEnvFile(\n\t\t\t\tparams.outputEnv,\n\t\t\t\t[\n\t\t\t\t\t`${params.outputEnvPrefix}DID=\"${params.userIdentity}\"`,\n\t\t\t\t\t`${params.outputEnvPrefix}ORGANIZATION_DID=\"${params.organizationIdentity}\"`,\n\t\t\t\t\t`${params.outputEnvPrefix}EMAIL=\"${params.email}\"`,\n\t\t\t\t\t`${params.outputEnvPrefix}PASSWORD=\"${generatedPassword}\"`,\n\t\t\t\t\t`${params.outputEnvPrefix}GIVEN_NAME=\"${params.givenName ?? \"\"}\"`,\n\t\t\t\t\t`${params.outputEnvPrefix}FAMILY_NAME=\"${params.familyName ?? \"\"}\"`\n\t\t\t\t],\n\t\t\t\tfalse\n\t\t\t);\n\t\t}\n\t}\n\n\tCLIDisplay.done();\n\n\treturn json;\n}\n"]}
@@ -0,0 +1,185 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { CLIDisplay, CLIUtils } from "@twin.org/cli-core";
4
+ import { Converter, GeneralError, Guards, I18n, Is } from "@twin.org/core";
5
+ import { Did } from "@twin.org/identity-models";
6
+ import { VaultConnectorFactory, VaultKeyType } from "@twin.org/vault-models";
7
+ const COMMAND_NAME = "vault-key-create";
8
+ /**
9
+ * Get the command definition parameters.
10
+ * @param commandDefinitions The registered command definitions.
11
+ */
12
+ export function getCommandDefinitionVaultKeyCreate(commandDefinitions) {
13
+ commandDefinitions[COMMAND_NAME] = {
14
+ command: COMMAND_NAME,
15
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.description"),
16
+ example: I18n.formatMessage("node.cli.commands.vault-key-create.example"),
17
+ requiresNodeIdentity: false,
18
+ requiresTenantId: false,
19
+ params: [
20
+ {
21
+ key: "identity",
22
+ type: "string",
23
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.identity.description"),
24
+ extendedType: "did",
25
+ required: true
26
+ },
27
+ {
28
+ key: "key-id",
29
+ type: "string",
30
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.key-id.description"),
31
+ required: true
32
+ },
33
+ {
34
+ key: "key-type",
35
+ type: "string",
36
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.key-type.description"),
37
+ options: ["Ed25519", "Secp256k1", "ChaCha20Poly1305"],
38
+ defaultValue: "Ed25519",
39
+ required: false
40
+ },
41
+ {
42
+ key: "overwrite-mode",
43
+ type: "string",
44
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.overwrite-mode.description"),
45
+ options: ["skip", "overwrite", "error"],
46
+ defaultValue: "skip",
47
+ required: false
48
+ },
49
+ {
50
+ key: "load-env",
51
+ type: "string",
52
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.load-env.description"),
53
+ required: false
54
+ },
55
+ {
56
+ key: "output-json",
57
+ type: "string",
58
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.output-json.description"),
59
+ required: false
60
+ },
61
+ {
62
+ key: "output-env",
63
+ type: "string",
64
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.output-env.description"),
65
+ required: false
66
+ },
67
+ {
68
+ key: "output-env-prefix",
69
+ type: "string",
70
+ description: I18n.formatMessage("node.cli.commands.vault-key-create.params.output-env-prefix.description"),
71
+ required: false
72
+ }
73
+ ],
74
+ action: async (engineCore, envVars, params) => vaultKeyCreate(engineCore, envVars, params)
75
+ };
76
+ }
77
+ /**
78
+ * Command for creating a vault key.
79
+ * @param engineCore The engine core.
80
+ * @param envVars The environment variables for the node.
81
+ * @param params The parameters for the command.
82
+ * @param params.identity The DID to create the vault key for.
83
+ * @param params.keyId The ID of the key to create.
84
+ * @param params.keyType The type of key to create.
85
+ * @param params.overwriteMode The mode to use when a user with the same identity already exists.
86
+ * @param params.outputJson The output .json file to store the command output.
87
+ * @param params.outputEnv The output .env file to store the command output.
88
+ * @param params.outputEnvPrefix The prefix to use for variables in the output .env file.
89
+ * @returns The created vault key details or undefined if skipped.
90
+ */
91
+ export async function vaultKeyCreate(engineCore, envVars, params) {
92
+ Did.guard("vaultKeyCreate", "identity", params.identity);
93
+ Guards.stringValue("vaultKeyCreate", "key-id", params.keyId);
94
+ Guards.arrayOneOf("vaultKeyCreate", "key-type", params.keyType, [
95
+ "Ed25519",
96
+ "Secp256k1",
97
+ "ChaCha20Poly1305"
98
+ ]);
99
+ const defaultVaultConnectorType = engineCore.getRegisteredInstanceType("vaultConnector");
100
+ const vaultConnector = VaultConnectorFactory.get(defaultVaultConnectorType);
101
+ let createVaultKey = true;
102
+ const fullKeyId = `${params.identity}/${params.keyId}`;
103
+ let existingKey;
104
+ try {
105
+ existingKey = await vaultConnector.getKey(fullKeyId);
106
+ }
107
+ catch { }
108
+ if (!Is.empty(existingKey)) {
109
+ if (params.overwriteMode === "error") {
110
+ throw new GeneralError("vaultKeyCreate", "vaultKeyAlreadyExists");
111
+ }
112
+ else if (params.overwriteMode === "skip") {
113
+ createVaultKey = false;
114
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.vault-key-create.labels.skipping"));
115
+ }
116
+ else if (params.overwriteMode === "overwrite") {
117
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.vault-key-create.labels.overwriting"));
118
+ await vaultConnector.removeKey(fullKeyId);
119
+ }
120
+ }
121
+ let json;
122
+ if (createVaultKey) {
123
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.vault-key-create.labels.creating"));
124
+ CLIDisplay.spinnerStart();
125
+ await vaultConnector.createKey(fullKeyId, VaultKeyType[params.keyType]);
126
+ const key = await vaultConnector.getKey(fullKeyId);
127
+ CLIDisplay.spinnerStop();
128
+ CLIDisplay.task(I18n.formatMessage("node.cli.commands.vault-key-create.labels.created"));
129
+ const privateKeyBase64 = key.privateKey ? Converter.bytesToBase64(key.privateKey) : undefined;
130
+ const publicKeyBase64 = key.publicKey ? Converter.bytesToBase64(key.publicKey) : undefined;
131
+ const privateKeyHex = key.privateKey ? Converter.bytesToHex(key.privateKey, true) : undefined;
132
+ const publicKeyHex = key.publicKey ? Converter.bytesToHex(key.publicKey, true) : undefined;
133
+ CLIDisplay.break();
134
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.vault-key-create.labels.keyId"), params.keyId);
135
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.vault-key-create.labels.keyType"), params.keyType);
136
+ if (Is.stringValue(privateKeyBase64)) {
137
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.vault-key-create.labels.privateKeyBase64"), privateKeyBase64);
138
+ }
139
+ if (Is.stringValue(publicKeyBase64)) {
140
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.vault-key-create.labels.publicKeyBase64"), publicKeyBase64);
141
+ }
142
+ if (Is.stringValue(privateKeyHex)) {
143
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.vault-key-create.labels.privateKeyHex"), privateKeyHex);
144
+ }
145
+ if (Is.stringValue(publicKeyHex)) {
146
+ CLIDisplay.value(I18n.formatMessage("node.cli.commands.vault-key-create.labels.publicKeyHex"), publicKeyHex);
147
+ }
148
+ CLIDisplay.break();
149
+ json = {
150
+ identity: params.identity,
151
+ keyId: params.keyId,
152
+ keyType: params.keyType,
153
+ privateKeyBase64,
154
+ publicKeyBase64,
155
+ privateKeyHex,
156
+ publicKeyHex
157
+ };
158
+ if (Is.stringValue(params.outputJson)) {
159
+ await CLIUtils.writeJsonFile(params.outputJson, json, false);
160
+ }
161
+ if (Is.stringValue(params.outputEnv)) {
162
+ const outputParams = [
163
+ `${params.outputEnvPrefix}IDENTITY="${params.identity}"`,
164
+ `${params.outputEnvPrefix}KEY_ID="${params.keyId}"`,
165
+ `${params.outputEnvPrefix}KEY_TYPE="${params.keyType}"`
166
+ ];
167
+ if (Is.stringValue(privateKeyBase64)) {
168
+ outputParams.push(`${params.outputEnvPrefix}PRIVATE_KEY_BASE64="${privateKeyBase64}"`);
169
+ }
170
+ if (Is.stringValue(publicKeyBase64)) {
171
+ outputParams.push(`${params.outputEnvPrefix}PUBLIC_KEY_BASE64="${publicKeyBase64}"`);
172
+ }
173
+ if (Is.stringValue(privateKeyHex)) {
174
+ outputParams.push(`${params.outputEnvPrefix}PRIVATE_KEY_HEX="${privateKeyHex}"`);
175
+ }
176
+ if (Is.stringValue(publicKeyHex)) {
177
+ outputParams.push(`${params.outputEnvPrefix}PUBLIC_KEY_HEX="${publicKeyHex}"`);
178
+ }
179
+ await CLIUtils.writeEnvFile(params.outputEnv, outputParams, false);
180
+ }
181
+ }
182
+ CLIDisplay.done();
183
+ return json;
184
+ }
185
+ //# sourceMappingURL=vaultKeyCreate.js.map