@adobe/aio-cli-plugin-app-storage 1.1.0 → 1.2.0-pre.2026-02-12.sha-de5341b6

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 (36) hide show
  1. package/README.md +701 -14
  2. package/package.json +34 -7
  3. package/src/BaseCommand.js +11 -58
  4. package/src/DBBaseCommand.js +112 -0
  5. package/src/StateBaseCommand.js +87 -0
  6. package/src/commands/app/add/db.js +20 -0
  7. package/src/commands/app/db/collection/create.js +119 -0
  8. package/src/commands/app/db/collection/drop.js +90 -0
  9. package/src/commands/app/db/collection/list.js +100 -0
  10. package/src/commands/app/db/collection/rename.js +98 -0
  11. package/src/commands/app/db/collection/stats.js +94 -0
  12. package/src/commands/app/db/delete.js +89 -0
  13. package/src/commands/app/db/document/count.js +96 -0
  14. package/src/commands/app/db/document/delete.js +95 -0
  15. package/src/commands/app/db/document/find.js +133 -0
  16. package/src/commands/app/db/document/insert.js +147 -0
  17. package/src/commands/app/db/document/replace.js +122 -0
  18. package/src/commands/app/db/document/update.js +144 -0
  19. package/src/commands/app/db/index/create.js +170 -0
  20. package/src/commands/app/db/index/drop.js +87 -0
  21. package/src/commands/app/db/index/list.js +82 -0
  22. package/src/commands/app/db/ping.js +77 -0
  23. package/src/commands/app/db/provision.js +190 -0
  24. package/src/commands/app/db/stats.js +87 -0
  25. package/src/commands/app/db/status.js +159 -0
  26. package/src/commands/app/state/delete.js +3 -3
  27. package/src/commands/app/state/get.js +2 -2
  28. package/src/commands/app/state/list.js +3 -3
  29. package/src/commands/app/state/put.js +4 -4
  30. package/src/commands/app/state/stats.js +2 -2
  31. package/src/constants/db.js +32 -0
  32. package/src/constants/global.js +14 -0
  33. package/src/{constants.js → constants/state.js} +3 -0
  34. package/src/utils/inputValidation.js +74 -0
  35. package/src/utils/output.js +35 -0
  36. package/oclif.manifest.json +0 -311
package/package.json CHANGED
@@ -1,20 +1,31 @@
1
1
  {
2
2
  "name": "@adobe/aio-cli-plugin-app-storage",
3
- "version": "1.1.0",
3
+ "version": "1.2.0-pre.2026-02-12.sha-de5341b6",
4
4
  "dependencies": {
5
5
  "@adobe/aio-lib-core-config": "^5",
6
6
  "@adobe/aio-lib-core-logging": "^3",
7
- "@adobe/aio-lib-state": "^5",
7
+ "@adobe/aio-lib-db": "^0.1.0-beta.6",
8
+ "@adobe/aio-lib-env": "^3.0.1",
9
+ "@adobe/aio-lib-state": "^5.3.0",
8
10
  "@inquirer/prompts": "^5",
9
11
  "@oclif/core": "^4",
10
12
  "@oclif/plugin-help": "^6",
13
+ "@oclif/table": "^0.5.0",
11
14
  "chalk": "^5",
15
+ "dotenv": "^16.5.0",
12
16
  "semver": "^7.6.3"
13
17
  },
14
18
  "devDependencies": {
15
- "@adobe/eslint-config-aio-lib-config": "^4",
19
+ "@adobe/eslint-config-aio-lib-config": "^4.0.0",
16
20
  "@jest/globals": "^29",
17
- "eslint": "^8",
21
+ "eslint": "^8.57.1",
22
+ "eslint-config-standard": "^17.1.0",
23
+ "eslint-plugin-import": "^2.31.0",
24
+ "eslint-plugin-jest": "^27.9.0",
25
+ "eslint-plugin-jsdoc": "^48.11.0",
26
+ "eslint-plugin-n": "^15.7.0",
27
+ "eslint-plugin-node": "^11.1.0",
28
+ "eslint-plugin-promise": "^6.6.0",
18
29
  "execa": "^8",
19
30
  "jest": "^29",
20
31
  "memfs": "^4.11.1",
@@ -39,6 +50,18 @@
39
50
  "topics": {
40
51
  "app:state": {
41
52
  "description": "Manage your App Builder State storage"
53
+ },
54
+ "app:db": {
55
+ "description": "Manage your App Builder Database storage"
56
+ },
57
+ "app:db:collection": {
58
+ "description": "Manage database collections, also available under 'aio app db col <command>'"
59
+ },
60
+ "app:db:document": {
61
+ "description": "Manage documents in a collection, also available under 'aio app db doc <command>'"
62
+ },
63
+ "app:db:index": {
64
+ "description": "Manage indexes on a collection, also available under 'aio app db idx <command>'"
42
65
  }
43
66
  },
44
67
  "bin": "aio",
@@ -64,6 +87,10 @@
64
87
  "jest": {
65
88
  "collectCoverage": true,
66
89
  "testEnvironment": "node",
67
- "transform": {}
68
- }
69
- }
90
+ "transform": {},
91
+ "setupFiles": [
92
+ "<rootDir>/test/jest.env.js"
93
+ ]
94
+ },
95
+ "prereleaseSha": "de5341b6d051595337eaaabf08766ec36df360dc"
96
+ }
@@ -10,24 +10,19 @@ OF ANY KIND, either express or implied. See the License for the specific languag
10
10
  governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import { Command, Flags } from '@oclif/core'
