@@ -7,6 +7,50 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
88## [ Unreleased]
99
10+ ## [ 3.1.0] - 2026-02-21
11+
12+ ### Added
13+
14+ - ** SelectorBuilder Class with Interface** (SOSO-365)
15+ - ` SelectorBuilderInterface ` : Contract for selector building and value escaping
16+ - ` SelectorBuilder ` : Default implementation with 4 methods:
17+ - ` ensureFunction() ` : Wraps raw boolean expressions in ` Filter() ` for API compliance
18+ - ` escapeValue() ` : Escapes ` " ` and ` \ ` to prevent injection attacks
19+ - ` buildFilter() ` : Combines escaping with ` Filter() ` wrapping (convenience)
20+ - ` isSafeIdentifier() ` : Validates table/field names for safe characters
21+ - Comprehensive test suite with 40+ tests including injection attack prevention
22+ - Integrated from ` AppSheetFilterEscape ` utility in ` service_portfolio_mcp `
23+
24+ - ** DI-Compatible SelectorBuilder Injection (Option B)**
25+ - ` AppSheetClientFactory ` accepts optional ` SelectorBuilderInterface ` in constructor
26+ - ` AppSheetClient ` accepts optional ` SelectorBuilderInterface ` as 3rd constructor parameter
27+ - Enables custom builder injection via tsyringe or other DI frameworks
28+ - Enables AOP extensibility (e.g. ` @LogExecution ` via subclass)
29+ - Default behavior unchanged (falls back to ` new SelectorBuilder() ` )
30+ - ` AppSheetClientFactoryInterface.create() ` signature unchanged — no breaking change
31+
32+ - ** Bugfix Concept Document**
33+ - ` docs/SOSO-365/BUGFIX_CONCEPT.md ` with design decisions, DI compatibility, and AOP extensibility
34+
35+ ### Fixed
36+
37+ - ** Selector Wrapping** (SOSO-365): ` AppSheetClient.find() ` now automatically wraps raw
38+ boolean expressions in ` Filter(tableName, expression) ` as required by AppSheet API spec.
39+ Previously raw expressions like ` [Field] = "value" ` were sent without wrapper.
40+ Already-wrapped expressions (` Filter() ` , ` Select() ` , ` OrderBy() ` , ` Top() ` ) pass through
41+ unchanged (idempotent).
42+
43+ - ** Default Base URL** (SOSO-365): Changed from deprecated ` https://api.appsheet.com/api/v2 `
44+ to ` https://www.appsheet.com/api/v2 ` per current AppSheet API documentation.
45+ Regional endpoints (EU, Asia Pacific) continue to work via ` baseUrl ` override.
46+
47+ ### Technical Details
48+
49+ - ** Breaking Changes** : None
50+ - ** SemVer Level** : MINOR (new features + bug fixes, fully backward compatible)
51+ - ** Test Coverage** : 265 tests across 9 test suites
52+ - ** Jira** : [ SOSO-365] ( https://techdivision.atlassian.net/browse/SOSO-365 )
53+
1054## [ 3.0.0] - 2024-11-30
1155
1256### Added
@@ -81,6 +125,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
81125See [ CLAUDE.md] ( ./CLAUDE.md ) Breaking Changes section for detailed migration examples.
82126
83127** Quick Migration:**
128+
84129``` typescript
85130// Old (v2.x)
86131const client = new AppSheetClient ({ appId , applicationAccessKey , runAsUserEmail });
0 commit comments