@adobe/aio-cli-plugin-api-mesh 3.5.0-alpha.1 → 3.6.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
- package/src/commands/__fixtures__/env_invalid +2 -8
- package/src/commands/api-mesh/__tests__/create.test.js +18 -5
- package/src/commands/api-mesh/__tests__/run.test.js +20 -7
- package/src/commands/api-mesh/init.js +19 -13
- package/src/templates/deployWorkflow.yaml +63 -0
- package/src/templates/devcontainer.json +27 -0
- package/src/templates/gitignore +5 -1
- package/src/templates/mesh.json +14 -0
- package/src/templates/package.json +11 -2
- package/src/templates/readme.md +9 -0
- package/src/templates/sample.env +1 -0
- package/src/templates/vscode_launch.json +15 -0
- package/src/utils.js +5 -61
package/oclif.manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"3.
|
|
1
|
+
{"version":"3.6.0-beta.1","commands":{"PLUGINNAME":{"id":"PLUGINNAME","description":"Your description here","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio PLUGINNAME:some_command"],"flags":{"someflag":{"name":"someflag","type":"option","char":"f","description":"this is some flag"}},"args":[]},"api-mesh:create":{"id":"api-mesh:create","description":"Create a mesh with the given config.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"json":{"name":"json","type":"boolean","description":"Output JSON","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"secrets":{"name":"secrets","type":"option","char":"s","description":"Path to secrets file","default":false}},"args":[{"name":"file"}]},"api-mesh:delete":{"id":"api-mesh:delete","description":"Delete the config of a given mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false}},"args":[]},"api-mesh:describe":{"id":"api-mesh:describe","description":"Get details of a mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[]},"api-mesh:get":{"id":"api-mesh:get","description":"Get the config of a given mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"json":{"name":"json","type":"boolean","description":"Output JSON","allowNo":false}},"args":[{"name":"file"}]},"api-mesh:init":{"id":"api-mesh:init","description":"This command will create a workspace where you can organise your API mesh configuration and other files","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":[{"description":"API mesh workspace init","command":"aio api-mesh init commerce-mesh"},{"description":"API mesh workspace init with flags","command":"aio api-mesh init commerce-mesh --path ./mesh_projects/test_mesh --git y --packageManager yarn"}],"flags":{"path":{"name":"path","type":"option","char":"p","default":"."},"packageManager":{"name":"packageManager","type":"option","char":"m","options":["npm","yarn"]},"git":{"name":"git","type":"option","char":"g","options":["y","n"]}},"args":[{"name":"projectName","description":"Project name","required":true}]},"api-mesh:run":{"id":"api-mesh:run","description":"Run a local development server that builds and compiles a mesh locally","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"Port number for the local dev server"},"debug":{"name":"debug","type":"boolean","description":"Enable debugging mode","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"select":{"name":"select","type":"boolean","description":"Retrieve existing artifacts from the mesh","allowNo":false},"secrets":{"name":"secrets","type":"option","char":"s","description":"Path to secrets file","default":false}},"args":[{"name":"file","description":"Mesh File"}]},"api-mesh:status":{"id":"api-mesh:status","description":"Get a mesh status with a given meshid.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[]},"api-mesh:update":{"id":"api-mesh:update","description":"Update a mesh with the given config.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"secrets":{"name":"secrets","type":"option","char":"s","description":"Path to secrets file","default":false}},"args":[{"name":"file"}]},"api-mesh:source:discover":{"id":"api-mesh:source:discover","description":"Return the list of avaliable sources","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm install action prompt. CLI will not check ask user to install source.","allowNo":false}},"args":[]},"api-mesh:source:get":{"id":"api-mesh:source:get","description":"Command returns the content of a specific source.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio api-mesh:source:get -s=<version>@<source_name>","$ aio api-mesh:source:get -s<source_name>","$ aio api-mesh:source:get -m"],"flags":{"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm print action prompt. CLI will not check ask user to print source.","allowNo":false},"source":{"name":"source","type":"option","char":"s","description":"Source name"},"multiple":{"name":"multiple","type":"boolean","char":"m","description":"Select multiple sources","allowNo":false}},"args":[]},"api-mesh:source:install":{"id":"api-mesh:source:install","description":"Command to install the source to your API mesh.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio api-mesh:source:install <version>@<source_name>","$ aio api-mesh:source:install <source_name> -v <variable_name>=<variable_value>","$ aio api-mesh:source:install <source_name> -f <path_to_variables_file>"],"flags":{"source":{"name":"source","type":"option","char":"s","description":"Source name"},"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm override action prompt. CLI will not check ask user to override source.","allowNo":false},"variable":{"name":"variable","type":"option","char":"v","description":"Variables required for the source"},"variable-file":{"name":"variable-file","type":"option","char":"f","description":"Variables file path"},"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[{"name":"source"}]}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/aio-cli-plugin-api-mesh",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0-beta.1",
|
|
4
4
|
"description": "Adobe I/O CLI plugin to develop and manage API mesh sources",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oclif-plugin"
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
"version": "oclif-dev readme && git add README.md"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@adobe-apimesh/mesh-builder": "1.
|
|
40
|
+
"@adobe-apimesh/mesh-builder": "1.6.0",
|
|
41
41
|
"@adobe/aio-cli-lib-console": "^4.0.0",
|
|
42
42
|
"@adobe/aio-lib-core-config": "^3.0.0",
|
|
43
43
|
"@adobe/aio-lib-core-logging": "^2.0.0",
|
|
44
44
|
"@adobe/aio-lib-env": "^2.0.0",
|
|
45
45
|
"@adobe/aio-lib-ims": "^6.0.1",
|
|
46
|
-
"@adobe/plugin-hooks": "0.
|
|
46
|
+
"@adobe/plugin-hooks": "0.3.0",
|
|
47
47
|
"@adobe/plugin-on-fetch": "0.1.0",
|
|
48
48
|
"@graphql-mesh/cli": "0.82.30",
|
|
49
49
|
"@graphql-mesh/graphql": "0.34.13",
|
|
@@ -774,7 +774,7 @@ describe('create command tests', () => {
|
|
|
774
774
|
`);
|
|
775
775
|
});
|
|
776
776
|
|
|
777
|
-
test('should return error if mesh has placeholders and the provided env file is invalid', async () => {
|
|
777
|
+
test('should return error if mesh has placeholders and the provided env file is invalid and parsed to {}', async () => {
|
|
778
778
|
parseSpy.mockResolvedValueOnce({
|
|
779
779
|
args: { file: 'src/commands/__fixtures__/sample_mesh_with_placeholder' },
|
|
780
780
|
flags: {
|
|
@@ -788,14 +788,17 @@ describe('create command tests', () => {
|
|
|
788
788
|
|
|
789
789
|
await expect(runResult).rejects.toEqual(
|
|
790
790
|
new Error(
|
|
791
|
-
|
|
791
|
+
'Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
792
792
|
),
|
|
793
793
|
);
|
|
794
794
|
|
|
795
795
|
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
796
796
|
[
|
|
797
797
|
[
|
|
798
|
-
"
|
|
798
|
+
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
799
|
+
],
|
|
800
|
+
[
|
|
801
|
+
"Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
799
802
|
],
|
|
800
803
|
]
|
|
801
804
|
`);
|
|
@@ -819,7 +822,9 @@ describe('create command tests', () => {
|
|
|
819
822
|
|
|
820
823
|
const runResult = CreateCommand.run();
|
|
821
824
|
await expect(runResult).rejects.toEqual(
|
|
822
|
-
new Error(
|
|
825
|
+
new Error(
|
|
826
|
+
'Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2',
|
|
827
|
+
),
|
|
823
828
|
);
|
|
824
829
|
|
|
825
830
|
await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
@@ -827,6 +832,9 @@ describe('create command tests', () => {
|
|
|
827
832
|
[
|
|
828
833
|
"The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
829
834
|
],
|
|
835
|
+
[
|
|
836
|
+
"Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
837
|
+
],
|
|
830
838
|
]
|
|
831
839
|
`);
|
|
832
840
|
});
|
|
@@ -853,7 +861,9 @@ describe('create command tests', () => {
|
|
|
853
861
|
|
|
854
862
|
const runResult = CreateCommand.run();
|
|
855
863
|
await expect(runResult).rejects.toEqual(
|
|
856
|
-
new Error(
|
|
864
|
+
new Error(
|
|
865
|
+
'Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
866
|
+
),
|
|
857
867
|
);
|
|
858
868
|
|
|
859
869
|
await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
@@ -861,6 +871,9 @@ describe('create command tests', () => {
|
|
|
861
871
|
[
|
|
862
872
|
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
863
873
|
],
|
|
874
|
+
[
|
|
875
|
+
"Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
876
|
+
],
|
|
864
877
|
]
|
|
865
878
|
`);
|
|
866
879
|
});
|
|
@@ -272,17 +272,20 @@ describe('run command tests', () => {
|
|
|
272
272
|
|
|
273
273
|
await expect(runResult).rejects.toEqual(
|
|
274
274
|
new Error(
|
|
275
|
-
|
|
275
|
+
'Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
276
276
|
),
|
|
277
277
|
);
|
|
278
278
|
|
|
279
279
|
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
280
280
|
[
|
|
281
281
|
[
|
|
282
|
-
"
|
|
282
|
+
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
283
|
+
],
|
|
284
|
+
[
|
|
285
|
+
"Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
283
286
|
],
|
|
284
287
|
[
|
|
285
|
-
"Issue in src/commands/__fixtures__/env_invalid file -
|
|
288
|
+
"Issue in src/commands/__fixtures__/env_invalid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
286
289
|
],
|
|
287
290
|
]
|
|
288
291
|
`);
|
|
@@ -304,7 +307,9 @@ describe('run command tests', () => {
|
|
|
304
307
|
|
|
305
308
|
const runResult = RunCommand.run();
|
|
306
309
|
await expect(runResult).rejects.toEqual(
|
|
307
|
-
new Error(
|
|
310
|
+
new Error(
|
|
311
|
+
'Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2',
|
|
312
|
+
),
|
|
308
313
|
);
|
|
309
314
|
|
|
310
315
|
await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
@@ -313,7 +318,10 @@ describe('run command tests', () => {
|
|
|
313
318
|
"The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
314
319
|
],
|
|
315
320
|
[
|
|
316
|
-
"The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
321
|
+
"Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
322
|
+
],
|
|
323
|
+
[
|
|
324
|
+
"Issue in src/commands/__fixtures__/env_valid file - The mesh file cannot be interpolated due to missing keys : newKey1 , newKey2",
|
|
317
325
|
],
|
|
318
326
|
]
|
|
319
327
|
`);
|
|
@@ -339,7 +347,9 @@ describe('run command tests', () => {
|
|
|
339
347
|
|
|
340
348
|
const runResult = RunCommand.run();
|
|
341
349
|
await expect(runResult).rejects.toEqual(
|
|
342
|
-
new Error(
|
|
350
|
+
new Error(
|
|
351
|
+
'Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
352
|
+
),
|
|
343
353
|
);
|
|
344
354
|
|
|
345
355
|
await expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
@@ -348,7 +358,10 @@ describe('run command tests', () => {
|
|
|
348
358
|
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
349
359
|
],
|
|
350
360
|
[
|
|
351
|
-
"Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
361
|
+
"Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
362
|
+
],
|
|
363
|
+
[
|
|
364
|
+
"Issue in src/commands/__fixtures__/env_valid file - Interpolated mesh is not a valid JSON. Please check the generated json file.",
|
|
352
365
|
],
|
|
353
366
|
]
|
|
354
367
|
`);
|
|
@@ -70,18 +70,12 @@ class InitCommand extends Command {
|
|
|
70
70
|
await fs.writeFile(filePath, JSON.stringify(pkgJSON, null, 2), 'utf8', { mode: 'w' });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
async
|
|
73
|
+
async cloneFile(templatePath, filePath) {
|
|
74
74
|
const dotNpmrcFile = await fs.readFile(templatePath, 'utf8');
|
|
75
75
|
|
|
76
76
|
await fs.writeFile(filePath, dotNpmrcFile, 'utf8', { mode: 'w' });
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
async createGitIgnoreFile(templatePath, filePath) {
|
|
80
|
-
const gitIgnoreFile = await fs.readFile(templatePath, 'utf8');
|
|
81
|
-
|
|
82
|
-
await fs.writeFile(filePath, gitIgnoreFile, 'utf8', { mode: 'w' });
|
|
83
|
-
}
|
|
84
|
-
|
|
85
79
|
async run() {
|
|
86
80
|
const { args, flags } = await this.parse(InitCommand);
|
|
87
81
|
const gitFlagOptions = {
|
|
@@ -92,8 +86,16 @@ class InitCommand extends Command {
|
|
|
92
86
|
let absolutePath = resolve(flags.path);
|
|
93
87
|
let shouldCreateGit = gitFlagOptions[flags.git];
|
|
94
88
|
let packageManagerChoice = flags.packageManager;
|
|
89
|
+
|
|
95
90
|
const packageJsonTemplate = `${getAppRootDir()}/src/templates/package.json`;
|
|
96
91
|
const dotNpmrcPath = `${getAppRootDir()}/src/templates/npmrc`;
|
|
92
|
+
const vsCodeLaunchJsonPath = `${getAppRootDir()}/src/templates/vscode_launch.json`;
|
|
93
|
+
const devContainerJsonPath = `${getAppRootDir()}/src/templates/devcontainer.json`;
|
|
94
|
+
const sampleENVPath = `${getAppRootDir()}/src/templates/sample.env`;
|
|
95
|
+
const githubWorkflowPath = `${getAppRootDir()}/src/templates/deployWorkflow.yaml`;
|
|
96
|
+
const readmePath = `${getAppRootDir()}/src/templates/readme.md`;
|
|
97
|
+
const sampleMeshConfigPath = `${getAppRootDir()}/src/templates/mesh.json`;
|
|
98
|
+
|
|
97
99
|
const shouldCreateWorkspace = await promptConfirm(
|
|
98
100
|
`Do you want to create the workspace in ${absolutePath}`,
|
|
99
101
|
);
|
|
@@ -140,23 +142,27 @@ class InitCommand extends Command {
|
|
|
140
142
|
const gitIgnoreTemplatePath = `${getAppRootDir()}/src/templates/gitignore`;
|
|
141
143
|
const gitIgnoreFilePath = `${absolutePath}/.gitignore`;
|
|
142
144
|
|
|
143
|
-
await this.
|
|
145
|
+
await this.cloneFile(gitIgnoreTemplatePath, gitIgnoreFilePath);
|
|
146
|
+
await this.cloneFile(githubWorkflowPath, `${absolutePath}/.github/workflows/deploy.yaml`);
|
|
144
147
|
} catch (error) {
|
|
145
148
|
this.error(error);
|
|
146
149
|
}
|
|
147
150
|
}
|
|
148
151
|
|
|
149
|
-
await fs.writeFile(`${absolutePath}/.env`, '', 'utf8', { mode: 'w' });
|
|
150
|
-
|
|
151
|
-
this.log(`Installing dependencies`);
|
|
152
|
-
|
|
153
152
|
await this.createPackageJson(
|
|
154
153
|
packageJsonTemplate,
|
|
155
154
|
`${absolutePath}/package.json`,
|
|
156
155
|
args.projectName,
|
|
157
156
|
);
|
|
158
157
|
|
|
159
|
-
await this.
|
|
158
|
+
await this.cloneFile(dotNpmrcPath, `${absolutePath}/.npmrc`);
|
|
159
|
+
await this.cloneFile(vsCodeLaunchJsonPath, `${absolutePath}/.vscode/launch.json`);
|
|
160
|
+
await this.cloneFile(devContainerJsonPath, `${absolutePath}/.devcontainer/devcontainer.json`);
|
|
161
|
+
await this.cloneFile(sampleENVPath, `${absolutePath}/.env`);
|
|
162
|
+
await this.cloneFile(readmePath, `${absolutePath}/README.md`);
|
|
163
|
+
await this.cloneFile(sampleMeshConfigPath, `${absolutePath}/mesh.json`);
|
|
164
|
+
|
|
165
|
+
this.log(`Installing dependencies`);
|
|
160
166
|
|
|
161
167
|
if (packageManagerChoice === 'npm') {
|
|
162
168
|
try {
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Deploy Mesh
|
|
2
|
+
|
|
3
|
+
# Controls when the workflow will run
|
|
4
|
+
on:
|
|
5
|
+
# Triggers the workflow on push or pull request events but only for the "main" branch
|
|
6
|
+
push:
|
|
7
|
+
branches: ["main"]
|
|
8
|
+
# Allows you to run this workflow manually from the Actions tab
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
|
12
|
+
jobs:
|
|
13
|
+
deploy:
|
|
14
|
+
name: Deploy to Prod
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
max-parallel: 1
|
|
18
|
+
matrix:
|
|
19
|
+
node-version: ["20"]
|
|
20
|
+
os: [ubuntu-latest]
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
+
uses: actions/setup-node@v4
|
|
26
|
+
with:
|
|
27
|
+
node-version: ${{ matrix.node-version }}
|
|
28
|
+
- name: Setup CLI
|
|
29
|
+
uses: adobe/aio-cli-setup-action@1.3.0
|
|
30
|
+
with:
|
|
31
|
+
os: ${{ matrix.os }}
|
|
32
|
+
version: 10.x.x
|
|
33
|
+
- name: api-mesh-plugin install
|
|
34
|
+
run: aio plugins:install @adobe/aio-cli-plugin-api-mesh
|
|
35
|
+
- name: Auth
|
|
36
|
+
uses: adobe/aio-apps-action@3.3.0
|
|
37
|
+
with:
|
|
38
|
+
os: ${{ matrix.os }}
|
|
39
|
+
command: oauth_sts
|
|
40
|
+
CLIENTID: ${{ secrets.CLIENTID }}
|
|
41
|
+
CLIENTSECRET: ${{ secrets.CLIENTSECRET }}
|
|
42
|
+
TECHNICALACCOUNTID: ${{ secrets.TECHNICALACCID }}
|
|
43
|
+
TECHNICALACCOUNTEMAIL: ${{ secrets.TECHNICALACCEMAIL }}
|
|
44
|
+
IMSORGID: ${{ secrets.IMSORGID }}
|
|
45
|
+
SCOPES: AdobeID, openid, read_organizations, additional_info.projectedProductContext, additional_info.roles, adobeio_api, read_client_secret, manage_client_secrets
|
|
46
|
+
- name: Set CLI ENV
|
|
47
|
+
run: aio config set cli.env prod
|
|
48
|
+
- name: Select org
|
|
49
|
+
run: aio console:org:select ${{ secrets.ORGID }}
|
|
50
|
+
- name: Select project
|
|
51
|
+
run: aio console:project:select ${{ secrets.PROJECTID }}
|
|
52
|
+
- name: Select workspace
|
|
53
|
+
run: aio console:workspace:select ${{ secrets.WORKSPACEID }}
|
|
54
|
+
- name: "Create env file"
|
|
55
|
+
run: |
|
|
56
|
+
touch .env
|
|
57
|
+
echo API_ENDPOINT="https://xxx.execute-api.us-west-2.amazonaws.com" >> .env
|
|
58
|
+
echo API_KEY=${{ secrets.API_KEY }} >> .env
|
|
59
|
+
cat .env
|
|
60
|
+
- name: Describe
|
|
61
|
+
run: aio api-mesh:describe
|
|
62
|
+
- name: Update
|
|
63
|
+
run: aio api-mesh:update -c mesh.json --env .env
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
|
2
|
+
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
|
|
3
|
+
{
|
|
4
|
+
"name": "API Mesh Dev Container",
|
|
5
|
+
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bookworm",
|
|
6
|
+
"hostRequirements": {
|
|
7
|
+
"cpus": 2,
|
|
8
|
+
"memory": "8gb",
|
|
9
|
+
"storage": "32gb"
|
|
10
|
+
},
|
|
11
|
+
"forwardPorts": [5000],
|
|
12
|
+
"postAttachCommand": {
|
|
13
|
+
"server": "yarn start mesh.json"
|
|
14
|
+
},
|
|
15
|
+
"postCreateCommand": "yarn install && yarn devcontainer:setup",
|
|
16
|
+
"portsAttributes": {
|
|
17
|
+
"5000": {
|
|
18
|
+
"label": "Mesh GraphQL Server",
|
|
19
|
+
"onAutoForward": "openPreview"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"customizations": {
|
|
23
|
+
"codespaces": {
|
|
24
|
+
"openFiles": ["README.md", "mesh.json"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/templates/gitignore
CHANGED
|
@@ -42,7 +42,16 @@
|
|
|
42
42
|
"api-mesh"
|
|
43
43
|
],
|
|
44
44
|
"license": "Apache-2.0",
|
|
45
|
-
"scripts": {
|
|
45
|
+
"scripts": {
|
|
46
|
+
"start": "nodemon --watch $1 --watch .env -e js,json,yaml node_modules/.bin/aio api-mesh run $1",
|
|
47
|
+
"debug": "nodemon --watch $1 --watch .env -e js,json,yaml node_modules/.bin/aio api-mesh run $1 --debug",
|
|
48
|
+
"setupTelemetry": "echo {aio-cli-telemetry: {optOut: false}} > ~/.config/aio",
|
|
49
|
+
"devcontainer:setup": "yarn setupTelemetry & aio plugins:install @adobe/aio-cli-plugin-api-mesh"
|
|
50
|
+
},
|
|
46
51
|
"description": "API mesh starter template",
|
|
47
|
-
"author": "Adobe Inc."
|
|
52
|
+
"author": "Adobe Inc.",
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@adobe/aio-cli": "^10.0.0",
|
|
55
|
+
"nodemon": "^3.1.3"
|
|
56
|
+
}
|
|
48
57
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Adobe API Mesh Starter Kit
|
|
2
|
+
|
|
3
|
+
Bootstrap your Adobe API Mesh development with ease.
|
|
4
|
+
|
|
5
|
+
Simply use the template to create a new repo and get started with Github Codespaces to write, test and deploy from the browser.
|
|
6
|
+
|
|
7
|
+
This repo comes with all the files necessary to get started with API Mesh.
|
|
8
|
+
|
|
9
|
+
Check out the [documentation](https://developer.adobe.com/graphql-mesh-gateway/mesh/template) for further details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
COMMERCE_ENDPOINT=""
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"name": "Attach",
|
|
9
|
+
"port": 9229,
|
|
10
|
+
"request": "attach",
|
|
11
|
+
"skipFiles": ["<node_internals>/**"],
|
|
12
|
+
"type": "node"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
package/src/utils.js
CHANGED
|
@@ -308,61 +308,6 @@ function validateFileName(filesList) {
|
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
/**validates the environment file content
|
|
312
|
-
* @param {string} envContent
|
|
313
|
-
* @returns {object} containing the status of validation
|
|
314
|
-
* If validation is failed then the error property including the formatting errors is returned.
|
|
315
|
-
*/
|
|
316
|
-
function validateEnvFileFormat(envContent) {
|
|
317
|
-
//Key should start with a underscore or an alphabet followed by underscore/alphanumeric characters
|
|
318
|
-
const envKeyRegex = /^[a-zA-Z_]+[a-zA-Z0-9_]*$/;
|
|
319
|
-
|
|
320
|
-
const envValueRegex = /^(?:"(?:\\.|[^\\"])*"|'(?:\\.|[^\\'])*'|[^'"\s])+$/;
|
|
321
|
-
|
|
322
|
-
/*
|
|
323
|
-
The above regex matches one or more of below :
|
|
324
|
-
(?:"(?:\\.|[^\\"])*"|'(?:\\.|[^\\'])*'|[^'"\s])
|
|
325
|
-
which is
|
|
326
|
-
1. ?:"(?:\\.|[^\\"])*" : Non capturing group starts and ends with '"'
|
|
327
|
-
*/
|
|
328
|
-
const envDict = {};
|
|
329
|
-
const lines = envContent.split(/\r?\n/);
|
|
330
|
-
const errors = [];
|
|
331
|
-
|
|
332
|
-
for (let index = 0; index < lines.length; index++) {
|
|
333
|
-
const line = lines[index];
|
|
334
|
-
const trimmedLine = line.trim();
|
|
335
|
-
if (trimmedLine.startsWith('#') || trimmedLine === '') {
|
|
336
|
-
// ignore comment or empty lines
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (!trimmedLine.includes('=')) {
|
|
341
|
-
errors.push(`Invalid format << ${trimmedLine} >> on line ${index + 1}`);
|
|
342
|
-
} else {
|
|
343
|
-
const [key, value] = trimmedLine.split('=', 2);
|
|
344
|
-
if (!envKeyRegex.test(key) || !envValueRegex.test(value)) {
|
|
345
|
-
// invalid format: key or value does not match regex
|
|
346
|
-
errors.push(`Invalid format for key/value << ${trimmedLine} >> on line ${index + 1}`);
|
|
347
|
-
}
|
|
348
|
-
if (key in envDict) {
|
|
349
|
-
// duplicate key found
|
|
350
|
-
errors.push(`Duplicate key << ${key} >> on line ${index + 1}`);
|
|
351
|
-
}
|
|
352
|
-
envDict[key] = value;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
if (errors.length) {
|
|
356
|
-
return {
|
|
357
|
-
valid: false,
|
|
358
|
-
error: errors.toString(),
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
return {
|
|
362
|
-
valid: true,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
|
|
366
311
|
/**
|
|
367
312
|
* Read the environment file, checks for validation status and interpolate mesh
|
|
368
313
|
* @param {string} inputMeshData
|
|
@@ -375,10 +320,10 @@ async function validateAndInterpolateMesh(inputMeshData, envFilePath, command) {
|
|
|
375
320
|
const envFileContent = await readFileContents(envFilePath, command, 'env');
|
|
376
321
|
|
|
377
322
|
//Validate the environment file
|
|
378
|
-
|
|
379
|
-
if (envFileValidity.valid) {
|
|
323
|
+
try {
|
|
380
324
|
//load env file using dotenv and add 'env' as the root property in the object
|
|
381
|
-
const
|
|
325
|
+
const config = dotenv.parse(envFileContent);
|
|
326
|
+
const envObj = { env: config };
|
|
382
327
|
const { interpolationStatus, missingKeys, interpolatedMeshData } = await interpolateMesh(
|
|
383
328
|
inputMeshData,
|
|
384
329
|
envObj,
|
|
@@ -397,8 +342,8 @@ async function validateAndInterpolateMesh(inputMeshData, envFilePath, command) {
|
|
|
397
342
|
command.log(interpolatedMeshData);
|
|
398
343
|
command.error('Interpolated mesh is not a valid JSON. Please check the generated json file.');
|
|
399
344
|
}
|
|
400
|
-
}
|
|
401
|
-
command.error(`Issue in ${envFilePath} file - ` +
|
|
345
|
+
} catch (err) {
|
|
346
|
+
command.error(`Issue in ${envFilePath} file - ` + err.message);
|
|
402
347
|
}
|
|
403
348
|
}
|
|
404
349
|
|
|
@@ -540,7 +485,6 @@ module.exports = {
|
|
|
540
485
|
envFileFlag,
|
|
541
486
|
checkPlaceholders,
|
|
542
487
|
readFileContents,
|
|
543
|
-
validateEnvFileFormat,
|
|
544
488
|
validateAndInterpolateMesh,
|
|
545
489
|
getAppRootDir,
|
|
546
490
|
portNoFlag,
|