@africode/core 5.0.4 → 5.0.6
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/AGENTS.md +583 -0
- package/AGENT_INSTRUCTIONS.md +595 -0
- package/COMPONENT_SCHEMA.json +990 -836
- package/README.md +32 -0
- package/components/index.js +14 -0
- package/components/ui-badge.js +61 -0
- package/components/ui-button.js +149 -0
- package/components/ui-card.js +75 -0
- package/components/ui-input.js +110 -0
- package/components/ui-switch.js +85 -0
- package/core/cli/commands/build.js +31 -1
- package/core/cli/commands/dev.js +38 -1
- package/core/lipa-namba-journey.js +28 -6
- package/dist/africode.js +672 -422
- package/dist/africode.js.map +9 -4
- package/dist/build-info.json +3 -3
- package/dist/components.js +554 -304
- package/dist/components.js.map +9 -4
- package/package.json +3 -1
- package/templates/starter-tailwind/src/pages/index.js +30 -0
- package/templates/starter-tailwind/tailwind.config.cjs +18 -0
|
@@ -134,6 +134,22 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
134
134
|
|
|
135
135
|
const validated = schema.parse(request);
|
|
136
136
|
|
|
137
|
+
// Deduplicate by reference when provided: return existing session if found
|
|
138
|
+
if (validated.reference) {
|
|
139
|
+
for (const session of this.sessions.values()) {
|
|
140
|
+
if (session.reference === validated.reference) {
|
|
141
|
+
return {
|
|
142
|
+
ok: true,
|
|
143
|
+
paymentRequestId: session.id,
|
|
144
|
+
sessionData: session,
|
|
145
|
+
message: 'DUPLICATE_REFERENCE',
|
|
146
|
+
nextStep: session.status === 'INITIATED' ? 'IDENTIFY_CUSTOMER' : undefined,
|
|
147
|
+
expiresIn: Math.max(0, Math.floor((new Date(session.expiresAt) - Date.now()) / 1000))
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
137
153
|
// Verify merchant is registered and compliant
|
|
138
154
|
const merchantStatus = await this._verifyMerchantCompliance(validated.merchantId);
|
|
139
155
|
if (!merchantStatus.ok) {
|
|
@@ -400,7 +416,7 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
400
416
|
try {
|
|
401
417
|
// Step 1: Initiate
|
|
402
418
|
const init = await this.initiatePayment(request);
|
|
403
|
-
if (!init.ok) return init;
|
|
419
|
+
if (!init.ok) return { ok: false, error: init.error || 'INITIATION_FAILED', completedSteps: steps };
|
|
404
420
|
steps.push({ step: 'INITIATE', ok: true });
|
|
405
421
|
|
|
406
422
|
// Step 2: Identify
|
|
@@ -409,7 +425,7 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
409
425
|
credentials.nin,
|
|
410
426
|
credentials.pin
|
|
411
427
|
);
|
|
412
|
-
if (!identify.ok) return identify;
|
|
428
|
+
if (!identify.ok) return { ok: false, error: identify.error || 'IDENTIFICATION_FAILED', completedSteps: steps };
|
|
413
429
|
steps.push({ step: 'IDENTIFY', ok: true });
|
|
414
430
|
|
|
415
431
|
// Step 3: AML Screen
|
|
@@ -417,7 +433,7 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
417
433
|
init.paymentRequestId,
|
|
418
434
|
identify.customerId
|
|
419
435
|
);
|
|
420
|
-
if (!aml.ok) return aml;
|
|
436
|
+
if (!aml.ok) return { ok: false, error: aml.error || 'AML_SCREEN_FAILED', completedSteps: steps };
|
|
421
437
|
steps.push({ step: 'AML_SCREEN', ok: true });
|
|
422
438
|
|
|
423
439
|
// Step 4: Confirm
|
|
@@ -426,7 +442,7 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
426
442
|
identify.customerId,
|
|
427
443
|
confirmation.code
|
|
428
444
|
);
|
|
429
|
-
if (!confirm.ok) return confirm;
|
|
445
|
+
if (!confirm.ok) return { ok: false, error: confirm.error || 'CONFIRMATION_FAILED', completedSteps: steps };
|
|
430
446
|
steps.push({ step: 'CONFIRM', ok: true });
|
|
431
447
|
|
|
432
448
|
// Step 5: Process
|
|
@@ -434,7 +450,7 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
434
450
|
init.paymentRequestId,
|
|
435
451
|
identify.customerId
|
|
436
452
|
);
|
|
437
|
-
if (!process.ok) return process;
|
|
453
|
+
if (!process.ok) return { ok: false, error: process.error || 'PROCESSING_FAILED', completedSteps: steps };
|
|
438
454
|
steps.push({ step: 'PROCESS', ok: true });
|
|
439
455
|
|
|
440
456
|
return {
|
|
@@ -525,7 +541,13 @@ export class LipaNambaJourney extends EventEmitter {
|
|
|
525
541
|
|
|
526
542
|
async _verifyNIDA(nin, pin) {
|
|
527
543
|
// Implementation calls NIDA CIG
|
|
528
|
-
// For now,
|
|
544
|
+
// For now, provide a deterministic mock: valid NIN is 20 digits
|
|
545
|
+
const ninPattern = /^[0-9]{20}$/;
|
|
546
|
+
if (!nin || !ninPattern.test(nin)) {
|
|
547
|
+
return { verified: false, nin };
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Simulate successful lookup
|
|
529
551
|
return { verified: true, nin, firstName: 'John', lastName: 'Doe' };
|
|
530
552
|
}
|
|
531
553
|
|