Skip to content

Commit b245d3c

Browse files
authored
Merge pull request #1130 from nxext/cap-plugin
Feature: Add Capacitor Crystal Plugin
2 parents 32a4fc9 + a22caa8 commit b245d3c

File tree

7 files changed

+138
-121
lines changed

7 files changed

+138
-121
lines changed

e2e/capacitor-e2e/tests/capacitor.spec.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('capacitor-project e2e', () => {
1515
`generate @nx/web:application ${appDir} --style=css --bundler=vite --e2eTestRunner=none --linter=none --skipFormat=true`
1616
);
1717
await runNxCommandAsync(
18-
`generate @nxext/capacitor:configuration --project=${app} --appName=test --appId=test --skipFormat=true`
18+
`generate @nxext/capacitor:configuration --project=${app} --appName=test --appId=test.example.app --skipFormat=true`
1919
);
2020
});
2121

@@ -55,4 +55,28 @@ describe('capacitor-project e2e', () => {
5555
);
5656
expect(capHelpResults.stdout).toContain('Usage: cap');
5757
});
58+
59+
it('should add android platform', async () => {
60+
const capResults = await runNxCommandAsync(`run ${app}:add:android`);
61+
expect(stripAnsi(capResults.stdout)).toContain(
62+
'[success] android platform added!'
63+
);
64+
});
65+
66+
it('should sync android platform', async () => {
67+
const capResults = await runNxCommandAsync(`run ${app}:sync:android`);
68+
expect(stripAnsi(capResults.stdout)).toContain('✔ update android');
69+
});
70+
71+
it('should add ios platform', async () => {
72+
const capResults = await runNxCommandAsync(`run ${app}:add:ios`);
73+
expect(stripAnsi(capResults.stdout)).toContain(
74+
'[success] ios platform added!'
75+
);
76+
});
77+
78+
it('should sync ios platform', async () => {
79+
const capResults = await runNxCommandAsync(`run ${app}:sync:ios`);
80+
expect(stripAnsi(capResults.stdout)).toContain('✔ update ios');
81+
});
5882
});

e2e/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function createTestProject() {
2222
});
2323

