@akanjs/devkit 3.0.0-beta.29 → 3.0.0-beta.30
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/akanConfig/akanConfig.test.ts +109 -92
- package/akanConfig/akanConfig.ts +183 -163
- package/akanConfig/types.ts +12 -6
- package/executors.test.ts +4 -3
- package/executors.ts +1 -1
- package/frontendBuild/ssrBaseArtifactBuilder.ts +5 -5
- package/mobile/desktopBin.test.ts +1 -1
- package/mobile/desktopServerStage.ts +4 -4
- package/mobile/mobileTarget.test.ts +10 -10
- package/mobile/mobileTarget.ts +17 -17
- package/mobile/nativeApp.test.ts +7 -7
- package/mobile/nativeApp.ts +11 -11
- package/mobile/nativeConfig.test.ts +47 -44
- package/mobile/nativeConfig.ts +29 -32
- package/mobile/nativeWebDir.test.ts +3 -3
- package/mobile/nativeWebDir.ts +4 -4
- package/package.json +2 -2
- package/workspaceLayout.test.ts +1 -1
- package/workspaceLayout.ts +2 -2
|
@@ -50,7 +50,7 @@ const loadExtAppConfig = async (tmpPrefix: string, appConfig: string, libConfig:
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
describe("AkanAppConfig", () => {
|
|
53
|
-
test("applies defaults for route domains, i18n, image,
|
|
53
|
+
test("applies defaults for route domains, i18n, image, native, and imports", () => {
|
|
54
54
|
const config = new AkanAppConfig(app, ["shared"], packageJson, {}, baseDevEnv);
|
|
55
55
|
|
|
56
56
|
expect([...config.domains].sort()).toEqual([
|
|
@@ -62,7 +62,7 @@ describe("AkanAppConfig", () => {
|
|
|
62
62
|
expect(config.i18n.defaultLocale).toBe("en");
|
|
63
63
|
expect(config.i18n.locales).toContain("en");
|
|
64
64
|
expect(config.images.formats).toEqual(["image/webp"]);
|
|
65
|
-
expect(config.
|
|
65
|
+
expect(config.native).toMatchObject({
|
|
66
66
|
appName: "portal",
|
|
67
67
|
appId: "com.akanjs.portal",
|
|
68
68
|
version: "0.0.1",
|
|
@@ -102,7 +102,7 @@ describe("AkanAppConfig", () => {
|
|
|
102
102
|
},
|
|
103
103
|
],
|
|
104
104
|
i18n: { locales: ["ko", "en"], defaultLocale: "ko" },
|
|
105
|
-
|
|
105
|
+
native: {
|
|
106
106
|
appName: "Portal App",
|
|
107
107
|
appId: "com.portal.mobile",
|
|
108
108
|
version: "1.2.3",
|
|
@@ -135,8 +135,8 @@ describe("AkanAppConfig", () => {
|
|
|
135
135
|
expect(config.i18n.defaultLocale).toBe("ko");
|
|
136
136
|
expect(config.images.qualities).toEqual([80, 90]);
|
|
137
137
|
expect(config.images.dangerouslyAllowSVG).toBe(true);
|
|
138
|
-
expect(config.
|
|
139
|
-
expect(config.
|
|
138
|
+
expect(config.native.buildNum).toBe(7);
|
|
139
|
+
expect(config.native.targets.default).toMatchObject({
|
|
140
140
|
name: "default",
|
|
141
141
|
appName: "Portal App",
|
|
142
142
|
appId: "com.portal.mobile",
|
|
@@ -241,10 +241,10 @@ describe("AkanAppConfig", () => {
|
|
|
241
241
|
expect(lines(new AkanAppConfig(app, [], packageJson, {}, baseDevEnv).dockerfile)).toEqual(lines(before.join("\n")));
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
-
test("refuses a csr-less build that ships a
|
|
244
|
+
test("refuses a csr-less build that ships a native app", () => {
|
|
245
245
|
expect(
|
|
246
|
-
() => new AkanAppConfig(app, [], packageJson, { web: { csr: false },
|
|
247
|
-
).toThrow("the
|
|
246
|
+
() => new AkanAppConfig(app, [], packageJson, { web: { csr: false }, native: { appName: "portal" } }, baseDevEnv),
|
|
247
|
+
).toThrow("the native apps ship that bundle");
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
test("installs only ca-certificates and tzdata in the default image", () => {
|
|
@@ -427,14 +427,14 @@ describe("AkanAppConfig", () => {
|
|
|
427
427
|
]);
|
|
428
428
|
});
|
|
429
429
|
|
|
430
|
-
test("normalizes
|
|
430
|
+
test("normalizes the native targets and validates base paths", () => {
|
|
431
431
|
const config = new AkanAppConfig(
|
|
432
432
|
app,
|
|
433
433
|
[],
|
|
434
434
|
packageJson,
|
|
435
435
|
{
|
|
436
436
|
routes: [{ basePath: "admin", domains: {} }],
|
|
437
|
-
|
|
437
|
+
native: {
|
|
438
438
|
appName: "Portal",
|
|
439
439
|
appId: "com.portal.app",
|
|
440
440
|
version: "1.0.0",
|
|
@@ -447,12 +447,9 @@ describe("AkanAppConfig", () => {
|
|
|
447
447
|
appId: "com.portal.admin",
|
|
448
448
|
buildNum: 8,
|
|
449
449
|
permissions: ["camera"],
|
|
450
|
-
deepLinks: {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
ios: { teamId: " TEAMID " },
|
|
454
|
-
android: { sha256CertFingerprints: ["AA:BB", "AA:BB"] },
|
|
455
|
-
},
|
|
450
|
+
deepLinks: { schemes: ["portal-admin", "portal-admin"], domains: ["https://Portal.Admin/"] },
|
|
451
|
+
ios: { teamId: " TEAMID " },
|
|
452
|
+
android: { sha256CertFingerprints: ["AA:BB", "AA:BB"] },
|
|
456
453
|
},
|
|
457
454
|
},
|
|
458
455
|
},
|
|
@@ -460,7 +457,7 @@ describe("AkanAppConfig", () => {
|
|
|
460
457
|
baseDevEnv,
|
|
461
458
|
);
|
|
462
459
|
|
|
463
|
-
expect(config.
|
|
460
|
+
expect(config.native.targets.admin).toMatchObject({
|
|
464
461
|
name: "admin",
|
|
465
462
|
basePath: "admin",
|
|
466
463
|
indexPath: "/admin/home",
|
|
@@ -469,46 +466,51 @@ describe("AkanAppConfig", () => {
|
|
|
469
466
|
version: "1.0.0",
|
|
470
467
|
buildNum: 8,
|
|
471
468
|
permissions: ["camera"],
|
|
472
|
-
deepLinks: {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
ios: { teamId: "TEAMID" },
|
|
476
|
-
android: { sha256CertFingerprints: ["AA:BB"] },
|
|
477
|
-
},
|
|
469
|
+
deepLinks: { schemes: ["portal-admin"], domains: ["portal.admin"] },
|
|
470
|
+
ios: { teamId: "TEAMID" },
|
|
471
|
+
android: { sha256CertFingerprints: ["AA:BB"] },
|
|
478
472
|
});
|
|
479
473
|
|
|
480
474
|
expect(
|
|
481
475
|
() =>
|
|
482
|
-
new AkanAppConfig(
|
|
483
|
-
app,
|
|
484
|
-
[],
|
|
485
|
-
packageJson,
|
|
486
|
-
{
|
|
487
|
-
mobile: { targets: { bad: { basePath: "missing" } } },
|
|
488
|
-
},
|
|
489
|
-
baseDevEnv,
|
|
490
|
-
),
|
|
476
|
+
new AkanAppConfig(app, [], packageJson, { native: { targets: { bad: { basePath: "missing" } } } }, baseDevEnv),
|
|
491
477
|
).toThrow("unknown basePath");
|
|
492
478
|
});
|
|
493
479
|
|
|
494
|
-
test("
|
|
480
|
+
test("an app without basePaths has one target, default, with no basePath and the section's settings", () => {
|
|
481
|
+
const config = new AkanAppConfig(
|
|
482
|
+
app,
|
|
483
|
+
[],
|
|
484
|
+
packageJson,
|
|
485
|
+
{ native: { indexPath: "/explore", desktop: { server: true } } },
|
|
486
|
+
baseDevEnv,
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
expect(Object.keys(config.native.targets)).toEqual(["default"]);
|
|
490
|
+
expect(config.native.targets.default.basePath).toBeUndefined();
|
|
491
|
+
expect(config.native.targets.default).toMatchObject({ indexPath: "/explore", desktop: { server: true } });
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
test("a target takes the native section with its own fields over it: objects merge, lists and values replace", () => {
|
|
495
495
|
const config = new AkanAppConfig(
|
|
496
496
|
app,
|
|
497
497
|
[],
|
|
498
498
|
packageJson,
|
|
499
499
|
{
|
|
500
|
-
|
|
500
|
+
native: {
|
|
501
501
|
fileName: "portal",
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
502
|
+
plugins: ["iap"],
|
|
503
|
+
ios: { infoPlist: { ITSAppUsesNonExemptEncryption: false }, files: { "sound.caf": "assets/sound.caf" } },
|
|
504
|
+
android: {
|
|
505
|
+
manifest: ["<queries/>"],
|
|
506
|
+
googleServices: "secrets/google-services.json",
|
|
507
|
+
files: { "res/raw/chime.mp3": "assets/chime.mp3" },
|
|
507
508
|
},
|
|
508
509
|
targets: {
|
|
509
510
|
default: {
|
|
510
|
-
|
|
511
|
-
|
|
511
|
+
plugins: ["share"],
|
|
512
|
+
ios: { files: { "extra.caf": "assets/extra.caf" } },
|
|
513
|
+
android: { manifest: ["<uses-feature/>"] },
|
|
512
514
|
},
|
|
513
515
|
},
|
|
514
516
|
},
|
|
@@ -516,44 +518,46 @@ describe("AkanAppConfig", () => {
|
|
|
516
518
|
baseDevEnv,
|
|
517
519
|
);
|
|
518
520
|
|
|
519
|
-
expect(config.
|
|
521
|
+
expect(config.native.targets.default).toMatchObject({
|
|
520
522
|
fileName: "portal",
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
523
|
+
plugins: ["share"],
|
|
524
|
+
ios: {
|
|
525
|
+
infoPlist: { ITSAppUsesNonExemptEncryption: false },
|
|
526
|
+
files: { "sound.caf": "assets/sound.caf", "extra.caf": "assets/extra.caf" },
|
|
527
|
+
},
|
|
528
|
+
android: {
|
|
529
|
+
manifest: ["<uses-feature/>"],
|
|
530
|
+
googleServices: "secrets/google-services.json",
|
|
531
|
+
files: { "res/raw/chime.mp3": "assets/chime.mp3" },
|
|
526
532
|
},
|
|
527
533
|
});
|
|
528
534
|
});
|
|
529
535
|
|
|
530
|
-
test("gives every target the
|
|
536
|
+
test("gives every target the section's updates, a target overriding a field", () => {
|
|
531
537
|
const updates = { url: "https://releases.example.com/portal", publicKey: "key=" };
|
|
532
538
|
const config = new AkanAppConfig(
|
|
533
539
|
app,
|
|
534
540
|
[],
|
|
535
541
|
packageJson,
|
|
536
|
-
{
|
|
537
|
-
mobile: {
|
|
538
|
-
updates,
|
|
539
|
-
targets: { default: {}, pilot: { updates: { channel: "pilot" } } },
|
|
540
|
-
},
|
|
541
|
-
},
|
|
542
|
+
{ native: { updates, targets: { default: {}, pilot: { updates: { channel: "pilot" } } } } },
|
|
542
543
|
baseDevEnv,
|
|
543
544
|
);
|
|
544
545
|
|
|
545
|
-
expect(config.
|
|
546
|
-
expect(config.
|
|
546
|
+
expect(config.native.targets.default.updates).toEqual(updates);
|
|
547
|
+
expect(config.native.targets.pilot.updates).toEqual({ ...updates, channel: "pilot" });
|
|
547
548
|
expect(
|
|
548
549
|
() =>
|
|
549
550
|
new AkanAppConfig(
|
|
550
551
|
app,
|
|
551
552
|
[],
|
|
552
553
|
packageJson,
|
|
553
|
-
{
|
|
554
|
+
{ native: { targets: { pilot: { updates: { channel: "pilot" } } } } },
|
|
554
555
|
baseDevEnv,
|
|
555
556
|
),
|
|
556
|
-
).toThrow("
|
|
557
|
+
).toThrow("native.targets.pilot.updates in apps/portal/akan.config.ts has no url or publicKey");
|
|
558
|
+
expect(
|
|
559
|
+
() => new AkanAppConfig(app, [], packageJson, { native: { updates: { channel: "pilot" } } }, baseDevEnv),
|
|
560
|
+
).toThrow("native.updates in apps/portal/akan.config.ts has no url or publicKey.");
|
|
557
561
|
});
|
|
558
562
|
|
|
559
563
|
test("merges the desktop settings field by field, the target winning", () => {
|
|
@@ -562,80 +566,93 @@ describe("AkanAppConfig", () => {
|
|
|
562
566
|
[],
|
|
563
567
|
packageJson,
|
|
564
568
|
{
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
targets: { default: {
|
|
569
|
+
native: {
|
|
570
|
+
desktop: { recovery: "reload", window: { fullscreen: true } },
|
|
571
|
+
targets: { default: { desktop: { window: { skipTaskbar: true } } } },
|
|
568
572
|
},
|
|
569
573
|
},
|
|
570
574
|
baseDevEnv,
|
|
571
575
|
);
|
|
572
576
|
|
|
573
|
-
expect(config.
|
|
577
|
+
expect(config.native.targets.default.desktop).toEqual({
|
|
574
578
|
recovery: "reload",
|
|
575
579
|
window: { fullscreen: true, skipTaskbar: true },
|
|
576
580
|
});
|
|
577
581
|
});
|
|
578
582
|
|
|
579
|
-
test("merges the
|
|
583
|
+
test("merges the section's push and privacy into each target field by field; an icon object is one value", () => {
|
|
580
584
|
const publicKey = Buffer.alloc(32, 7).toString("base64");
|
|
581
585
|
const config = new AkanAppConfig(
|
|
582
586
|
app,
|
|
583
587
|
[],
|
|
584
588
|
packageJson,
|
|
585
589
|
{
|
|
586
|
-
|
|
590
|
+
native: {
|
|
587
591
|
updates: { url: "https://updates.example.com/portal", publicKey },
|
|
588
|
-
|
|
592
|
+
icon: { image: "assets/icon.png", backgroundColor: "#000000" },
|
|
593
|
+
android: { push: { color: "#ff5a5f" } },
|
|
594
|
+
ios: { privacy: { tracking: false } },
|
|
589
595
|
targets: {
|
|
590
596
|
default: {},
|
|
591
597
|
beta: {
|
|
592
598
|
updates: { channel: "beta" },
|
|
593
|
-
|
|
599
|
+
icon: { image: "assets/beta.png" },
|
|
600
|
+
android: { push: { smallIcon: "assets/noti.png" } },
|
|
594
601
|
},
|
|
595
602
|
},
|
|
596
603
|
},
|
|
597
|
-
}
|
|
604
|
+
},
|
|
598
605
|
baseDevEnv,
|
|
599
606
|
);
|
|
600
607
|
|
|
601
|
-
expect(config.
|
|
602
|
-
expect(config.
|
|
608
|
+
expect(config.native.targets.default.updates).toEqual({ url: "https://updates.example.com/portal", publicKey });
|
|
609
|
+
expect(config.native.targets.beta).toMatchObject({
|
|
603
610
|
updates: { url: "https://updates.example.com/portal", publicKey, channel: "beta" },
|
|
604
|
-
|
|
611
|
+
android: { push: { color: "#ff5a5f", smallIcon: "assets/noti.png" } },
|
|
612
|
+
ios: { privacy: { tracking: false } },
|
|
605
613
|
});
|
|
614
|
+
expect(config.native.targets.beta.icon).toEqual({ image: "assets/beta.png" });
|
|
606
615
|
});
|
|
607
616
|
|
|
608
|
-
test("refuses
|
|
609
|
-
const make = (
|
|
610
|
-
new AkanAppConfig(app, [], packageJson,
|
|
617
|
+
test("refuses `mobile` and every setting that moved, naming where it went", () => {
|
|
618
|
+
const make = (config: Record<string, unknown>) => () =>
|
|
619
|
+
new AkanAppConfig(app, [], packageJson, config as never, baseDevEnv);
|
|
611
620
|
|
|
612
|
-
expect(make({
|
|
613
|
-
|
|
621
|
+
expect(make({ mobile: { appName: "portal" } })).toThrow("declares `mobile`, which is now `native`");
|
|
622
|
+
expect(make({ native: { assets: { icon: "assets/icon.png" } } })).toThrow(
|
|
623
|
+
"native.assets in apps/portal/akan.config.ts has moved: icon and splash sit directly in the native section.",
|
|
624
|
+
);
|
|
625
|
+
expect(make({ native: { targets: { default: { native: { desktop: { server: true } } } } } })).toThrow(
|
|
626
|
+
"native.targets.default.native in apps/portal/akan.config.ts has moved",
|
|
627
|
+
);
|
|
628
|
+
expect(make({ native: { files: { "ios/sound.caf": "assets/sound.caf" } } })).toThrow(
|
|
629
|
+
"native.files in apps/portal/akan.config.ts has moved: ios.files",
|
|
630
|
+
);
|
|
631
|
+
expect(make({ native: { deepLinks: { ios: { teamId: "TEAMID" } } } })).toThrow(
|
|
632
|
+
"native.deepLinks.ios in apps/portal/akan.config.ts has moved: ios.teamId.",
|
|
614
633
|
);
|
|
615
|
-
expect(make({
|
|
616
|
-
|
|
634
|
+
expect(make({ native: { android: { files: { "App/x.json": "x.json" } } } })).toThrow(
|
|
635
|
+
'native.android.files["App/x.json"] in apps/portal/akan.config.ts must land at res/<type>/<file> or assets/<path>.',
|
|
617
636
|
);
|
|
618
|
-
expect(make({ targets: {
|
|
619
|
-
"
|
|
637
|
+
expect(make({ native: { targets: { kiosk: { ios: { files: { "../x.caf": "x.caf" } } } } } })).toThrow(
|
|
638
|
+
'native.targets.kiosk.ios.files["../x.caf"] in apps/portal/akan.config.ts must land at <path in the app bundle>.',
|
|
620
639
|
);
|
|
621
|
-
expect(make({
|
|
622
|
-
"
|
|
640
|
+
expect(make({ native: { ios: { scheme: "App" } } })).toThrow(
|
|
641
|
+
"native.ios.scheme in apps/portal/akan.config.ts is not a native setting",
|
|
623
642
|
);
|
|
624
|
-
expect(make({ server: { url: "http://x" } })).toThrow(
|
|
625
|
-
"
|
|
643
|
+
expect(make({ native: { server: { url: "http://x" } } })).toThrow(
|
|
644
|
+
"native.server in apps/portal/akan.config.ts is not a native setting",
|
|
626
645
|
);
|
|
627
646
|
});
|
|
628
647
|
|
|
629
|
-
test("derives a repo-scoped default appId and records explicit
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
expect(
|
|
633
|
-
expect(withoutMobile.hasMobileConfig).toBe(false);
|
|
648
|
+
test("derives a repo-scoped default appId and records an explicit native section", () => {
|
|
649
|
+
const withoutNative = new AkanAppConfig(app, [], packageJson, {}, baseDevEnv);
|
|
650
|
+
expect(withoutNative.native.appId).toBe("com.akanjs.portal");
|
|
651
|
+
expect(withoutNative.hasNativeConfig).toBe(false);
|
|
634
652
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
expect(
|
|
638
|
-
expect(withMobile.hasMobileConfig).toBe(true);
|
|
653
|
+
const withNative = new AkanAppConfig(app, [], packageJson, { native: { version: "2.0.0" } }, baseDevEnv);
|
|
654
|
+
expect(withNative.native.appId).toBe("com.akanjs.portal");
|
|
655
|
+
expect(withNative.hasNativeConfig).toBe(true);
|
|
639
656
|
});
|
|
640
657
|
});
|
|
641
658
|
|