14
- import config from '@adobe/aio-lib-core-config'
13
+ import { Command } from '@oclif/core'
15
14
  import AioLogger from '@adobe/aio-lib-core-logging'
16
-
17
- import { CONFIG_STATE_REGION } from './constants.js'
18
15
  import chalk from 'chalk'
19
- import semver from 'semver'
20
16
 
21
17
  export class BaseCommand extends Command {
22
18
  async init () {
23
19
  await super.init()
24
- // eslint-disable-next-line node/no-unsupported-features/es-syntax
25
- const { readFile } = await import('fs/promises') // dynamic import to be able to mock fs, ESM and Jest are not friends
26
20
 
27
21
  // setup debug logger
28
22
  const command = this.constructor.name.toLowerCase() // hacky but convenient
23
+ const serviceName = this.getServiceName() // Get service name dynamically
29
24
  this.debugLogger = AioLogger(
30
- `aio:app:state:${command}`,
25
+ `aio:app:${serviceName}:${command}`,
31
26
  { provider: 'debug' }
32
27
  )
33
28
  // override warn to stderr
@@ -38,50 +33,14 @@ export class BaseCommand extends Command {
38
33
  this.flags = flags
39
34
  this.args = args
40
35
  this.debugLogger.debug(`${command} args=${JSON.stringify(this.args)} flags=${JSON.stringify(this.flags)}`)
36
+ }
41
37
 
42
- // check application dependencies
43
- let packageJson
44
- try {
45
- const file = await readFile('package.json')
46
- packageJson = JSON.parse(file.toString())
47
- } catch (e) {
48
- this.debugLogger.debug('package.json not found, skipping dependency check')
49
- }
50
- if (packageJson) {
51
- const aioLibStateVersion = packageJson.dependencies?.['@adobe/aio-lib-state']
52
- const aioSdkVersion = packageJson.dependencies?.['@adobe/aio-sdk']
53
- if ((aioLibStateVersion && semver.lt(semver.coerce(aioLibStateVersion), '4.0.0')) ||
54
- (aioSdkVersion && semver.lt(semver.coerce(aioSdkVersion), '6.0.0'))) {
55
- this.error('State commands are not available for legacy State, please migrate to the latest "@adobe/aio-lib-state" (or "@adobe/aio-sdk" >= 6.0.0).')
56
- }
57
- }
58
-
59
- // init state client
60
- const owOptions = {
61
- namespace: config.get('runtime.namespace'),
62
- auth: config.get('runtime.auth')
63
- }
64
- if (!(owOptions.namespace && owOptions.auth)) {
65
- this.error(
66
- `This command is expected to be run in the root of a App Builder app project.
67
- Please make sure the 'AIO_RUNTIME_NAMESPACE' and 'AIO_RUNTIME_AUTH' environment variables are configured.`
68
- )
69
- }
70
- const region = flags.region || config.get(CONFIG_STATE_REGION) || 'amer'
71
- this.debugLogger.info('using state region: %s', region)
72
-
73
- if (config.get('state.endpoint')) {
74
- process.env.AIO_STATE_ENDPOINT = config.get('state.endpoint')
75
- this.debugLogger.info('using custom endpoint: %s', process.env.AIO_STATE_ENDPOINT)
76
- }
77
- // dynamic import to be able to reload the AIO_STATE_ENDPOINT var
78
- // eslint-disable-next-line node/no-unsupported-features/es-syntax
79
- const State = await import('@adobe/aio-lib-state')
80
-
81
- /** @type {import('@adobe/aio-lib-state').AdobeState} */
82
- this.state = await State.init({ region, ow: owOptions })
83
-
84
- this.rtNamespace = owOptions.namespace
38
+ /**
39
+ * Get the service name for logging
40
+ * @returns {string} The service name
41
+ */
42
+ getServiceName () {
43
+ return 'app' // Default fallback
85
44
  }
86
45
 
87
46
  async catch (error) {
@@ -105,12 +64,6 @@ export class BaseCommand extends Command {
105
64
  // display the JSON returned by the command's run method.
106
65
  BaseCommand.enableJsonFlag = true
107
66
 
108
- BaseCommand.flags = {
109
- region: Flags.string({
110
- description: 'State region. Defaults to \'AIO_STATE_REGION\' env or \'amer\' if neither is set.',
111
- required: false,
112
- options: ['amer', 'emea', 'apac']
113
- })
114
- }
67
+ BaseCommand.flags = {}
115
68
 
116
69
  BaseCommand.args = {}
@@ -0,0 +1,112 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { BaseCommand } from './BaseCommand.js'
14
+ import config from '@adobe/aio-lib-core-config'
15
+ import { CONFIG_RUNTIME_AUTH, CONFIG_RUNTIME_NAMESPACE } from './constants/global.js'
16
+ import { AVAILABLE_REGIONS, CONFIG_DB_ENDPOINT, CONFIG_DB_REGION, DEFAULT_REGION } from './constants/db.js'
17
+ import { Flags } from '@oclif/core'
18
+ import { getCliEnv } from '@adobe/aio-lib-env'
19
+
20
+ export class DBBaseCommand extends BaseCommand {
21
+ async init () {
22
+ await super.init()
23
+
24
+ // Initialize database client
25
+ await this.initializeDBClient()
26
+
27
+ this.debugLogger?.info?.('DBBaseCommand initialized with DB client')
28
+ }
29
+
30
+ /**
31
+ * Initialize the database client using aio-lib-db
32
+ */
33
+ async initializeDBClient () {
34
+ try {
35
+ const region = this.flags?.region || config.get(CONFIG_DB_REGION) || DEFAULT_REGION
36
+ // Get database configuration
37
+ const dbConfig = {
38
+ ow: {
39
+ namespace: config.get(CONFIG_RUNTIME_NAMESPACE),
40
+ auth: config.get(CONFIG_RUNTIME_AUTH)
41
+ },
42
+ region
43
+ }
44
+
45
+ // Validate region based on environment
46
+ const allowedRegions = AVAILABLE_REGIONS[getCliEnv()]
47
+ if (!allowedRegions.includes(region)) {
48
+ this.error(`Invalid region '${region}' for the ${getCliEnv()} environment, must be one of: ${allowedRegions.join(', ')}`)
49
+ }
50
+
51
+ // Validate required configuration
52
+ if (!(dbConfig.ow.namespace && dbConfig.ow.auth)) {
53
+ this.error(
54
+ `Database commands require App Builder project configuration.
55
+ Please make sure the 'AIO_RUNTIME_NAMESPACE' and 'AIO_RUNTIME_AUTH' environment variables are configured.`
56
+ )
57
+ }
58
+
59
+ const endpointOverride = config.get(CONFIG_DB_ENDPOINT)
60
+ if (endpointOverride) {
61
+ process.env.AIO_DB_ENDPOINT = endpointOverride
62
+ this.debugLogger?.info?.('Using custom endpoint: %s', process.env.AIO_DB_ENDPOINT)
63
+ }
64
+
65
+ // Dynamic import to be able to reload the AIO_DB_ENDPOINT var
66
+ // eslint-disable-next-line node/no-unsupported-features/es-syntax
67
+ const aioLibDb = await import('@adobe/aio-lib-db')
68
+ const { init } = aioLibDb.default || aioLibDb
69
+
70
+ this.debugLogger?.info?.('Initializing DB client with config:', {
71
+ namespace: dbConfig.ow.namespace,
72
+ region: dbConfig.region,
73
+ hasAuth: !!dbConfig.ow.auth
74
+ })
75
+
76
+ // Initialize the database client
77
+ this.db = await init(dbConfig)
78
+ this.dbConfig = dbConfig
79
+ this.rtNamespace = dbConfig.ow.namespace
80
+
81
+ this.debugLogger?.info?.('DB client initialized successfully')
82
+ } catch (error) {
83
+ this.debugLogger?.error?.('Failed to initialize DB client:', error.message)
84
+ this.error(`Failed to initialize database client: ${error.message}`)
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Get the service name for logging
90
+ * @returns {string} The service name
91
+ */
92
+ getServiceName () {
93
+ return 'db'
94
+ }
95
+ }
96
+
97
+ // Add json and region flags to GLOBAL FLAGS section in --help output
98
+ DBBaseCommand.flags = {
99
+ ...BaseCommand.flags,
100
+ json: {
101
+ description: 'Format output as json.',
102
+ default: false,
103
+ required: false,
104
+ helpGroup: 'GLOBAL'
105
+ },
106
+ region: Flags.string({
107
+ description: `Database region. Defaults to 'AIO_DB_REGION' environment variable or '${DEFAULT_REGION}' if neither is set. Any database region set in 'app.config.yaml' takes precedence over all of these.\n<options: ${AVAILABLE_REGIONS.prod.join('|')}>`,
108
+ required: false,
109
+ helpGroup: 'GLOBAL'
110
+ // Don't set default here to let it load from the environment var if not passed as a flag
111
+ })
112
+ }
@@ -0,0 +1,87 @@
1
+ /*
2
+ Copyright 2024 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { BaseCommand } from './BaseCommand.js'
14
+ import config from '@adobe/aio-lib-core-config'
15
+ import { AVAILABLE_REGIONS, CONFIG_STATE_REGION, DEFAULT_REGION } from './constants/state.js'
16
+ import { CONFIG_RUNTIME_NAMESPACE, CONFIG_RUNTIME_AUTH } from './constants/global.js'
17
+
18
+ import semver from 'semver'
19
+ import { Flags } from '@oclif/core'
20
+
21
+ export class StateBaseCommand extends BaseCommand {
22
+ async init () {
23
+ await super.init()
24
+ // check application dependencies
25
+ let packageJson
26
+ try {
27
+ // eslint-disable-next-line node/no-unsupported-features/es-syntax
28
+ const { readFile } = await import('fs/promises')
29
+ const file = await readFile('package.json')
30
+ packageJson = JSON.parse(file.toString())
31
+ } catch (e) {
32
+ this.debugLogger?.debug?.('package.json not found, skipping dependency check')
33
+ }
34
+ if (packageJson) {
35
+ const aioLibStateVersion = packageJson.dependencies?.['@adobe/aio-lib-state']
36
+ const aioSdkVersion = packageJson.dependencies?.['@adobe/aio-sdk']
37
+ if ((aioLibStateVersion && semver.lt(semver.coerce(aioLibStateVersion), '4.0.0')) ||
38
+ (aioSdkVersion && semver.lt(semver.coerce(aioSdkVersion), '6.0.0'))) {
39
+ this.error('State commands are not available for legacy State, please migrate to the latest "@adobe/aio-lib-state" (or "@adobe/aio-sdk" >= 6.0.0).')
40
+ }
41
+ }
42
+
43
+ // init state client
44
+ const owOptions = {
45
+ namespace: config.get(CONFIG_RUNTIME_NAMESPACE),
46
+ auth: config.get(CONFIG_RUNTIME_AUTH)
47
+ }
48
+ if (!(owOptions.namespace && owOptions.auth)) {
49
+ this.error(
50
+ `This command is expected to be run in the root of a App Builder app project.
51
+ Please make sure the 'AIO_RUNTIME_NAMESPACE' and 'AIO_RUNTIME_AUTH' environment variables are configured.`
52
+ )
53
+ }
54
+ const region = this.flags.region || config.get(CONFIG_STATE_REGION) || DEFAULT_REGION
55
+ this.debugLogger?.info?.('using state region: %s', region)
56
+
57
+ if (config.get('state.endpoint')) {
58
+ process.env.AIO_STATE_ENDPOINT = config.get('state.endpoint')
59
+ this.debugLogger?.info?.('using custom endpoint: %s', process.env.AIO_STATE_ENDPOINT)
60
+ }
61
+ // dynamic import to be able to reload the AIO_STATE_ENDPOINT var
62
+ // eslint-disable-next-line node/no-unsupported-features/es-syntax
63
+ const aioLibState = await import('@adobe/aio-lib-state')
64
+
65
+ /** @type {import('@adobe/aio-lib-state').AdobeState} */
66
+ this.state = await aioLibState.init({ region, ow: owOptions })
67
+
68
+ this.rtNamespace = owOptions.namespace
69
+ }
70
+
71
+ /**
72
+ * Get the service name for logging
73
+ * @returns {string} The service name
74
+ */
75
+ getServiceName () {
76
+ return 'state'
77
+ }
78
+ }
79
+
80
+ StateBaseCommand.flags = {
81
+ ...BaseCommand.flags,
82
+ region: Flags.string({
83
+ description: 'State region. Defaults to \'AIO_STATE_REGION\' env or \'amer\' if neither is set.',
84
+ required: false,
85
+ options: AVAILABLE_REGIONS
86
+ })
87
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { Provision } from '../db/provision.js'
14
+
15
+ // 'aio app add db' is an alias for 'aio app db provision', but to have it show up in
16
+ // help correctly it needs its own class instead of using Provision.aliases
17
+ export class AddDb extends Provision {}
18
+
19
+ // Update the examples for the help display
20
+ AddDb.examples = Provision.examples.map(example => example.replace('$ aio app db provision', '$ aio app add db'))
@@ -0,0 +1,119 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { DBBaseCommand } from '../../../../DBBaseCommand.js'
14
+ import { Args, Flags } from '@oclif/core'
15
+ import chalk from 'chalk'
16
+ import { asObject, isNonEmptyString } from '../../../../utils/inputValidation.js'
17
+
18
+ export class CreateCollection extends DBBaseCommand {
19
+ async run () {
20
+ const { collection } = this.args
21
+ const { validator } = this.flags
22
+
23
+ try {
24
+ this.log(chalk.blue(`Creating collection '${collection}'...`))
25
+
26
+ // Log flag values if set
27
+ if (validator) {
28
+ this.log(chalk.dim(` Using validator: ${validator}`))
29
+ }
30
+
31
+ const client = await this.db.connect()
32
+
33
+ // Check if collection already exists
34
+ const existingCollections = await client.listCollections()
35
+ const collectionExists = existingCollections && existingCollections.some(col => col.name === collection)
36
+
37
+ if (collectionExists) {
38
+ const errorMessage = `Collection '${collection}' already exists`
39
+
40
+ this.log(chalk.red(errorMessage))
41
+ this.log(chalk.dim(` Namespace: ${this.rtNamespace}`))
42
+
43
+ this.error(errorMessage)
44
+ }
45
+
46
+ // Build collection options
47
+ const options = {}
48
+ if (validator) {
49
+ options.validator = { $jsonSchema: validator }
50
+ }
51
+
52
+ // Create the collection
53
+ const result = await client.createCollection(collection, options)
54
+
55
+ this.debugLogger?.info?.('Collection created successfully:', result)
56
+
57
+ const response = {
58
+ collection,
59
+ status: 'created',
60
+ namespace: this.rtNamespace,
61
+ timestamp: new Date().toISOString(),
62
+ options
63
+ }
64
+
65
+ this.log(chalk.green(`Collection '${collection}' created successfully`))
66
+ this.log(chalk.dim(` Namespace: ${this.rtNamespace}`))
67
+
68
+ if (validator) {
69
+ // Display the final validator object (after parsing) in compact JSON format
70
+ const validatorDisplay = JSON.stringify(options.validator.$jsonSchema)
71
+ this.log(chalk.dim(` Validator: ${validatorDisplay}`))
72
+ }
73
+
74
+ this.log(chalk.dim(` Created: ${new Date().toLocaleString()}`))
75
+
76
+ return response
77
+ } catch (error) {
78
+ this.debugLogger?.error?.('Error creating collection:', error)
79
+
80
+ const errorMessage = `Failed to create collection '${collection}': ${error.message}`
81
+
82
+ this.log(chalk.red('Failed to create collection'))
83
+ this.log(chalk.dim(` Collection: ${collection}`))
84
+ this.log(chalk.dim(` Namespace: ${this.rtNamespace}`))
85
+ this.log(chalk.dim(` Error: ${error.message}`))
86
+
87
+ this.error(errorMessage)
88
+ }
89
+ }
90
+ }
91
+
92
+ CreateCollection.description = 'Create a new collection in the database'
93
+
94
+ CreateCollection.examples = [
95
+ '$ aio app db collection create users',
96
+ '$ aio app db collection create inventory --validator \'{"type": "object", "required": ["id", "quantity"]}\' --json',
97
+ '$ aio app db col create products --json',
98
+ '$ aio app db col create products --validator \'{"type": "object", "properties": {"name": {"type": "string"}, "price": {"type": "number", "minimum": 0}}, "required": ["name", "price"]}\''
99
+ ]
100
+
101
+ CreateCollection.args = {
102
+ collection: Args.string({
103
+ name: 'collection',
104
+ description: 'The name of the collection to create',
105
+ required: true,
106
+ parse: input => isNonEmptyString(input, 'Collection name')
107
+ })
108
+ }
109
+
110
+ CreateCollection.flags = {
111
+ ...DBBaseCommand.flags,
112
+ validator: Flags.string({
113
+ char: 'v',
114
+ description: 'JSON schema validator for document validation (JSON string)',
115
+ parse: input => asObject(input, 'Validator')
116
+ })
117
+ }
118
+
119
+ CreateCollection.aliases = ['app:db:col:create']
@@ -0,0 +1,90 @@
1
+ /*
2
+ Copyright 2025 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { DBBaseCommand } from '../../../../DBBaseCommand.js'
14
+ import { Args } from '@oclif/core'
15
+ import chalk from 'chalk'
16
+ import { isNonEmptyString } from '../../../../utils/inputValidation.js'
17
+ import { prettyJson } from '../../../../utils/output.js'
18
+
19
+ export class DropCollection extends DBBaseCommand {
20
+ async run () {
21
+ const { collection } = this.args
22
+
23
+ try {
24
+ this.log(chalk.blue(`Dropping collection '${collection}'...`))
25
+
26
+ const client = await this.db.connect()
27
+
28
+ // Get the collection object
29
+ const coll = client.collection(collection)
30
+
31
+ // Drop collection
32
+ const result = await coll.drop()
33
+
34
+ this.debugLogger?.info?.('Collection dropped successfully:', result)
35
+
36
+ const response = {
37
+ collection,
38
+ status: 'dropped',
39
+ namespace: this.rtNamespace,
40
+ timestamp: new Date().toISOString(),
41
+ result
42
+ }
43
+
44
+ this.log(chalk.green(`Collection '${collection}' dropped successfully`))
45
+ this.log(chalk.dim(` Namespace: ${this.rtNamespace}`))
46
+
47
+ if (result && typeof result === 'object' && Object.keys(result).length > 0) {
48
+ this.log(chalk.dim(` Details:\n${prettyJson(result)}`))
49
+ }
50
+
51
+ this.log(chalk.dim(` Dropped: ${new Date().toLocaleString()}`))
52
+
53
+ return response
54
+ } catch (error) {
55
+ this.debugLogger?.error?.('Error dropping collection:', error)
56
+
57
+ const errorMessage = `Failed to drop collection '${collection}': ${error.message}`
58
+
59
+ this.log(chalk.red('Failed to drop collection'))
60
+ this.log(chalk.dim(` Collection: ${collection}`))
61
+ this.log(chalk.dim(` Namespace: ${this.rtNamespace}`))
62
+ this.log(chalk.dim(` Error: ${error.message}`))
63
+
64
+ this.error(errorMessage)
65
+ }
66
+ }
67
+ }
68
+
69
+ DropCollection.description = 'Drop a collection from the database'
70
+
71
+ DropCollection.examples = [
72
+ '$ aio app db collection drop users',
73
+ '$ aio app db collection drop products --json',
74
+ '$ aio app db col drop inventory'
75
+ ]
76
+
77
+ DropCollection.args = {
78
+ collection: Args.string({
79
+ name: 'collection',
80
+ description: 'The name of the collection to drop',
81
+ required: true,
82
+ parse: input => isNonEmptyString(input, 'Collection name')
83
+ })
84
+ }
85
+
86
+ DropCollection.flags = {
87
+ ...DBBaseCommand.flags
88
+ }
89
+
90
+ DropCollection.aliases = ['app:db:col:drop']