2424
execSync(
25-
`npx --yes create-nx-workspace@19 ${projectName} --preset apps --nxCloud skip --interactive false --packageManager pnpm`,
25+
`npx --yes create-nx-workspace@latest ${projectName} --preset apps --nxCloud skip --interactive false --packageManager pnpm`,
2626
{
2727
cwd: dirname(projectDirectory),
2828
stdio: 'inherit',

packages/capacitor/package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
"directory": "packages/capacitor"
1010
},
1111
"license": "MIT",
12-
"main": "src/index.js",
12+
"exports": {
13+
".": "./src/index.js",
14+
"./package.json": "./package.json",
15+
"./plugin": "./src/plugins/plugin.js"
16+
},
1317
"generators": "./generators.json",
1418
"executors": "./executors.json",
1519
"nx-migrations": {
@@ -19,7 +23,8 @@
1923
"builders": "./executors.json",
2024
"dependencies": {
2125
"ignore": "^5.3.1",
22-
"tslib": "^2.3.0"
26+
"tslib": "^2.3.0",
27+
"@nxext/common": "20.0.1"
2328
},
2429
"peerDependencies": {
2530
"@nx/devkit": "^20.0.0",

packages/capacitor/src/generators/configuration/generator.spec.ts

Lines changed: 4 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
addProjectConfiguration,
33
normalizePath,
44
readJson,
5+
readNxJson,
56
readProjectConfiguration,
67
Tree,
78
writeJson,
@@ -90,84 +91,10 @@ describe('capacitor-project', () => {
9091
);
9192
});
9293

93-
it('should update workspace.json', async () => {
94+
it('should update nx.json', async () => {
9495
await generator(appTree, options);
95-
const projectConfiguration = readProjectConfiguration(
96-
appTree,
97-
options.project
98-
);
99-
100-
expect(projectConfiguration.targets.cap.executor).toEqual(
101-
'@nxext/capacitor:cap'
102-
);
103-
expect(projectConfiguration.targets.cap.options).toEqual({
104-
cmd: '--help',
105-
});
106-
107-
expect(projectConfiguration.targets.add.executor).toEqual(
108-
'@nxext/capacitor:cap'
109-
);
110-
expect(projectConfiguration.targets.add.options).toEqual({
111-
cmd: 'add',
112-
});
113-
expect(
114-
projectConfiguration.targets.add.configurations['ios'].cmd
115-
).toEqual('add ios');
116-
expect(
117-
projectConfiguration.targets.add.configurations['android'].cmd
118-
).toEqual('add android');
119-
120-
expect(projectConfiguration.targets.copy.executor).toEqual(
121-
'@nxext/capacitor:cap'
122-
);
123-
expect(projectConfiguration.targets.copy.options).toEqual({
124-
cmd: 'copy',
125-
});
126-
expect(
127-
projectConfiguration.targets.copy.configurations['ios'].cmd
128-
).toEqual('copy ios');
129-
expect(
130-
projectConfiguration.targets.copy.configurations['android'].cmd
131-
).toEqual('copy android');
132-
133-
expect(projectConfiguration.targets.open.executor).toEqual(
134-
'@nxext/capacitor:cap'
135-
);
136-
expect(projectConfiguration.targets.open.options).toEqual({
137-
cmd: 'open',
138-
});
139-
expect(
140-
projectConfiguration.targets.open.configurations['ios'].cmd
141-
).toEqual('open ios');
142-
expect(
143-
projectConfiguration.targets.open.configurations['android'].cmd
144-
).toEqual('open android');
145-
146-
expect(projectConfiguration.targets.sync.executor).toEqual(
147-
'@nxext/capacitor:cap'
148-
);
149-
expect(projectConfiguration.targets.sync.options).toEqual({
150-
cmd: 'sync',
151-
});
152-
expect(
153-
projectConfiguration.targets.sync.configurations['ios'].cmd
154-
).toEqual('sync ios');
155-
expect(
156-
projectConfiguration.targets.sync.configurations['android'].cmd
157-
).toEqual('sync android');
158-
159-
expect(projectConfiguration.targets.update.executor).toEqual(
160-
'@nxext/capacitor:cap'
161-
);
162-
expect(projectConfiguration.targets.update.options).toEqual({
163-
cmd: 'update',
164-
});
165-
expect(
166-
projectConfiguration.targets.update.configurations['ios'].cmd
167-
).toEqual('update ios');
168-
expect(
169-
projectConfiguration.targets.update.configurations['android'].cmd
170-
).toEqual('update android');
96+
const nxJson = readNxJson(appTree);
97+
expect(nxJson.plugins).toContain('@nxext/capacitor/plugin');
17198
});
17299

173100
it('should not remove existing target configurations', async () => {

packages/capacitor/src/generators/configuration/generator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { convertNxGenerator, formatFiles, Tree } from '@nx/devkit';
22
import { addCapacitorConfig } from './lib/add-capacitor-config';
33
import { addDependencies } from './lib/add-dependencies';
4-
import { addProject } from './lib/add-project';
54
import { normalizeOptions } from './lib/normalize-options';
65
import { updateProjectGitignore } from './lib/update-project-gitignore';
76
import { updateProjectPackageJson } from './lib/update-project-package-json';
87
import { CapacitorConfigurationSchema } from './schema';
98
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
9+
import { addPluginToNxJson } from '@nxext/common';
1010

1111
export async function capacitorConfigurationGenerator(
1212
host: Tree,
@@ -18,8 +18,8 @@ export async function capacitorConfigurationGenerator(
1818
const installTask = addDependencies(host);
1919
addCapacitorConfig(host, normalizedOptions);
2020
updateProjectGitignore(host, normalizedOptions);
21-
addProject(host, normalizedOptions);
2221
updateProjectPackageJson(host, normalizedOptions);
22+
addPluginToNxJson('@nxext/capacitor/plugin', host);
2323

2424
if (!options.skipFormat) {
2525
await formatFiles(host);

packages/capacitor/src/generators/configuration/lib/add-project.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import {
2+
CreateNodesV2,
3+
ProjectConfiguration,
4+
TargetConfiguration,
5+
} from '@nx/devkit';
6+
import { existsSync } from 'node:fs';
7+
import { dirname, join } from 'node:path';
8+
9+
export interface CapacitorPluginOptions {}
10+
11+
export type CapCommand = 'add' | 'copy' | 'open' | 'run' | 'sync' | 'update';
12+
export type CapPlatform = 'ios' | 'android';
13+
export type CapCommandFormat =
14+
| `cap ${CapCommand}`
15+
| `cap ${CapCommand} ${CapPlatform}`;
16+
17+
export const createNodesV2: CreateNodesV2<CapacitorPluginOptions> = [
18+
'**/capacitor.config.ts',
19+
(configFiles) => {
20+
return configFiles.map((configFile) => {
21+
const projectRoot = dirname(configFile);
22+
23+
const isProject =
24+
existsSync(join(projectRoot, 'project.json')) ||
25+
existsSync(join(projectRoot, 'package.json'));
26+
if (!isProject) {
27+
return null;
28+
}
29+
30+
return [
31+
projectRoot,
32+
{
33+
projects: {
34+
[projectRoot]: {
35+
projectType: 'application',
36+
targets: buildTargets(projectRoot),
37+
},
38+
},
39+
},
40+
];
41+
});
42+
},
43+
];
44+
45+
function buildTargets(projectRoot: string): ProjectConfiguration['targets'] {
46+
const commands: CapCommand[] = [
47+
'add',
48+
'copy',
49+
'open',
50+
'run',
51+
'sync',
52+
'update',
53+
];
54+
const platforms: CapPlatform[] = ['ios', 'android'];
55+
56+
const baseTargetOptions: TargetConfiguration<any> = {
57+
options: {
58+
cwd: projectRoot,
59+
},
60+
cache: false,
61+
metadata: {
62+
technologies: ['capacitor'],
63+
},
64+
};
65+
66+
const targets: ProjectConfiguration['targets'] = {
67+
cap: {
68+
command: 'cap --help',
69+
...baseTargetOptions,
70+
},
71+
};
72+
73+
const formatCapCommand = (
74+
command: CapCommand,
75+
platform?: CapPlatform
76+
): CapCommandFormat => {
77+
if (platform) {
78+
return `cap ${command} ${platform}`;
79+
}
80+
81+
return `cap ${command}`;
82+
};
83+
84+
for (const command of commands) {
85+
targets[command] = {
86+
command: formatCapCommand(command),
87+
...baseTargetOptions,
88+
};
89+
90+
for (const platform of platforms) {
91+
targets[command].configurations ??= {};
92+
targets[command].configurations[platform] = {
93+
command: formatCapCommand(command, platform),
94+
};
95+
}
96+
}
97+
98+
return targets;
99+
}

0 commit comments

Comments
 (0)